diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
index dac17214..09f9f962 100644
--- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
+++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
@@ -285,8 +285,10 @@
+
+
diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs
index 39912ab0..b4c44a1b 100644
--- a/FFXIVClassic Map Server/WorldManager.cs
+++ b/FFXIVClassic Map Server/WorldManager.cs
@@ -678,14 +678,21 @@ namespace FFXIVClassic_Map_Server
Server.GetWorldConnection().QueuePacket(packet, true, false);
}
- public bool RequestWorldLinkshellRankChange(Player player, string lsname, string memberName, byte newRank)
+ public void RequestWorldLinkshellRankChange(Player player, string lsname, string memberName, byte newRank)
{
- return false;
+
}
- public bool RequestWorldLinkshellAddMember(Player player, string lsname, string memberName)
+ public void RequestWorldLinkshellInviteMember(Player player, string lsname, uint invitedActorId)
{
- return false;
+ SubPacket packet = LinkshellInvitePacket.BuildPacket(player.playerSession, invitedActorId, lsname);
+ Server.GetWorldConnection().QueuePacket(packet, true, false);
+ }
+
+ public void RequestWorldLinkshellCancelInvite(Player player)
+ {
+ SubPacket packet = LinkshellInviteCancelPacket.BuildPacket(player.playerSession);
+ Server.GetWorldConnection().QueuePacket(packet, true, false);
}
public bool RequestWorldLinkshellRemoveMember(Player player, bool wasKicked, string lsname, string memberName)
diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs
index ddbae92a..9131270d 100644
--- a/FFXIVClassic Map Server/lua/LuaEngine.cs
+++ b/FFXIVClassic Map Server/lua/LuaEngine.cs
@@ -363,6 +363,7 @@ namespace FFXIVClassic_Map_Server.lua
((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua");
script.Globals["GetWorldManager"] = (Func)Server.GetWorldManager;
script.Globals["GetStaticActor"] = (Func)Server.GetStaticActors;
+ script.Globals["GetStaticActorById"] = (Func)Server.GetStaticActors;
script.Globals["GetWorldMaster"] = (Func)Server.GetWorldManager().GetActor;
script.Globals["GetItemGamedata"] = (Func)Server.GetItemGamedata;
diff --git a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellInviteCancelPacket.cs b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellInviteCancelPacket.cs
new file mode 100644
index 00000000..f6823db0
--- /dev/null
+++ b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellInviteCancelPacket.cs
@@ -0,0 +1,23 @@
+using FFXIVClassic.Common;
+using FFXIVClassic_Map_Server.dataobjects;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
+{
+ class LinkshellInviteCancelPacket
+ {
+ public const ushort OPCODE = 0x1030;
+ public const uint PACKET_SIZE = 0x28;
+
+ public static SubPacket BuildPacket(Session session)
+ {
+ byte[] data = new byte[PACKET_SIZE - 0x20];
+ return new SubPacket(true, OPCODE, session.id, session.id, data);
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellInvitePacket.cs b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellInvitePacket.cs
new file mode 100644
index 00000000..fbe14e10
--- /dev/null
+++ b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellInvitePacket.cs
@@ -0,0 +1,31 @@
+using FFXIVClassic.Common;
+using FFXIVClassic_Map_Server.dataobjects;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
+{
+ class LinkshellInvitePacket
+ {
+ public const ushort OPCODE = 0x1029;
+ public const uint PACKET_SIZE = 0x48;
+
+ public static SubPacket BuildPacket(Session session, uint actorId, string linkshellName)
+ {
+ byte[] data = new byte[PACKET_SIZE - 0x20];
+ using (MemoryStream mem = new MemoryStream(data))
+ {
+ using (BinaryWriter binWriter = new BinaryWriter(mem))
+ {
+ binWriter.Write((UInt32)actorId);
+ binWriter.Write(Encoding.ASCII.GetBytes(linkshellName), 0, Encoding.ASCII.GetByteCount(linkshellName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(linkshellName));
+ }
+ }
+ return new SubPacket(true, OPCODE, session.id, session.id, data);
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/packets/send/GameMessagePacket.cs b/FFXIVClassic Map Server/packets/send/GameMessagePacket.cs
index cffe2a37..553f5eec 100644
--- a/FFXIVClassic Map Server/packets/send/GameMessagePacket.cs
+++ b/FFXIVClassic Map Server/packets/send/GameMessagePacket.cs
@@ -329,6 +329,11 @@ namespace FFXIVClassic_Map_Server.packets.send
{
case 0:
case 1:
+ total += 5;
+ break;
+ case 2:
+ total += 20;
+ break;
case 6:
total += 5;
break;
diff --git a/FFXIVClassic Map Server/packets/send/events/KickEventPacket.cs b/FFXIVClassic Map Server/packets/send/events/KickEventPacket.cs
index 14e20263..518aee1e 100644
--- a/FFXIVClassic Map Server/packets/send/events/KickEventPacket.cs
+++ b/FFXIVClassic Map Server/packets/send/events/KickEventPacket.cs
@@ -23,10 +23,10 @@ namespace FFXIVClassic_Map_Server.packets.send.events
{
binWriter.Write((UInt32)playerActorId);
binWriter.Write((UInt32)targetActorId);
- binWriter.Write((Byte)0x5);
- binWriter.Write((Byte)0x87);
- binWriter.Write((Byte)0xDC);
- binWriter.Write((Byte)0x75);
+
+ int test = 0;
+
+ binWriter.Write((UInt32)test);
binWriter.Write((UInt32)0x30400000);
binWriter.Write(Encoding.ASCII.GetBytes(conditionName), 0, Encoding.ASCII.GetByteCount(conditionName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(conditionName));
diff --git a/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs b/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs
index f66dc348..22345bc8 100644
--- a/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs
+++ b/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs
@@ -51,7 +51,7 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
public void AddMember(uint charaId)
{
- members.Add(new LinkshellMember(charaId, dbId, 0xa));
+ members.Add(new LinkshellMember(charaId, dbId, 0x0));
members.Sort();
}
@@ -85,10 +85,24 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
public override List BuildMemberList(uint id)
{
- List groupMembers = new List();
- foreach (LinkshellMember member in members)
- groupMembers.Add(new GroupMember(member.charaId, -1, 0, false, true, Server.GetServer().GetNameForId(member.charaId)));
- return groupMembers;
+ lock (members)
+ {
+ List groupMembers = new List();
+ foreach (LinkshellMember member in members)
+ groupMembers.Add(new GroupMember(member.charaId, -1, 0, false, true, Server.GetServer().GetNameForId(member.charaId)));
+ return groupMembers;
+ }
+ }
+
+ public uint[] GetMemberIds()
+ {
+ lock (members)
+ {
+ uint[] memberIds = new uint[members.Count];
+ for (int i = 0; i < memberIds.Length; i++)
+ memberIds[i] = members[i].charaId;
+ return memberIds;
+ }
}
public override void SendInitWorkValues(Session session)
@@ -115,5 +129,34 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
{
members = Database.GetLSMembers(this);
}
+
+ public void OnPlayerJoin(Session inviteeSession)
+ {
+ for (int i = 0; i < members.Count; i++)
+ {
+ Session session = Server.GetServer().GetSession(members[i].charaId);
+ if (session == null)
+ continue;
+
+ if (inviteeSession.Equals(session))
+ session.SendGameMessage(25157, 0x20, (object) 0, (object)inviteeSession, name);
+ else
+ session.SendGameMessage(25284, 0x20, (object) 0, (object)Server.GetServer().GetNameForId(inviteeSession.sessionId), name);
+ }
+ }
+
+ public bool HasMember(uint id)
+ {
+ lock (members)
+ {
+ for (int i = 0; i < members.Count; i++)
+ {
+ if (members[i].charaId == id)
+ return true;
+ }
+ return false;
+ }
+ }
+
}
}
diff --git a/FFXIVClassic World Server/DataObjects/Group/Relation.cs b/FFXIVClassic World Server/DataObjects/Group/Relation.cs
index b256faf5..8564ee8a 100644
--- a/FFXIVClassic World Server/DataObjects/Group/Relation.cs
+++ b/FFXIVClassic World Server/DataObjects/Group/Relation.cs
@@ -12,13 +12,15 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
class Relation : Group
{
public RelationWork work = new RelationWork();
- public uint charaOther;
+ private uint charaOther;
+ private ulong topicGroup;
- public Relation(ulong groupIndex, uint host, uint other, uint command) : base (groupIndex)
+ public Relation(ulong groupIndex, uint host, uint other, uint command, ulong topicGroup) : base (groupIndex)
{
this.charaOther = other;
work._globalTemp.host = ((ulong)host << 32) | (0xc17909);
work._globalTemp.variableCommand = command;
+ this.topicGroup = topicGroup;
}
public uint GetHost()
@@ -41,6 +43,11 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
return Group.GroupInvitationRelationGroup;
}
+ public ulong GetTopicGroupIndex()
+ {
+ return topicGroup;
+ }
+
public override List BuildMemberList(uint id)
{
List groupMembers = new List();
diff --git a/FFXIVClassic World Server/DataObjects/LuaUtils.cs b/FFXIVClassic World Server/DataObjects/LuaUtils.cs
index 67c18b75..b6736024 100644
--- a/FFXIVClassic World Server/DataObjects/LuaUtils.cs
+++ b/FFXIVClassic World Server/DataObjects/LuaUtils.cs
@@ -294,7 +294,11 @@ namespace FFXIVClassic_World_Server.DataObjects
else if (o == null)
{
luaParams.Add(new LuaParam(0x5, null));
- }
+ }
+ else if (o is Session)
+ {
+ luaParams.Add(new LuaParam(0x6, (uint)((Session)o).sessionId));
+ }
else if (o is Type7Param)
{
luaParams.Add(new LuaParam(0x7, (Type7Param)o));
diff --git a/FFXIVClassic World Server/DataObjects/Session.cs b/FFXIVClassic World Server/DataObjects/Session.cs
index ee94330f..d90a3f1d 100644
--- a/FFXIVClassic World Server/DataObjects/Session.cs
+++ b/FFXIVClassic World Server/DataObjects/Session.cs
@@ -16,6 +16,7 @@ namespace FFXIVClassic_World_Server.DataObjects
public string characterName;
public uint currentZoneId;
+ public uint activeLinkshellIndex = 0;
public readonly ClientConnection clientConnection;
public readonly Channel type;
@@ -27,7 +28,17 @@ namespace FFXIVClassic_World_Server.DataObjects
this.clientConnection = connection;
this.type = type;
connection.owner = this;
- Database.LoadZoneSessionInfo(this);
+ Database.LoadZoneSessionInfo(this);
+ }
+
+ public void SendGameMessage(uint actorId, ushort textId, byte log, params object[] msgParams)
+ {
+ if (msgParams == null || msgParams.Length == 0)
+ {
+ clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, actorId, 0x5FF80001, textId, log), true, false);
+ }
+ else
+ clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, actorId, 0x5FF80001, textId, log, LuaUtils.CreateLuaParamList(msgParams)), true, false);
}
public void SendGameMessage( ushort textId, byte log, params object[] msgParams)
diff --git a/FFXIVClassic World Server/DataObjects/ZoneServer.cs b/FFXIVClassic World Server/DataObjects/ZoneServer.cs
index f4a2ac00..2ed92de4 100644
--- a/FFXIVClassic World Server/DataObjects/ZoneServer.cs
+++ b/FFXIVClassic World Server/DataObjects/ZoneServer.cs
@@ -77,7 +77,12 @@ namespace FFXIVClassic_World_Server.DataObjects
}
catch (Exception e)
{ Program.Log.Error("Weird case, socket was d/ced: {0}", e); }
- }
+ }
+ else
+ {
+ if (Connect())
+ SendPacket(subpacket);
+ }
}
private void ReceiveCallback(IAsyncResult result)
diff --git a/FFXIVClassic World Server/Database.cs b/FFXIVClassic World Server/Database.cs
index f6b40f00..51a923e8 100644
--- a/FFXIVClassic World Server/Database.cs
+++ b/FFXIVClassic World Server/Database.cs
@@ -381,7 +381,41 @@ namespace FFXIVClassic_World_Server
public static bool LinkshellAddPlayer(ulong lsId, uint charaId)
{
- throw new NotImplementedException();
+ string query;
+ MySqlCommand cmd;
+
+ using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
+ {
+ try
+ {
+ conn.Open();
+
+ query = @"
+ INSERT INTO characters_linkshells
+ (characterId, linkshellId)
+ VALUES
+ (@charaId, @lsId)
+ ";
+
+ cmd = new MySqlCommand(query, conn);
+ cmd.Parameters.AddWithValue("@charaId", charaId);
+ cmd.Parameters.AddWithValue("@lsId", lsId);
+ cmd.ExecuteNonQuery();
+
+ }
+ catch (MySqlException e)
+ {
+ Program.Log.Error(e.ToString());
+ conn.Dispose();
+ return false;
+ }
+ finally
+ {
+ conn.Dispose();
+ }
+ }
+
+ return true;
}
public static bool LinkshellRemovePlayer(ulong lsId, uint charaId)
diff --git a/FFXIVClassic World Server/FFXIVClassic World Server.csproj b/FFXIVClassic World Server/FFXIVClassic World Server.csproj
index f491b4b8..0f113c2f 100644
--- a/FFXIVClassic World Server/FFXIVClassic World Server.csproj
+++ b/FFXIVClassic World Server/FFXIVClassic World Server.csproj
@@ -111,6 +111,8 @@
+
+
diff --git a/FFXIVClassic World Server/LinkshellManager.cs b/FFXIVClassic World Server/LinkshellManager.cs
index 32b5e0fa..e6423c11 100644
--- a/FFXIVClassic World Server/LinkshellManager.cs
+++ b/FFXIVClassic World Server/LinkshellManager.cs
@@ -34,10 +34,11 @@ namespace FFXIVClassic_World_Server
Linkshell newLs = new Linkshell(resultId, mWorldManager.GetGroupIndex(), name, crest, master, 0xa);
//Add founder to the LS
- if (AddMemberToLinkshell(master, newLs.groupIndex))
+ if (AddMemberToLinkshell(master, newLs.name))
{
mLinkshellList.Add(mWorldManager.GetGroupIndex(), newLs);
mNameToIdLookup.Add(newLs.name, newLs.groupIndex);
+ mLSIdToIdLookup.Add(newLs.dbId, newLs);
mCurrentWorldGroupsReference.Add(mWorldManager.GetGroupIndex(), newLs);
mWorldManager.IncrementGroupIndex();
}
@@ -112,10 +113,10 @@ namespace FFXIVClassic_World_Server
}
//Adds a player to the linkshell
- public bool AddMemberToLinkshell(uint charaId, ulong groupId)
+ public bool AddMemberToLinkshell(uint charaId, string LSName)
{
//Get the LS
- Linkshell ls = GetLinkshell(groupId);
+ Linkshell ls = GetLinkshell(LSName);
if (ls == null)
return false;
@@ -135,10 +136,10 @@ namespace FFXIVClassic_World_Server
}
//Removes a player from the linkshell
- public bool RemoveMemberFromLinkshell(uint charaId, ulong groupId)
+ public bool RemoveMemberFromLinkshell(uint charaId, string LSName)
{
//Get the LS
- Linkshell ls = GetLinkshell(groupId);
+ Linkshell ls = GetLinkshell(LSName);
if (ls == null)
return false;
@@ -157,7 +158,7 @@ namespace FFXIVClassic_World_Server
}
}
- //Get a single linkshell group either already instantiated or make one from the db
+ //Get a single linkshell group either already instantiated or make one from the db by Name
public Linkshell GetLinkshell(string name)
{
if (mNameToIdLookup.ContainsKey(name))
@@ -173,6 +174,7 @@ namespace FFXIVClassic_World_Server
{
mLinkshellList.Add(ls.groupIndex, ls);
mNameToIdLookup.Add(ls.name, ls.groupIndex);
+ mLSIdToIdLookup.Add(ls.dbId, ls);
mCurrentWorldGroupsReference.Add(ls.groupIndex, ls);
mWorldManager.IncrementGroupIndex();
return ls;
@@ -183,11 +185,11 @@ namespace FFXIVClassic_World_Server
}
}
- //Get a single linkshell group either already instantiated or make one from the db
+ //Get a single linkshell group either already instantiated or make one from the db by ID
public Linkshell GetLinkshell(ulong lsId)
{
if (mLSIdToIdLookup.ContainsKey(lsId))
- return mLSIdToIdLookup[lsId];
+ return (Linkshell)mCurrentWorldGroupsReference[mLSIdToIdLookup[lsId].groupIndex];
else
{
lock (mGroupLockReference)
@@ -196,7 +198,7 @@ namespace FFXIVClassic_World_Server
ls.LoadMembers();
if (ls != null)
- {
+ {
mLinkshellList.Add(ls.groupIndex, ls);
mNameToIdLookup.Add(ls.name, ls.groupIndex);
mLSIdToIdLookup.Add(ls.dbId, ls);
@@ -204,9 +206,10 @@ namespace FFXIVClassic_World_Server
mWorldManager.IncrementGroupIndex();
return ls;
}
+ else
+ return null;
}
}
- return null;
}
//Get the linkshells player is part of
diff --git a/FFXIVClassic World Server/Packets/Send/Subpackets/GameMessagePacket.cs b/FFXIVClassic World Server/Packets/Send/Subpackets/GameMessagePacket.cs
index 8b3041fe..9f27c67d 100644
--- a/FFXIVClassic World Server/Packets/Send/Subpackets/GameMessagePacket.cs
+++ b/FFXIVClassic World Server/Packets/Send/Subpackets/GameMessagePacket.cs
@@ -329,6 +329,8 @@ namespace FFXIVClassic_World_Server.Packets.Send.Subpackets
{
case 0:
case 1:
+ total += 5;
+ break;
case 2:
total += 1 + 0x20;
break;
diff --git a/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellInviteCancelPacket.cs b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellInviteCancelPacket.cs
new file mode 100644
index 00000000..0f2bf8f7
--- /dev/null
+++ b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellInviteCancelPacket.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
+{
+ class LinkshellInviteCancelPacket
+ {
+ public bool invalidPacket = false;
+
+ public string lsName;
+ public uint actorId;
+
+ public LinkshellInviteCancelPacket(byte[] data)
+ {
+ using (MemoryStream mem = new MemoryStream(data))
+ {
+ using (BinaryReader binReader = new BinaryReader(mem))
+ {
+ try
+ {
+ }
+ catch (Exception)
+ {
+ invalidPacket = true;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellInvitePacket.cs b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellInvitePacket.cs
new file mode 100644
index 00000000..5f1e86b4
--- /dev/null
+++ b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellInvitePacket.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
+{
+ class LinkshellInvitePacket
+ {
+ public bool invalidPacket = false;
+
+ public string lsName;
+ public uint actorId;
+
+ public LinkshellInvitePacket(byte[] data)
+ {
+ using (MemoryStream mem = new MemoryStream(data))
+ {
+ using (BinaryReader binReader = new BinaryReader(mem))
+ {
+ try
+ {
+ actorId = binReader.ReadUInt32();
+ lsName = Encoding.ASCII.GetString(binReader.ReadBytes(0x20)).Trim(new[] { '\0' });
+ }
+ catch (Exception)
+ {
+ invalidPacket = true;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/FFXIVClassic World Server/Program.cs b/FFXIVClassic World Server/Program.cs
index 117e6903..13a4f777 100644
--- a/FFXIVClassic World Server/Program.cs
+++ b/FFXIVClassic World Server/Program.cs
@@ -19,16 +19,7 @@ namespace FFXIVClassic_World_Server
{
// set up logging
Log = LogManager.GetCurrentClassLogger();
-#if DEBUG
- TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
- Debug.Listeners.Add(myWriter);
- if (System.Diagnostics.Debugger.IsAttached)
- {
- System.Threading.Thread.Sleep(15000);
- }
-
-#endif
bool startServer = true;
Log.Info("==================================");
@@ -36,6 +27,17 @@ namespace FFXIVClassic_World_Server
Log.Info("Version: 0.0.1");
Log.Info("==================================");
+#if DEBUG
+ TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
+ Debug.Listeners.Add(myWriter);
+
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ System.Threading.Thread.Sleep(5000);
+ }
+
+#endif
+
//Load Config
if (!ConfigConstants.Load())
startServer = false;
diff --git a/FFXIVClassic World Server/RelationGroupManager.cs b/FFXIVClassic World Server/RelationGroupManager.cs
index c15f6bc1..9d73b513 100644
--- a/FFXIVClassic World Server/RelationGroupManager.cs
+++ b/FFXIVClassic World Server/RelationGroupManager.cs
@@ -19,12 +19,12 @@ namespace FFXIVClassic_World_Server
mCurrentWorldGroupsReference = worldGroupList;
}
- public Relation CreatePartyRelationGroup(uint hostCharaId, uint otherCharaId)
+ public Relation CreatePartyRelationGroup(ulong topicGroupId, uint hostCharaId, uint otherCharaId)
{
lock (mGroupLockReference)
{
ulong groupIndex = mWorldManager.GetGroupIndex();
- Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, 10001);
+ Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, 10001, topicGroupId);
mPartyRelationList.Add(groupIndex, relation);
mCurrentWorldGroupsReference.Add(groupIndex, relation);
mWorldManager.IncrementGroupIndex();
@@ -32,12 +32,12 @@ namespace FFXIVClassic_World_Server
}
}
- public Relation CreateLinkshellRelationGroup(uint hostCharaId, uint otherCharaId)
+ public Relation CreateLinkshellRelationGroup(ulong topicGroupId, uint hostCharaId, uint otherCharaId)
{
lock (mGroupLockReference)
{
ulong groupIndex = mWorldManager.GetGroupIndex();
- Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, 10002);
+ Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, 10002, topicGroupId);
mLinkshellRelationList.Add(groupIndex, relation);
mCurrentWorldGroupsReference.Add(groupIndex, relation);
mWorldManager.IncrementGroupIndex();
diff --git a/FFXIVClassic World Server/Server.cs b/FFXIVClassic World Server/Server.cs
index 0e3d6247..422f3e75 100644
--- a/FFXIVClassic World Server/Server.cs
+++ b/FFXIVClassic World Server/Server.cs
@@ -249,6 +249,9 @@ namespace FFXIVClassic_World_Server
case 0x2711:
mWorldManager.ProcessPartyInviteResult(GetSession(subpacket.header.sourceId), groupInviteResultPacket.result);
break;
+ case 0x2712:
+ mWorldManager.ProcessLinkshellInviteResult(GetSession(subpacket.header.sourceId), groupInviteResultPacket.result);
+ break;
}
break;
@@ -282,6 +285,16 @@ namespace FFXIVClassic_World_Server
SetActiveLinkshellPacket setActiveLinkshellPacket = new SetActiveLinkshellPacket(subpacket.data);
//Linkshell ls = mWorldManager.GetLinkshellManager().GetLinkshell();
break;
+ //Linkshell invite member
+ case 0x1029:
+ LinkshellInvitePacket linkshellInvitePacket = new LinkshellInvitePacket(subpacket.data);
+ mWorldManager.ProcessLinkshellInvite(GetSession(subpacket.header.sourceId), linkshellInvitePacket.lsName, linkshellInvitePacket.actorId);
+ break;
+ //Linkshell cancel invite
+ case 0x1030:
+ LinkshellInviteCancelPacket linkshellInviteCancelPacket = new LinkshellInviteCancelPacket(subpacket.data);
+ mWorldManager.ProcessLinkshellInviteCancel(GetSession(subpacket.header.sourceId));
+ break;
}
}
else if (mZoneSessionList.ContainsKey(sessionId))
diff --git a/FFXIVClassic World Server/WorldMaster.cs b/FFXIVClassic World Server/WorldMaster.cs
index 779bf352..0e588559 100644
--- a/FFXIVClassic World Server/WorldMaster.cs
+++ b/FFXIVClassic World Server/WorldMaster.cs
@@ -298,7 +298,7 @@ namespace FFXIVClassic_World_Server
else
{
Session inviteeSession = mServer.GetSession(invitee);
- Relation inviteRelation = mRelationGroupManager.CreatePartyRelationGroup(requestSession.sessionId, invitee);
+ Relation inviteRelation = mRelationGroupManager.CreatePartyRelationGroup(mPartyManager.GetParty(requestSession.sessionId).groupIndex, 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
@@ -335,6 +335,79 @@ namespace FFXIVClassic_World_Server
}
+ public void ProcessLinkshellInvite(Session inviterSession, string lsName, uint invitee)
+ {
+
+ if (mServer.GetSession(invitee) == null)
+ {
+ inviterSession.SendGameMessage(30544, 0x20);
+ }
+ else if (mRelationGroupManager.GetLinkshellRelationGroup(inviterSession.sessionId) != null)
+ {
+ Session inviteeSession = mServer.GetSession(invitee);
+ inviterSession.SendGameMessage(25196, 0x20, (object)inviteeSession); //Unable to invite X another pending
+ }
+ else if (mLinkshellManager.GetLinkshell(lsName).HasMember(invitee))
+ {
+ Session inviteeSession = mServer.GetSession(invitee);
+ inviterSession.SendGameMessage(25155, 0x20, (object)inviteeSession, 1); //X already belongs to
+ }
+ else
+ {
+ Session inviteeSession = mServer.GetSession(invitee);
+ Relation inviteRelation = mRelationGroupManager.CreateLinkshellRelationGroup(mLinkshellManager.GetLinkshell(lsName).groupIndex, inviterSession.sessionId, invitee);
+ inviteRelation.SendGroupPacketsAll(inviterSession.sessionId, invitee);
+ inviteeSession.SendGameMessage(25150, 0x20, (object)1, (object)lsName, (object)inviterSession); //X Offers you
+ inviterSession.SendGameMessage(25151, 0x20, (object)1, null, (object)inviteeSession); //You offer X
+ }
+
+ }
+
+ public void ProcessLinkshellInviteResult(Session inviteeSession, uint resultCode)
+ {
+ Relation relation = mRelationGroupManager.GetLinkshellRelationGroup(inviteeSession.sessionId);
+ Session inviterSession = mServer.GetSession(relation.GetHost());
+
+ //Accept
+ if (resultCode == 1)
+ {
+ Linkshell newLS;
+ if (mCurrentWorldGroups.ContainsKey(relation.groupIndex))
+ newLS = (Linkshell) mCurrentWorldGroups[relation.GetTopicGroupIndex()];
+ else
+ {
+ //Error???
+ return;
+ }
+
+ mLinkshellManager.AddMemberToLinkshell(inviteeSession.sessionId, newLS.name);
+ newLS.SendGroupPacketsAll(newLS.GetMemberIds());
+ newLS.OnPlayerJoin(inviteeSession);
+ }
+ else //Refuse
+ {
+ inviteeSession.SendGameMessage(25189, 0x20); //You decline the linkpearl offer.
+ inviterSession.SendGameMessage(25190, 0x20); //Your linkpearl offer is declined.
+ }
+
+ //Delete the relation
+ mRelationGroupManager.DeleteRelationGroup(relation.groupIndex);
+ relation.SendDeletePackets(inviterSession.sessionId, inviteeSession.sessionId);
+ }
+
+ public void ProcessLinkshellInviteCancel(Session inviterSession)
+ {
+ Relation relation = mRelationGroupManager.GetLinkshellRelationGroup(inviterSession.sessionId);
+ Session inviteeSession = mServer.GetSession(relation.GetOther());
+
+ inviterSession.SendGameMessage(25191, 0x20); //You cancel the linkpearl offer.
+ inviteeSession.SendGameMessage(25192, 0x20); //The linkpearl offer has been canceled.
+
+ //Delete the relation
+ mRelationGroupManager.DeleteRelationGroup(relation.groupIndex);
+ relation.SendDeletePackets(inviterSession.sessionId, inviteeSession.sessionId);
+ }
+
public void IncrementGroupIndex()
{
mRunningGroupIndex++;