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++;