From 771b5b6d813b1ecc1f38cf0c5b4b5c9cb4e0698d Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Mon, 9 Jan 2017 00:12:11 -0500 Subject: [PATCH] LS kicking and leaving work. --- FFXIVClassic Map Server/WorldManager.cs | 8 ++- .../Send/Group/LinkshellLeavePacket.cs | 9 ++- .../DataObjects/Group/Group.cs | 3 +- .../DataObjects/Group/Linkshell.cs | 68 +++++++++++++++++-- FFXIVClassic World Server/Database.cs | 55 ++++++++++++++- .../Receive/Group/LinkshellLeavePacket.cs | 6 +- FFXIVClassic World Server/Server.cs | 6 +- 7 files changed, 139 insertions(+), 16 deletions(-) diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 8d0068d0..17c034a8 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -698,7 +698,13 @@ namespace FFXIVClassic_Map_Server public void RequestWorldLinkshellLeave(Player player, string lsname) { - SubPacket packet = LinkshellLeavePacket.BuildPacket(player.playerSession, lsname, false); + SubPacket packet = LinkshellLeavePacket.BuildPacket(player.playerSession, lsname, null, false); + Server.GetWorldConnection().QueuePacket(packet, true, false); + } + + public void RequestWorldLinkshellKick(Player player, string lsname, string kickedName) + { + SubPacket packet = LinkshellLeavePacket.BuildPacket(player.playerSession, lsname, kickedName, true); Server.GetWorldConnection().QueuePacket(packet, true, false); } diff --git a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellLeavePacket.cs b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellLeavePacket.cs index 2209cdc8..008add1a 100644 --- a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellLeavePacket.cs +++ b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/LinkshellLeavePacket.cs @@ -11,16 +11,19 @@ namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group class LinkshellLeavePacket { public const ushort OPCODE = 0x1031; - public const uint PACKET_SIZE = 0x48; + public const uint PACKET_SIZE = 0x68; - public static SubPacket BuildPacket(Session session, string lsName, bool isDisband) + public static SubPacket BuildPacket(Session session, string lsName, string kickedName, bool isKicked) { 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)); + binWriter.Write((UInt16)(isKicked ? 1 : 0)); + if (kickedName != null && isKicked) + binWriter.Write(Encoding.ASCII.GetBytes(kickedName), 0, Encoding.ASCII.GetByteCount(kickedName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(kickedName)); + binWriter.Seek(0x22, SeekOrigin.Begin); binWriter.Write(Encoding.ASCII.GetBytes(lsName), 0, Encoding.ASCII.GetByteCount(lsName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(lsName)); } } diff --git a/FFXIVClassic World Server/DataObjects/Group/Group.cs b/FFXIVClassic World Server/DataObjects/Group/Group.cs index 02a97553..2cef6f9e 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Group.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Group.cs @@ -122,7 +122,8 @@ namespace FFXIVClassic_World_Server.DataObjects.Group public void SendDeletePacket(Session session) { - session.clientConnection.QueuePacket(DeleteGroupPacket.buildPacket(session.sessionId, this), true, false); + if (session != null) + session.clientConnection.QueuePacket(DeleteGroupPacket.buildPacket(session.sessionId, this), true, false); } public virtual void SendInitWorkValues(Session session) diff --git a/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs b/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs index 54a3a2b8..27748ab7 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs @@ -176,6 +176,19 @@ namespace FFXIVClassic_World_Server.DataObjects.Group } } + public LinkshellMember GetMember(string name) + { + lock (members) + { + for (int i = 0; i < members.Count; i++) + { + if (Server.GetServer().GetNameForId((members[i].charaId)).Equals(name)) + return members[i]; + } + return null; + } + } + public bool HasMember(uint id) { lock (members) @@ -203,14 +216,56 @@ namespace FFXIVClassic_World_Server.DataObjects.Group { return; } - + //Send you are leaving message - requestSession.SendGameMessage(25162, 0x20, (Object)1, (Object)Server.GetServer().GetNameForId(leaver)); + requestSession.SendGameMessage(25162, 0x20, (Object)1, name); //All good, remove Server.GetServer().GetWorldManager().GetLinkshellManager().RemoveMemberFromLinkshell(requestSession.sessionId, name); SendGroupPacketsAll(GetMemberIds()); ResendWorkValues(); + + //Delete group for kicked guy + SendDeletePacket(requestSession); + } + + public void KickRequest(Session requestSession, string kickedName) + { + LinkshellMember kicked = GetMember(kickedName); + Session kickedSession = Server.GetServer().GetSession(kicked.charaId); + + //Check if ls contains this person + if (!HasMember(kicked.charaId)) + { + requestSession.SendGameMessage(25281, 0x20, (Object)1, (Object)kickedName, (Object)name); + return; + } + + //Send you are exiled message + lock (members) + { + for (int i = 0; i < members.Count; i++) + { + Session session = Server.GetServer().GetSession(members[i].charaId); + + if (session == null) + continue; + + if (session.sessionId == kicked.charaId) + session.SendGameMessage(25184, 0x20, (Object)1, (Object)name); + else + session.SendGameMessage(25280, 0x20, (Object)1, (Object)kickedName, (Object)name); + } + } + + //All good, remove + Server.GetServer().GetWorldManager().GetLinkshellManager().RemoveMemberFromLinkshell(kicked.charaId, name); + SendGroupPacketsAll(GetMemberIds()); + ResendWorkValues(); + + //Delete group for kicked guy + SendDeletePacket(kickedSession); + } public void RankChangeRequest(Session requestSession, string name, byte rank) @@ -221,9 +276,12 @@ namespace FFXIVClassic_World_Server.DataObjects.Group { if (Server.GetServer().GetNameForId(members[i].charaId).Equals(name)) { - members[i].rank = rank; - ResendWorkValues(); - requestSession.SendGameMessage(25277, 0x20, (object)(100000 + rank), (object)name); + if (Database.LinkshellChangeRank(members[i].charaId, rank)) + { + members[i].rank = rank; + ResendWorkValues(); + requestSession.SendGameMessage(25277, 0x20, (object)(100000 + rank), (object)name); + } return; } } diff --git a/FFXIVClassic World Server/Database.cs b/FFXIVClassic World Server/Database.cs index 51a923e8..e5a3993c 100644 --- a/FFXIVClassic World Server/Database.cs +++ b/FFXIVClassic World Server/Database.cs @@ -420,7 +420,34 @@ namespace FFXIVClassic_World_Server public static bool LinkshellRemovePlayer(ulong lsId, uint charaId) { - throw new NotImplementedException(); + bool success = false; + 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(); + + string query = @" + DELETE FROM characters_linkshells + WHERE characterId = @charaId AND linkshellId = @lsId; + "; + + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charaId", charaId); + cmd.Parameters.AddWithValue("@lsId", lsId); + cmd.ExecuteNonQuery(); + success = true; + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + } + } + return success; } public static bool ChangeLinkshellCrest(ulong lsId, ushort newCrestId) @@ -448,5 +475,31 @@ namespace FFXIVClassic_World_Server } return success; } + + public static bool LinkshellChangeRank(uint charaId, byte rank) + { + bool success = false; + 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(); + MySqlCommand cmd = new MySqlCommand("UPDATE characters_linkshells SET rank = @rank WHERE characterId = @charaId", conn); + cmd.Parameters.AddWithValue("@charaId", charaId); + cmd.Parameters.AddWithValue("@rank", rank); + cmd.ExecuteNonQuery(); + success = true; + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + } + } + return success; + } } } diff --git a/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellLeavePacket.cs b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellLeavePacket.cs index ecbe51ce..ea8a5469 100644 --- a/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellLeavePacket.cs +++ b/FFXIVClassic World Server/Packets/WorldPackets/Receive/Group/LinkshellLeavePacket.cs @@ -9,8 +9,9 @@ namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group { public bool invalidPacket = false; - public bool isDisband; + public bool isKicked; public string lsName; + public string kickedName; public LinkshellLeavePacket(byte[] data) { @@ -20,7 +21,8 @@ namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group { try { - isDisband = binReader.ReadUInt16() == 1; + isKicked = binReader.ReadUInt16() == 1; + kickedName = Encoding.ASCII.GetString(binReader.ReadBytes(0x20)).Trim(new[] { '\0' }); lsName = Encoding.ASCII.GetString(binReader.ReadBytes(0x20)).Trim(new[] { '\0' }); } catch (Exception) diff --git a/FFXIVClassic World Server/Server.cs b/FFXIVClassic World Server/Server.cs index f5c3ff6d..642bc604 100644 --- a/FFXIVClassic World Server/Server.cs +++ b/FFXIVClassic World Server/Server.cs @@ -315,12 +315,12 @@ namespace FFXIVClassic_World_Server LinkshellInviteCancelPacket linkshellInviteCancelPacket = new LinkshellInviteCancelPacket(subpacket.data); mWorldManager.ProcessLinkshellInviteCancel(GetSession(subpacket.header.sourceId)); break; - //Linkshell resign/disband + //Linkshell resign/kicked case 0x1031: LinkshellLeavePacket linkshellLeavePacket = new LinkshellLeavePacket(subpacket.data); Linkshell lsLeave = mWorldManager.GetLinkshellManager().GetLinkshell(linkshellLeavePacket.lsName); - if (linkshellLeavePacket.isDisband) - lsLeave.DisbandRequest(GetSession(subpacket.header.sourceId)); + if (linkshellLeavePacket.isKicked) + lsLeave.KickRequest(GetSession(subpacket.header.sourceId), linkshellLeavePacket.kickedName); else lsLeave.LeaveRequest(GetSession(subpacket.header.sourceId)); break;