diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
index 9df052dc..dac17214 100644
--- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
+++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
@@ -286,7 +286,7 @@
-
+
diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs
index 6f6bc7fe..653c7fab 100644
--- a/FFXIVClassic Map Server/PacketProcessor.cs
+++ b/FFXIVClassic Map Server/PacketProcessor.cs
@@ -111,7 +111,8 @@ namespace FFXIVClassic_Map_Server
return; ;
}
- session.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(session.id, session.id, chatMessage.logType, session.GetActor().customDisplayName, chatMessage.message), false);
+ if (chatMessage.logType == SendMessagePacket.MESSAGE_TYPE_SAY || chatMessage.logType == SendMessagePacket.MESSAGE_TYPE_SHOUT)
+ session.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(session.id, session.id, chatMessage.logType, session.GetActor().customDisplayName, chatMessage.message), false);
break;
//Langauge Code (Client safe to send packets to now)
diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs
index edc2042b..39912ab0 100644
--- a/FFXIVClassic Map Server/WorldManager.cs
+++ b/FFXIVClassic Map Server/WorldManager.cs
@@ -748,6 +748,23 @@ namespace FFXIVClassic_Map_Server
currentPlayerParties.Remove(party.groupIndex);
}
+ public void CreateInvitePartyGroup(Player player, string name)
+ {
+ SubPacket invitePacket = PartyInvitePacket.BuildPacket(player.playerSession, name);
+ player.QueuePacket(invitePacket);
+ }
+ public void CreateInvitePartyGroup(Player player, uint actorId)
+ {
+ SubPacket invitePacket = PartyInvitePacket.BuildPacket(player.playerSession, actorId);
+ player.QueuePacket(invitePacket);
+ }
+
+ public void GroupInviteResult(Player player, uint groupType, uint result)
+ {
+ SubPacket groupInviteResultPacket = GroupInviteResultPacket.BuildPacket(player.playerSession, groupType, result);
+ player.QueuePacket(groupInviteResultPacket);
+ }
+
public Player GetPCInWorld(string name)
{
foreach (Zone zone in zoneList.Values)
diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs
index f39b87b5..069c0904 100644
--- a/FFXIVClassic Map Server/actors/chara/player/Player.cs
+++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs
@@ -608,14 +608,15 @@ namespace FFXIVClassic_Map_Server.Actors
public void BroadcastPacket(SubPacket packet, bool sendToSelf)
{
- if (sendToSelf)
- QueuePacket(packet);
-
foreach (Actor a in playerSession.actorInstanceList)
{
if (a is Player)
{
- Player p = (Player)a;
+ Player p = (Player)a;
+
+ if (p.Equals(this) && !sendToSelf)
+ continue;
+
SubPacket clonedPacket = new SubPacket(packet, a.actorId);
p.QueuePacket(clonedPacket);
}
diff --git a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/PartyInviteResultPacket.cs b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/GroupInviteResultPacket.cs
similarity index 87%
rename from FFXIVClassic Map Server/packets/WorldPackets/Send/Group/PartyInviteResultPacket.cs
rename to FFXIVClassic Map Server/packets/WorldPackets/Send/Group/GroupInviteResultPacket.cs
index 6fc17074..a753bc9c 100644
--- a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/PartyInviteResultPacket.cs
+++ b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/GroupInviteResultPacket.cs
@@ -9,18 +9,19 @@ using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{
- class PartyInviteResultPacket
+ class GroupInviteResultPacket
{
public const ushort OPCODE = 0x1023;
public const uint PACKET_SIZE = 0x28;
- public static SubPacket BuildPacket(Session session, uint result)
+ public static SubPacket BuildPacket(Session session, uint groupType, uint result)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
+ binWriter.Write((UInt32)groupType);
binWriter.Write((UInt32)result);
}
}
diff --git a/FFXIVClassic World Server/DataObjects/Group/Group.cs b/FFXIVClassic World Server/DataObjects/Group/Group.cs
index a20b37d7..02a97553 100644
--- a/FFXIVClassic World Server/DataObjects/Group/Group.cs
+++ b/FFXIVClassic World Server/DataObjects/Group/Group.cs
@@ -48,6 +48,17 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
return new List();
}
+ public void SendGroupPacketsAll(params uint[] sessionIds)
+ {
+ for (int i = 0; i < sessionIds.Length; i++)
+ {
+ Session session = Server.GetServer().GetSession(sessionIds[i]);
+
+ if (session != null)
+ SendGroupPackets(session);
+ }
+ }
+
public void SendGroupPacketsAll(List sessionIds)
{
for (int i = 0; i < sessionIds.Count; i++)
@@ -59,6 +70,28 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
}
}
+ public void SendDeletePackets(params uint[] sessionIds)
+ {
+ for (int i = 0; i < sessionIds.Length; i++)
+ {
+ Session session = Server.GetServer().GetSession(sessionIds[i]);
+
+ if (session != null)
+ SendDeletePacket(session);
+ }
+ }
+
+ public void SendDeletePackets(List sessionIds)
+ {
+ for (int i = 0; i < sessionIds.Count; i++)
+ {
+ Session session = Server.GetServer().GetSession(sessionIds[i]);
+
+ if (session != null)
+ SendDeletePacket(session);
+ }
+ }
+
public void SendGroupPackets(Session session)
{
ulong time = Utils.MilisUnixTimeStampUTC();
@@ -87,6 +120,11 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
}
+ public void SendDeletePacket(Session session)
+ {
+ session.clientConnection.QueuePacket(DeleteGroupPacket.buildPacket(session.sessionId, this), true, false);
+ }
+
public virtual void SendInitWorkValues(Session session)
{
diff --git a/FFXIVClassic World Server/DataObjects/Group/Party.cs b/FFXIVClassic World Server/DataObjects/Group/Party.cs
index 1286d693..7fc1a9eb 100644
--- a/FFXIVClassic World Server/DataObjects/Group/Party.cs
+++ b/FFXIVClassic World Server/DataObjects/Group/Party.cs
@@ -252,6 +252,18 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
}
return groupMembers;
}
-
+
+ public void OnPlayerJoin(Session inviteeSession)
+ {
+ for (int i = 0; i < members.Count; i++)
+ {
+ Session session = Server.GetServer().GetSession(members[i]);
+ if (session == null)
+ continue;
+
+ session.SendGameMessage(30427, 0x20, (Object)Server.GetServer().GetNameForId(inviteeSession.sessionId));
+ }
+ }
+
}
}
diff --git a/FFXIVClassic World Server/FFXIVClassic World Server.csproj b/FFXIVClassic World Server/FFXIVClassic World Server.csproj
index 5e6868d3..f491b4b8 100644
--- a/FFXIVClassic World Server/FFXIVClassic World Server.csproj
+++ b/FFXIVClassic World Server/FFXIVClassic World Server.csproj
@@ -90,6 +90,8 @@
+
+
@@ -108,7 +110,7 @@
-
+
diff --git a/FFXIVClassic World Server/PacketProcessor.cs b/FFXIVClassic World Server/PacketProcessor.cs
index bf11afa1..95e27eea 100644
--- a/FFXIVClassic World Server/PacketProcessor.cs
+++ b/FFXIVClassic World Server/PacketProcessor.cs
@@ -1,9 +1,11 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.DataObjects;
+using FFXIVClassic_World_Server.DataObjects.Group;
using FFXIVClassic_World_Server.Packets.Receive;
using FFXIVClassic_World_Server.Packets.Receive.Subpackets;
using FFXIVClassic_World_Server.Packets.Send;
using FFXIVClassic_World_Server.Packets.Send.Login;
+using FFXIVClassic_World_Server.Packets.Send.Subpackets;
using FFXIVClassic_World_Server.Packets.WorldPackets.Receive;
using FFXIVClassic_World_Server.Packets.WorldPackets.Send;
using System;
@@ -151,6 +153,19 @@ namespace FFXIVClassic_World_Server
{
switch (subpacket.gameMessage.opcode)
{
+ case 0x00C9:
+ subpacket.DebugPrintSubPacket();
+ PartyChatMessagePacket partyChatMessagePacket = new PartyChatMessagePacket(subpacket.data);
+ Party playerParty = mServer.GetWorldManager().GetPartyManager().GetParty(session.sessionId);
+ for (int i = 0; i < playerParty.members.Count; i++)
+ {
+ Session thatSession = mServer.GetSession(playerParty.members[i]);
+ if (thatSession != null && !session.Equals(thatSession))
+ {
+ thatSession.clientConnection.QueuePacket(SendMessagePacket.BuildPacket(session.sessionId, thatSession.sessionId, SendMessagePacket.MESSAGE_TYPE_PARTY, mServer.GetNameForId(session.sessionId), partyChatMessagePacket.message), true, false);
+ }
+ }
+ break;
case 0x6:
mServer.GetWorldManager().DoLogin(session);
break;
diff --git a/FFXIVClassic World Server/Packets/Receive/Subpackets/ChatMessagePacket.cs b/FFXIVClassic World Server/Packets/Receive/Subpackets/ChatMessagePacket.cs
new file mode 100644
index 00000000..ad94cc71
--- /dev/null
+++ b/FFXIVClassic World Server/Packets/Receive/Subpackets/ChatMessagePacket.cs
@@ -0,0 +1,42 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace FFXIVClassic_World_Server.Packets.Receive.Subpackets
+{
+ class ChatMessagePacket
+ {
+ public float posX;
+ public float posY;
+ public float posZ;
+ public float posRot;
+
+ public uint logType;
+
+ public string message;
+
+ public bool invalidPacket = false;
+
+ public ChatMessagePacket(byte[] data)
+ {
+ using (MemoryStream mem = new MemoryStream(data))
+ {
+ using (BinaryReader binReader = new BinaryReader(mem))
+ {
+ try{
+ binReader.ReadUInt64();
+ posX = binReader.ReadSingle();
+ posY = binReader.ReadSingle();
+ posZ = binReader.ReadSingle();
+ posRot = binReader.ReadSingle();
+ logType = binReader.ReadUInt32();
+ message = Encoding.ASCII.GetString(binReader.ReadBytes(0x200)).Trim(new [] { '\0' });
+ }
+ catch (Exception){
+ invalidPacket = true;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/FFXIVClassic World Server/Packets/Receive/Subpackets/PartyChatMessagePacket.cs b/FFXIVClassic World Server/Packets/Receive/Subpackets/PartyChatMessagePacket.cs
new file mode 100644
index 00000000..ef20b3fc
--- /dev/null
+++ b/FFXIVClassic World Server/Packets/Receive/Subpackets/PartyChatMessagePacket.cs
@@ -0,0 +1,31 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace FFXIVClassic_World_Server.Packets.Receive.Subpackets
+{
+ class PartyChatMessagePacket
+ {
+ public uint actorId;
+ public string message;
+
+ public bool invalidPacket = false;
+
+ public PartyChatMessagePacket(byte[] data)
+ {
+ using (MemoryStream mem = new MemoryStream(data))
+ {
+ using (BinaryReader binReader = new BinaryReader(mem))
+ {
+ try{
+ actorId = binReader.ReadUInt32();
+ message = Encoding.ASCII.GetString(binReader.ReadBytes(0x200)).Trim(new [] { '\0' });
+ }
+ catch (Exception){
+ invalidPacket = true;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/FFXIVClassic World Server/Packets/Send/Subpackets/Groups/GroupHeaderPacket.cs b/FFXIVClassic World Server/Packets/Send/Subpackets/Groups/GroupHeaderPacket.cs
index 0c237f5e..d1d46a3a 100644
--- a/FFXIVClassic World Server/Packets/Send/Subpackets/Groups/GroupHeaderPacket.cs
+++ b/FFXIVClassic World Server/Packets/Send/Subpackets/Groups/GroupHeaderPacket.cs
@@ -46,6 +46,7 @@ namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
binWriter.Seek(0x64, SeekOrigin.Begin);
+ //Does this change chat????
binWriter.Write((UInt32)0x6D);
binWriter.Write((UInt32)0x6D);
binWriter.Write((UInt32)0x6D);
diff --git a/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/PartyInviteResultPacket.cs b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/GroupInviteResultPacket.cs
similarity index 80%
rename from FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/PartyInviteResultPacket.cs
rename to FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/GroupInviteResultPacket.cs
index f3fa8701..6197b16c 100644
--- a/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/PartyInviteResultPacket.cs
+++ b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/GroupInviteResultPacket.cs
@@ -5,13 +5,14 @@ using System.Text;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
{
- class PartyInviteResultPacket
+ class GroupInviteResultPacket
{
public bool invalidPacket = false;
+ public uint groupType;
public uint result;
- public PartyInviteResultPacket(byte[] data)
+ public GroupInviteResultPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
@@ -19,6 +20,7 @@ namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
{
try
{
+ groupType = binReader.ReadUInt32();
result = binReader.ReadUInt32();
}
catch (Exception)
diff --git a/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/PartyInvitePacket.cs b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/PartyInvitePacket.cs
index 796a1792..1a4d55e3 100644
--- a/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/PartyInvitePacket.cs
+++ b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/PartyInvitePacket.cs
@@ -23,7 +23,7 @@ namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
{
command = binReader.ReadUInt16();
- if (command == 0)
+ if (command == 1)
actorId = binReader.ReadUInt32();
else
name = Encoding.ASCII.GetString(binReader.ReadBytes(0x20)).Trim(new[] { '\0' });
diff --git a/FFXIVClassic World Server/Server.cs b/FFXIVClassic World Server/Server.cs
index d6221bb6..0e3d6247 100644
--- a/FFXIVClassic World Server/Server.cs
+++ b/FFXIVClassic World Server/Server.cs
@@ -233,16 +233,23 @@ namespace FFXIVClassic_World_Server
//Party Invite Request
case 0x1022:
PartyInvitePacket partyInvitePacket = new PartyInvitePacket(subpacket.data);
- if (partyInvitePacket.command == 0)
+ if (partyInvitePacket.command == 1)
mWorldManager.ProcessPartyInvite(GetSession(subpacket.header.sourceId), partyInvitePacket.actorId);
- else if (partyInvitePacket.command == 1)
+ else if (partyInvitePacket.command == 0)
{
}
break;
- //Party Invite Result
+ //Group Invite Result
case 0x1023:
- PartyInviteResultPacket partyInviteResultPacket = new PartyInviteResultPacket(subpacket.data);
+ GroupInviteResultPacket groupInviteResultPacket = new GroupInviteResultPacket(subpacket.data);
+
+ switch (groupInviteResultPacket.groupType)
+ {
+ case 0x2711:
+ mWorldManager.ProcessPartyInviteResult(GetSession(subpacket.header.sourceId), groupInviteResultPacket.result);
+ break;
+ }
break;
//Linkshell create request
diff --git a/FFXIVClassic World Server/WorldMaster.cs b/FFXIVClassic World Server/WorldMaster.cs
index 9181d46d..779bf352 100644
--- a/FFXIVClassic World Server/WorldMaster.cs
+++ b/FFXIVClassic World Server/WorldMaster.cs
@@ -219,10 +219,7 @@ namespace FFXIVClassic_World_Server
mRetainerGroupManager.GetRetainerGroup(session.sessionId).SendGroupPackets(session);
List linkshells = mLinkshellManager.GetPlayerLinkshellMembership(session.sessionId);
foreach (Linkshell ls in linkshells)
- ls.SendGroupPackets(session);
-
- mRelationGroupManager.CreatePartyRelationGroup(157, session.sessionId).SendGroupPackets(session);
-
+ ls.SendGroupPackets(session);
}
private void SendMotD(Session session)
@@ -292,9 +289,50 @@ namespace FFXIVClassic_World_Server
}
}
- public void ProcessPartyInvite(Session request, uint invitee)
+ public void ProcessPartyInvite(Session requestSession, uint invitee)
{
- throw new NotImplementedException();
+ if (mServer.GetSession(invitee) == null)
+ {
+ requestSession.SendGameMessage(30544, 0x20);
+ }
+ else
+ {
+ Session inviteeSession = mServer.GetSession(invitee);
+ Relation inviteRelation = mRelationGroupManager.CreatePartyRelationGroup(requestSession.sessionId, invitee);
+ inviteRelation.SendGroupPacketsAll(requestSession.sessionId, invitee);
+ inviteeSession.SendGameMessage(30430, 0x20, (object)mServer.GetNameForId(requestSession.sessionId)); //X Invited you
+ requestSession.SendGameMessage(30433, 0x20, (object)mServer.GetNameForId(inviteeSession.sessionId)); //You invite X
+ }
+ }
+
+ public void ProcessPartyInviteResult(Session inviteeSession, uint resultCode)
+ {
+ Relation relation = mRelationGroupManager.GetPartyRelationGroup(inviteeSession.sessionId);
+ Session inviterSession = mServer.GetSession(relation.GetHost());
+
+ //Accept
+ if (resultCode == 1)
+ {
+ Party oldParty = mPartyManager.GetParty(inviteeSession.sessionId);
+ if (oldParty.members.Count == 1)
+ {
+ mPartyManager.DeleteParty(oldParty.groupIndex);
+ Party newParty = mPartyManager.GetParty(inviterSession.sessionId);
+ mPartyManager.AddToParty(newParty.groupIndex, inviteeSession.sessionId);
+ newParty.SendGroupPacketsAll(newParty.members);
+ SendPartySync(newParty);
+ newParty.OnPlayerJoin(inviteeSession);
+ }
+ }
+ else //Refuse
+ {
+ inviterSession.SendGameMessage(30573, 0x20, (object)mServer.GetNameForId(inviteeSession.sessionId)); //X rejects your invite
+ }
+
+ //Delete the relation
+ mRelationGroupManager.DeleteRelationGroup(relation.groupIndex);
+ relation.SendDeletePackets(inviterSession.sessionId, inviteeSession.sessionId);
+
}
public void IncrementGroupIndex()