diff --git a/FFXIVClassic World Server/DataObjects/Group/Group.cs b/FFXIVClassic World Server/DataObjects/Group/Group.cs index b87501a0..bc7a0861 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Group.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Group.cs @@ -75,5 +75,10 @@ namespace FFXIVClassic_World_Server.DataObjects.Group session.clientConnection.QueuePacket(GroupMembersEndPacket.buildPacket(session.sessionId, session.currentZoneId, time, 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 57f06c42..d1d3bf7f 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Linkshell.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups; +using FFXIVClassic.Common; namespace FFXIVClassic_World_Server.DataObjects.Group { @@ -15,7 +16,7 @@ namespace FFXIVClassic_World_Server.DataObjects.Group public LinkshellWork linkshellWork = new LinkshellWork(); - public Dictionary members = new Dictionary(); + private List members = new List(); public Linkshell(ulong dbId, ulong groupIndex, string name, ushort crestId, uint master, byte rank) : base(groupIndex) { @@ -48,6 +49,25 @@ namespace FFXIVClassic_World_Server.DataObjects.Group linkshellWork._memberSave[index].rank = rank; } + public void AddMember(uint charaId) + { + members.Add(new LinkshellMember(charaId, dbId, 0xa)); + members.Sort(); + } + + public void RemoveMember(uint charaId) + { + for (int i = 0; i < members.Count; i++) + { + if (members[i].charaId == charaId) + { + members.Remove(members[i]); + members.Sort(); + break; + } + } + } + public override int GetMemberCount() { return members.Count; @@ -61,14 +81,39 @@ namespace FFXIVClassic_World_Server.DataObjects.Group public override uint GetTypeId() { return Group.CompanyGroup; - } + } public override List BuildMemberList() { List groupMembers = new List(); - foreach (LinkshellMember member in members.Values) - groupMembers.Add(new GroupMember(member.charaId, -1, 0, false, Server.GetServer().GetSession(member.charaId) != null, Server.GetServer().GetNameForId(member.charaId))); + foreach (LinkshellMember member in members) + groupMembers.Add(new GroupMember(member.charaId, -1, 0, false, Server.GetServer().GetSession(member.charaId) != null, Server.GetServer().GetNameForId(member.charaId))); return groupMembers; } + + public override void SendInitWorkValues(Session session) + { + + SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex); + groupWork.addProperty(this, "linkshellWork._globalSave.master"); + groupWork.addProperty(this, "linkshellWork._globalSave.crestIcon[0]"); + groupWork.addProperty(this, "linkshellWork._globalSave.rank"); + + for (int i = 0; i < members.Count; i++) + { + linkshellWork._memberSave[i].rank = members[i].rank; + groupWork.addProperty(this, String.Format("linkshellWork._memberSave[{0}].rank", i)); + } + + groupWork.setTarget("/_init"); + SubPacket test = groupWork.buildPacket(session.sessionId, session.sessionId); + test.DebugPrintSubPacket(); + session.clientConnection.QueuePacket(test, true, false); + } + + public void LoadMembers() + { + members = Database.GetLSMembers(this); + } } } diff --git a/FFXIVClassic World Server/DataObjects/Group/LinkshellMember.cs b/FFXIVClassic World Server/DataObjects/Group/LinkshellMember.cs index ea664bdf..61984c88 100644 --- a/FFXIVClassic World Server/DataObjects/Group/LinkshellMember.cs +++ b/FFXIVClassic World Server/DataObjects/Group/LinkshellMember.cs @@ -6,19 +6,22 @@ using System.Threading.Tasks; namespace FFXIVClassic_World_Server.DataObjects.Group { - class LinkshellMember + class LinkshellMember : IComparable { public readonly uint charaId; public readonly ulong lsId; - public readonly ushort slot; - public readonly ushort rank; + public readonly byte rank; - public LinkshellMember(uint charaId, ulong lsId, ushort slot, ushort rank) + public LinkshellMember(uint charaId, ulong lsId, byte rank) { this.charaId = charaId; this.lsId = lsId; - this.slot = slot; this.rank = rank; } + + public int CompareTo(LinkshellMember other) + { + return Server.GetServer().GetNameForId(charaId).CompareTo(Server.GetServer().GetNameForId(other.charaId)); + } } } diff --git a/FFXIVClassic World Server/DataObjects/Group/Party.cs b/FFXIVClassic World Server/DataObjects/Group/Party.cs index ff0413a3..3fc215fa 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Party.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Party.cs @@ -1,4 +1,5 @@ -using FFXIVClassic_World_Server.Actor.Group.Work; +using FFXIVClassic.Common; +using FFXIVClassic_World_Server.Actor.Group.Work; using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups; using System; using System.Collections.Generic; @@ -27,18 +28,16 @@ namespace FFXIVClassic_World_Server.DataObjects.Group { return (uint)(partyGroupWork._globalTemp.owner & 0xFFFFFF); } - - /* - public override void sendWorkValues(Session session) + + public override void SendInitWorkValues(Session session) { - SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupId); + SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex); groupWork.addProperty(this, "partyGroupWork._globalTemp.owner"); groupWork.setTarget("/_init"); SubPacket test = groupWork.buildPacket(session.sessionId, session.sessionId); session.clientConnection.QueuePacket(test, true, false); - } - */ + } public override int GetMemberCount() { diff --git a/FFXIVClassic World Server/DataObjects/Group/Relation.cs b/FFXIVClassic World Server/DataObjects/Group/Relation.cs index aedfecac..c257cf2c 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Relation.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Relation.cs @@ -1,4 +1,5 @@ -using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups; +using FFXIVClassic.Common; +using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups; using System; using System.Collections.Generic; using System.Linq; @@ -37,5 +38,17 @@ namespace FFXIVClassic_World_Server.DataObjects.Group return groupMembers; } + public override void SendInitWorkValues(Session session) + { + SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex); + groupWork.addProperty(this, "work._globalTemp.host"); + groupWork.addProperty(this, "work._globalTemp.variableCommand"); + groupWork.setTarget("/_init"); + + SubPacket test = groupWork.buildPacket(session.sessionId, session.sessionId); + test.DebugPrintSubPacket(); + session.clientConnection.QueuePacket(test, true, false); + } + } } diff --git a/FFXIVClassic World Server/DataObjects/Group/RetainerGroup.cs b/FFXIVClassic World Server/DataObjects/Group/RetainerGroup.cs index 72c11616..0fab6229 100644 --- a/FFXIVClassic World Server/DataObjects/Group/RetainerGroup.cs +++ b/FFXIVClassic World Server/DataObjects/Group/RetainerGroup.cs @@ -1,4 +1,5 @@ -using FFXIVClassic_World_Server.Actor.Group.Work; +using FFXIVClassic.Common; +using FFXIVClassic_World_Server.Actor.Group.Work; using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups; using System; using System.Collections.Generic; @@ -28,11 +29,10 @@ namespace FFXIVClassic_World_Server.DataObjects.Group work._memberSave[index].conditions = condition; work._memberSave[index].level = level; } - - /* - public override void sendWorkValues(Session session) + + public override void SendInitWorkValues(Session session) { - SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupId); + SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex); groupWork.addProperty(this, "work._memberSave[0].cdIDOffset"); groupWork.addProperty(this, "work._memberSave[0].placeName"); groupWork.addProperty(this, "work._memberSave[0].conditions"); @@ -42,8 +42,7 @@ namespace FFXIVClassic_World_Server.DataObjects.Group SubPacket test = groupWork.buildPacket(session.sessionId, session.sessionId); session.clientConnection.QueuePacket(test, true, false); } - */ - + public override int GetMemberCount() { return members.Count; diff --git a/FFXIVClassic World Server/Database.cs b/FFXIVClassic World Server/Database.cs index 4f8f2eed..e79d4b56 100644 --- a/FFXIVClassic World Server/Database.cs +++ b/FFXIVClassic World Server/Database.cs @@ -159,27 +159,26 @@ namespace FFXIVClassic_World_Server return null; } - public static Dictionary GetLSMembers(ulong lsId) + public static List GetLSMembers(Linkshell ls) { - Dictionary memberList = new Dictionary(); + List memberList = new List(); 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("SELECT characterId, linkshellId, slot, rank FROM characters_linkshells WHERE linkshellId = @lsId", conn); - cmd.Parameters.AddWithValue("@lsId", lsId); + MySqlCommand cmd = new MySqlCommand("SELECT characterId, linkshellId, rank FROM characters_linkshells WHERE linkshellId = @lsId", conn); + cmd.Parameters.AddWithValue("@lsId", ls.dbId); using (MySqlDataReader Reader = cmd.ExecuteReader()) { while (Reader.Read()) { uint characterId = Reader.GetUInt32("characterId"); ulong linkshellId = Reader.GetUInt64("linkshellId"); - ushort slot = Reader.GetUInt16("slot"); - ushort rank = Reader.GetUInt16("rank"); + byte rank = Reader.GetByte("rank"); - LinkshellMember member = new LinkshellMember(characterId, linkshellId, slot, rank); - memberList.Add(characterId, member); + LinkshellMember member = new LinkshellMember(characterId, linkshellId, rank); + memberList.Add(member); } } } @@ -192,6 +191,7 @@ namespace FFXIVClassic_World_Server conn.Dispose(); } } + memberList.Sort(); return memberList; } @@ -203,7 +203,7 @@ namespace FFXIVClassic_World_Server try { conn.Open(); - MySqlCommand cmd = new MySqlCommand("SELECT characterId, linkshellId, slot, rank FROM characters_linkshells WHERE characterid = @charaId", conn); + MySqlCommand cmd = new MySqlCommand("SELECT characterId, linkshellId, rank FROM characters_linkshells WHERE characterid = @charaId", conn); cmd.Parameters.AddWithValue("@lsId", charaId); using (MySqlDataReader Reader = cmd.ExecuteReader()) { @@ -211,10 +211,9 @@ namespace FFXIVClassic_World_Server { uint characterId = Reader.GetUInt32("characterId"); ulong linkshellId = Reader.GetUInt64("linkshellId"); - ushort slot = Reader.GetUInt16("slot"); - ushort rank = Reader.GetUInt16("rank"); + byte rank = Reader.GetByte("rank"); - LinkshellMember member = new LinkshellMember(characterId, linkshellId, slot, rank); + LinkshellMember member = new LinkshellMember(characterId, linkshellId, rank); memberList.Add(member); } } diff --git a/FFXIVClassic World Server/LinkshellManager.cs b/FFXIVClassic World Server/LinkshellManager.cs index 174f6f54..9b13c7b6 100644 --- a/FFXIVClassic World Server/LinkshellManager.cs +++ b/FFXIVClassic World Server/LinkshellManager.cs @@ -86,8 +86,7 @@ namespace FFXIVClassic_World_Server if (result) { - LinkshellMember newMember = new LinkshellMember(charaId, ls.dbId, 0, 0); - ls.members.Add(charaId, newMember); + ls.AddMember(charaId); return true; } else @@ -112,8 +111,7 @@ namespace FFXIVClassic_World_Server return false; //Remove from group instance - if (ls.members.ContainsKey(charaId)) - ls.members.Remove(charaId); + ls.RemoveMember(charaId); return true; } @@ -129,10 +127,10 @@ namespace FFXIVClassic_World_Server lock (mGroupLockReference) { Linkshell ls = Database.GetLinkshell(mServer.GetGroupIndex(), id); + ls.LoadMembers(); if (ls != null) - { - ls.members = Database.GetLSMembers(id); + { mLinkshellList.Add(id, ls); mCurrentWorldGroupsReference.Add(mServer.GetGroupIndex(), ls); mServer.IncrementGroupIndex(); diff --git a/FFXIVClassic World Server/Packets/Receive/Subpackets/GroupCreatedPacket.cs b/FFXIVClassic World Server/Packets/Receive/Subpackets/GroupCreatedPacket.cs new file mode 100644 index 00000000..f7135041 --- /dev/null +++ b/FFXIVClassic World Server/Packets/Receive/Subpackets/GroupCreatedPacket.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_World_Server.Packets.Receive.Subpackets +{ + class GroupCreatedPacket + { + public ulong groupId; + public string workString; + + public bool invalidPacket = false; + + public GroupCreatedPacket(byte[] data) + { + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryReader binReader = new BinaryReader(mem)) + { + try{ + groupId = binReader.ReadUInt64(); + workString = Encoding.ASCII.GetString(binReader.ReadBytes(0x20)).Trim(new[] { '\0' }); + } + catch (Exception){ + invalidPacket = true; + } + } + } + } + + } +} diff --git a/FFXIVClassic World Server/Server.cs b/FFXIVClassic World Server/Server.cs index c3ec0005..fca7e65f 100644 --- a/FFXIVClassic World Server/Server.cs +++ b/FFXIVClassic World Server/Server.cs @@ -1,6 +1,7 @@ using FFXIVClassic.Common; using FFXIVClassic_World_Server.DataObjects; using FFXIVClassic_World_Server.DataObjects.Group; +using FFXIVClassic_World_Server.Packets.Receive.Subpackets; using FFXIVClassic_World_Server.Packets.WorldPackets.Receive; using FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group; using System; @@ -161,12 +162,11 @@ namespace FFXIVClassic_World_Server public void OnReceiveSubPacketFromZone(ZoneServer zoneServer, SubPacket subpacket) { uint sessionId = subpacket.header.targetId; + Session session = GetSession(sessionId); if (subpacket.gameMessage.opcode >= 0x1000) { - subpacket.DebugPrintSubPacket(); - uint targetSession = subpacket.header.targetId; - Session session = GetSession(targetSession); + subpacket.DebugPrintSubPacket(); switch (subpacket.gameMessage.opcode) { @@ -236,6 +236,21 @@ namespace FFXIVClassic_World_Server break; } } + //Special case for groups. If it's a world group, send values, else send to zone server + else if (subpacket.gameMessage.opcode == 0x133) + { + GroupCreatedPacket groupCreatedPacket = new GroupCreatedPacket(subpacket.data); + if (mCurrentWorldGroups.ContainsKey(groupCreatedPacket.groupId)) + { + mCurrentWorldGroups[groupCreatedPacket.groupId].SendInitWorkValues(session); + } + else //Not a world group, send to zone server + { + ClientConnection conn = mZoneSessionList[sessionId].clientConnection; + conn.QueuePacket(subpacket, true, false); + conn.FlushQueuedSendPackets(); + } + } else if (mZoneSessionList.ContainsKey(sessionId)) { ClientConnection conn = mZoneSessionList[sessionId].clientConnection;