diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs index 4e4c1ece..8763eb00 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs @@ -80,6 +80,7 @@ namespace FFXIVClassic_Map_Server.Actors return AddActorPacket.BuildPacket(actorId, playerActorId, 8); } + int val = 0x0b00; // actorClassId, [], [], numBattleCommon, [battleCommon], numEventCommon, [eventCommon], args for either initForBattle/initForEvent public override SubPacket CreateScriptBindPacket(uint playerActorId) { @@ -88,6 +89,13 @@ namespace FFXIVClassic_Map_Server.Actors Player player = Server.GetWorldManager().GetPCInWorld(playerActorId); lParams = DoActorInit(player); + if (uniqueIdentifier.Equals("1")) + { + lParams[5].value = val; + val++; + player.SendMessage(0x20, "", String.Format("ID is now: 0x{0:X}", val)); + } + if (lParams != null && lParams.Count >= 3 && lParams[2].typeID == 0 && (int)lParams[2].value == 0) isStatic = true; @@ -114,15 +122,66 @@ namespace FFXIVClassic_Map_Server.Actors //ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams).DebugPrintSubPacket(); return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams); } - + public override BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType) { List subpackets = new List(); subpackets.Add(CreateAddActorPacket(playerActorId)); subpackets.AddRange(GetEventConditionPackets(playerActorId)); subpackets.Add(CreateSpeedPacket(playerActorId)); - subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x0)); - subpackets.Add(CreateAppearancePacket(playerActorId)); + subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x0)); + + if (uniqueIdentifier.Equals("door2")) + { + subpackets.Add(_0xD8Packet.BuildPacket(actorId, playerActorId, 0xB09, 0x1af)); + } + else if (uniqueIdentifier.Equals("uldah_mapshipport_1")) + { + subpackets.Add(_0xD8Packet.BuildPacket(actorId, playerActorId, 0xdc5, 0x1af)); + subpackets[subpackets.Count - 1].DebugPrintSubPacket(); + subpackets.Add(_0xD9Packet.BuildPacket(actorId, playerActorId, "end0")); + subpackets[subpackets.Count - 1].DebugPrintSubPacket(); + } + else if (uniqueIdentifier.Equals("uldah_mapshipport_2")) + { + subpackets.Add(_0xD8Packet.BuildPacket(actorId, playerActorId, 0x2, 0x1eb)); + subpackets[subpackets.Count - 1].DebugPrintSubPacket(); + subpackets.Add(_0xD9Packet.BuildPacket(actorId, playerActorId, "end0")); + subpackets[subpackets.Count - 1].DebugPrintSubPacket(); + } + else if (uniqueIdentifier.Equals("gridania_shipport")) + { + subpackets.Add(_0xD8Packet.BuildPacket(actorId,playerActorId, 0xcde, 0x141)); + subpackets.Add(_0xD9Packet.BuildPacket(actorId,playerActorId, "end0")); + } + else if (uniqueIdentifier.Equals("gridania_shipport2")) + { + subpackets.Add(_0xD8Packet.BuildPacket(actorId, playerActorId, 0x02, 0x187)); + subpackets.Add(_0xD9Packet.BuildPacket(actorId, playerActorId, "end0")); + } + else if (uniqueIdentifier.Equals("limsa_shipport")) + { + subpackets.Add(_0xD8Packet.BuildPacket(actorId, playerActorId, 0x1c8, 0xc4)); + subpackets.Add(_0xD9Packet.BuildPacket(actorId, playerActorId, "spin")); + } + else if (actorClassId == 5900013) + { + uint id = 2; + uint id2 = 5144; + string val = "fdot"; + subpackets.Add(_0xD8Packet.BuildPacket(actorId, playerActorId, id, id2)); + subpackets.Add(_0xD9Packet.BuildPacket(actorId, playerActorId, val)); + } + else if (actorClassId == 5900014) + { + uint id = 2; + uint id2 = 5145; + string val = "fdot"; + subpackets.Add(_0xD8Packet.BuildPacket(actorId, playerActorId, id, id2)); + subpackets.Add(_0xD9Packet.BuildPacket(actorId, playerActorId, val)); + } + else + subpackets.Add(CreateAppearancePacket(playerActorId)); subpackets.Add(CreateNamePacket(playerActorId)); subpackets.Add(CreateStatePacket(playerActorId)); subpackets.Add(CreateIdleAnimationPacket(playerActorId)); diff --git a/FFXIVClassic Map Server/dataobjects/Session.cs b/FFXIVClassic Map Server/dataobjects/Session.cs index 0ea83806..bdfcc561 100644 --- a/FFXIVClassic Map Server/dataobjects/Session.cs +++ b/FFXIVClassic Map Server/dataobjects/Session.cs @@ -82,7 +82,7 @@ namespace FFXIVClassic_Map_Server.dataobjects GetActor().zone.UpdateActorPosition(GetActor()); } - + long lastMilis = 0; public void UpdateInstance(List list) { if (isUpdatesLocked) @@ -95,11 +95,29 @@ namespace FFXIVClassic_Map_Server.dataobjects //Remove missing actors for (int i = 0; i < actorInstanceList.Count; i++) { + if (list.Contains(actorInstanceList[i]) && actorInstanceList[i] is Npc) + { + Npc npc = (Npc)actorInstanceList[i]; + + + long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; + + + if (npc.GetUniqueId().Equals("1") && milliseconds - lastMilis > 1000) + { + lastMilis = milliseconds; + GetActor().QueuePacket(RemoveActorPacket.BuildPacket(playerActor.actorId, actorInstanceList[i].actorId)); + actorInstanceList.RemoveAt(i); + continue; + } + } + if (!list.Contains(actorInstanceList[i])) { GetActor().QueuePacket(RemoveActorPacket.BuildPacket(playerActor.actorId, actorInstanceList[i].actorId)); actorInstanceList.RemoveAt(i); } + } //Add new actors or move diff --git a/FFXIVClassic World Server/DataObjects/Group/Party.cs b/FFXIVClassic World Server/DataObjects/Group/Party.cs index 3fc215fa..a4519a2b 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Party.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Party.cs @@ -29,6 +29,11 @@ namespace FFXIVClassic_World_Server.DataObjects.Group return (uint)(partyGroupWork._globalTemp.owner & 0xFFFFFF); } + public bool IsInParty(uint charaId) + { + return members.Contains(charaId); + } + public override void SendInitWorkValues(Session session) { SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex); diff --git a/FFXIVClassic World Server/FFXIVClassic World Server.csproj b/FFXIVClassic World Server/FFXIVClassic World Server.csproj index a8cfedad..3949d63f 100644 --- a/FFXIVClassic World Server/FFXIVClassic World Server.csproj +++ b/FFXIVClassic World Server/FFXIVClassic World Server.csproj @@ -64,12 +64,6 @@ - - - - - - @@ -93,6 +87,7 @@ + diff --git a/FFXIVClassic World Server/LinkshellManager.cs b/FFXIVClassic World Server/LinkshellManager.cs index 9b13c7b6..5b751a97 100644 --- a/FFXIVClassic World Server/LinkshellManager.cs +++ b/FFXIVClassic World Server/LinkshellManager.cs @@ -9,14 +9,14 @@ namespace FFXIVClassic_World_Server { class LinkshellManager { - private Server mServer; + private WorldManager mWorldManager; private Object mGroupLockReference; private Dictionary mCurrentWorldGroupsReference; private Dictionary mLinkshellList = new Dictionary(); - public LinkshellManager(Server server, Object groupLock, Dictionary worldGroupList) + public LinkshellManager(WorldManager worldManager, Object groupLock, Dictionary worldGroupList) { - mServer = server; + mWorldManager = worldManager; mGroupLockReference = groupLock; mCurrentWorldGroupsReference = worldGroupList; } @@ -29,14 +29,14 @@ namespace FFXIVClassic_World_Server ulong resultId = Database.CreateLinkshell(name, crest, master); if (resultId >= 0) { - Linkshell newLs = new Linkshell(resultId, mServer.GetGroupIndex(), name, crest, master, 0xa); + Linkshell newLs = new Linkshell(resultId, mWorldManager.GetGroupIndex(), name, crest, master, 0xa); //Add founder to the LS if (AddMemberToLinkshell(master, newLs.groupIndex)) { - mLinkshellList.Add(mServer.GetGroupIndex(), newLs); - mCurrentWorldGroupsReference.Add(mServer.GetGroupIndex(), newLs); - mServer.IncrementGroupIndex(); + mLinkshellList.Add(mWorldManager.GetGroupIndex(), newLs); + mCurrentWorldGroupsReference.Add(mWorldManager.GetGroupIndex(), newLs); + mWorldManager.IncrementGroupIndex(); } } return resultId; @@ -126,14 +126,14 @@ namespace FFXIVClassic_World_Server { lock (mGroupLockReference) { - Linkshell ls = Database.GetLinkshell(mServer.GetGroupIndex(), id); + Linkshell ls = Database.GetLinkshell(mWorldManager.GetGroupIndex(), id); ls.LoadMembers(); if (ls != null) { mLinkshellList.Add(id, ls); - mCurrentWorldGroupsReference.Add(mServer.GetGroupIndex(), ls); - mServer.IncrementGroupIndex(); + mCurrentWorldGroupsReference.Add(mWorldManager.GetGroupIndex(), ls); + mWorldManager.IncrementGroupIndex(); return ls; } } diff --git a/FFXIVClassic World Server/PartyManager.cs b/FFXIVClassic World Server/PartyManager.cs index b0bdb088..ae6cf642 100644 --- a/FFXIVClassic World Server/PartyManager.cs +++ b/FFXIVClassic World Server/PartyManager.cs @@ -6,27 +6,30 @@ namespace FFXIVClassic_World_Server { class PartyManager { - private Server mServer; + private WorldManager mWorldManager; private Object mGroupLockReference; private Dictionary mCurrentWorldGroupsReference; private Dictionary mPartyList = new Dictionary(); + private Dictionary mPlayerPartyLookup = new Dictionary(); - public PartyManager(Server server, Object groupLock, Dictionary worldGroupList) + public PartyManager(WorldManager worldManager, Object groupLock, Dictionary worldGroupList) { - mServer = server; + mWorldManager = worldManager; mGroupLockReference = groupLock; mCurrentWorldGroupsReference = worldGroupList; } - public void CreateParty(uint leaderCharaId) + public Party CreateParty(uint leaderCharaId) { lock (mGroupLockReference) { - ulong groupId = mServer.GetGroupIndex(); + ulong groupId = mWorldManager.GetGroupIndex(); Party party = new Party(groupId, leaderCharaId); mPartyList.Add(groupId, party); + mPlayerPartyLookup.Add(leaderCharaId, party); mCurrentWorldGroupsReference.Add(groupId, party); - mServer.IncrementGroupIndex(); + mWorldManager.IncrementGroupIndex(); + return party; } } @@ -44,7 +47,11 @@ namespace FFXIVClassic_World_Server { Party party = mPartyList[groupId]; if (!party.members.Contains(charaId)) + { party.members.Add(charaId); + mPlayerPartyLookup.Remove(charaId); + mPlayerPartyLookup.Add(charaId, party); + } return true; } return false; @@ -58,6 +65,7 @@ namespace FFXIVClassic_World_Server if (party.members.Contains(charaId)) { party.members.Remove(charaId); + mPlayerPartyLookup.Remove(charaId); //If current ldr, make a new ldr if not empty pt if (party.GetLeader() == charaId && party.members.Count != 0) @@ -81,5 +89,13 @@ namespace FFXIVClassic_World_Server } return false; } + + public Party GetParty(uint charaId) + { + if (mPlayerPartyLookup.ContainsKey(charaId)) + return mPlayerPartyLookup[charaId]; + else + return CreateParty(charaId); + } } } diff --git a/FFXIVClassic World Server/RelationGroupManager.cs b/FFXIVClassic World Server/RelationGroupManager.cs index 27d87749..974a950f 100644 --- a/FFXIVClassic World Server/RelationGroupManager.cs +++ b/FFXIVClassic World Server/RelationGroupManager.cs @@ -6,14 +6,14 @@ namespace FFXIVClassic_World_Server { class RelationGroupManager { - private Server mServer; + private WorldManager mWorldManager; private Object mGroupLockReference; private Dictionary mCurrentWorldGroupsReference; private Dictionary mRelationList = new Dictionary(); - public RelationGroupManager(Server server, Object groupLock, Dictionary worldGroupList) + public RelationGroupManager(WorldManager worldManager, Object groupLock, Dictionary worldGroupList) { - mServer = server; + mWorldManager = worldManager; mGroupLockReference = groupLock; mCurrentWorldGroupsReference = worldGroupList; } @@ -22,11 +22,11 @@ namespace FFXIVClassic_World_Server { lock (mGroupLockReference) { - ulong groupIndex = mServer.GetGroupIndex(); + ulong groupIndex = mWorldManager.GetGroupIndex(); Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, command); mRelationList.Add(groupIndex, relation); mCurrentWorldGroupsReference.Add(groupIndex, relation); - mServer.IncrementGroupIndex(); + mWorldManager.IncrementGroupIndex(); } } diff --git a/FFXIVClassic World Server/RetainerGroupManager.cs b/FFXIVClassic World Server/RetainerGroupManager.cs index fdcdf6f4..8f806a8f 100644 --- a/FFXIVClassic World Server/RetainerGroupManager.cs +++ b/FFXIVClassic World Server/RetainerGroupManager.cs @@ -9,14 +9,14 @@ namespace FFXIVClassic_World_Server { class RetainerGroupManager { - private Server mServer; + private WorldManager mWorldManager; private Object mGroupLockReference; private Dictionary mCurrentWorldGroupsReference; private Dictionary mRetainerGroupList = new Dictionary(); - public RetainerGroupManager(Server server, Object groupLock, Dictionary worldGroupList) + public RetainerGroupManager(WorldManager worldManager, Object groupLock, Dictionary worldGroupList) { - mServer = server; + mWorldManager = worldManager; mGroupLockReference = groupLock; mCurrentWorldGroupsReference = worldGroupList; } @@ -33,7 +33,7 @@ namespace FFXIVClassic_World_Server { lock(mGroupLockReference) { - ulong groupId = mServer.GetGroupIndex(); + ulong groupId = mWorldManager.GetGroupIndex(); RetainerGroup retainerGroup = new RetainerGroup(groupId, charaId); Dictionary members = Database.GetRetainers(charaId); @@ -44,7 +44,7 @@ namespace FFXIVClassic_World_Server mRetainerGroupList.Add(charaId, retainerGroup); mCurrentWorldGroupsReference.Add(groupId, retainerGroup); - mServer.IncrementGroupIndex(); + mWorldManager.IncrementGroupIndex(); return retainerGroup; } diff --git a/FFXIVClassic World Server/Server.cs b/FFXIVClassic World Server/Server.cs index fca7e65f..4c80709e 100644 --- a/FFXIVClassic World Server/Server.cs +++ b/FFXIVClassic World Server/Server.cs @@ -2,6 +2,7 @@ using FFXIVClassic_World_Server.DataObjects; using FFXIVClassic_World_Server.DataObjects.Group; using FFXIVClassic_World_Server.Packets.Receive.Subpackets; +using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups; using FFXIVClassic_World_Server.Packets.WorldPackets.Receive; using FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group; using System; @@ -29,25 +30,11 @@ namespace FFXIVClassic_World_Server //Session Management private List mConnectionList = new List(); private Dictionary mZoneSessionList = new Dictionary(); - private Dictionary mChatSessionList = new Dictionary(); - - //World Scope Group Management - private Object mGroupLock = new object(); - private ulong mRunningGroupIndex = 1; - private Dictionary mCurrentWorldGroups = new Dictionary(); - - private PartyManager mPartyManager; - private RetainerGroupManager mRetainerGroupManager; - private LinkshellManager mLinkshellManager; - private RelationGroupManager mRelationGroupManager; + private Dictionary mChatSessionList = new Dictionary(); public Server() { - mSelf = this; - mPartyManager = new PartyManager(this, mGroupLock, mCurrentWorldGroups); - mLinkshellManager = new LinkshellManager(this, mGroupLock, mCurrentWorldGroups); - mRetainerGroupManager = new RetainerGroupManager(this, mGroupLock, mCurrentWorldGroups); - mRelationGroupManager = new RelationGroupManager(this, mGroupLock, mCurrentWorldGroups); + mSelf = this; } public static Server GetServer() @@ -58,6 +45,9 @@ namespace FFXIVClassic_World_Server public bool StartServer() { mPacketProcessor = new PacketProcessor(this); + + LoadCharaNames(); + mWorldManager = new WorldManager(this); mWorldManager.LoadZoneServerList(); mWorldManager.LoadZoneEntranceList(); @@ -213,22 +203,22 @@ namespace FFXIVClassic_World_Server //Group get data request case 0x1020: GetGroupPacket getGroupPacket = new GetGroupPacket(subpacket.data); - SendGroupData(session, getGroupPacket.groupId); + mWorldManager.SendGroupData(session, getGroupPacket.groupId); break; //Group delete request case 0x1021: - DeleteGroupPacket deleteGroupPacket = new DeleteGroupPacket(subpacket.data); - DeleteGroup(deleteGroupPacket.groupId); + FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group.DeleteGroupPacket deleteGroupPacket = new FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group.DeleteGroupPacket(subpacket.data); + mWorldManager.DeleteGroup(deleteGroupPacket.groupId); break; //Linkshell create request case 0x1023: CreateLinkshellPacket createLinkshellpacket = new CreateLinkshellPacket(subpacket.data); - mLinkshellManager.CreateLinkshell(createLinkshellpacket.name, createLinkshellpacket.crestid, createLinkshellpacket.master); + mWorldManager.GetLinkshellManager().CreateLinkshell(createLinkshellpacket.name, createLinkshellpacket.crestid, createLinkshellpacket.master); break; //Linkshell modify request case 0x1024: ModifyLinkshellPacket modifyLinkshellpacket = new ModifyLinkshellPacket(subpacket.data); - mLinkshellManager.ModifyLinkshell(); + mWorldManager.GetLinkshellManager().ModifyLinkshell(); break; //Group Add/Remove Member case 0x1022: @@ -240,11 +230,7 @@ namespace FFXIVClassic_World_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 + if (!mWorldManager.SendGroupInit(session, groupCreatedPacket.groupId)) { ClientConnection conn = mZoneSessionList[sessionId].clientConnection; conn.QueuePacket(subpacket, true, false); @@ -412,68 +398,7 @@ namespace FFXIVClassic_World_Server if (mIdToNameMap.ContainsKey(charaId)) return mIdToNameMap[charaId]; return null; - } - - private void SendGroupData(Session session, ulong groupId) - { - if (mCurrentWorldGroups.ContainsKey(groupId)) - { - Group group = mCurrentWorldGroups[groupId]; - - } - } - - private void SendGroupDataToAllMembers(ulong groupId) - { - if (mCurrentWorldGroups.ContainsKey(groupId)) - { - Group group = mCurrentWorldGroups[groupId]; - - } - } - - public void GetGroup(Group group) - { - if (group is Party) - { - - } - else if (group is RetainerGroup) - { - - } - else if (group is Linkshell) - { - - } - else if (group is Relation) - { - - } - } - - public void DeleteGroup(ulong id) - { - if (!mCurrentWorldGroups.ContainsKey(id)) - return; - Group group = mCurrentWorldGroups[id]; - if (group is Party) - mPartyManager.DeleteParty(group.groupIndex); - else if (group is Linkshell) - mLinkshellManager.DeleteLinkshell(group.groupIndex); - else if (group is Relation) - mRelationGroupManager.DeleteRelationGroup(group.groupIndex); - } - - public void IncrementGroupIndex() - { - mRunningGroupIndex++; - } - - public ulong GetGroupIndex() - { - return mRunningGroupIndex; - } + } } } diff --git a/FFXIVClassic World Server/WorldMaster.cs b/FFXIVClassic World Server/WorldMaster.cs index 7d88bf31..eb1f4839 100644 --- a/FFXIVClassic World Server/WorldMaster.cs +++ b/FFXIVClassic World Server/WorldMaster.cs @@ -1,5 +1,7 @@ using FFXIVClassic.Common; using FFXIVClassic_World_Server.DataObjects; +using FFXIVClassic_World_Server.DataObjects.Group; +using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups; using FFXIVClassic_World_Server.Packets.WorldPackets.Send; using MySql.Data.MySqlClient; using System; @@ -18,9 +20,23 @@ namespace FFXIVClassic_World_Server public Dictionary mZoneServerList; private Dictionary zoneEntranceList; + //World Scope Group Management + private Object mGroupLock = new object(); + private ulong mRunningGroupIndex = 1; + private Dictionary mCurrentWorldGroups = new Dictionary(); + + private PartyManager mPartyManager; + private RetainerGroupManager mRetainerGroupManager; + private LinkshellManager mLinkshellManager; + private RelationGroupManager mRelationGroupManager; + public WorldManager(Server server) { mServer = server; + mPartyManager = new PartyManager(this, mGroupLock, mCurrentWorldGroups); + mLinkshellManager = new LinkshellManager(this, mGroupLock, mCurrentWorldGroups); + mRetainerGroupManager = new RetainerGroupManager(this, mGroupLock, mCurrentWorldGroups); + mRelationGroupManager = new RelationGroupManager(this, mGroupLock, mCurrentWorldGroups); } public void LoadZoneServerList() @@ -189,9 +205,9 @@ namespace FFXIVClassic_World_Server //Login Zone In public void DoLogin(Session session) - { + { session.routing1 = GetZoneServer(session.currentZoneId); - session.routing1.SendSessionStart(session); + session.routing1.SendSessionStart(session); } public class ZoneEntrance @@ -214,8 +230,74 @@ namespace FFXIVClassic_World_Server this.spawnZ = z; this.spawnRotation = rot; } - } + } + public void SendGroupData(Session session, ulong groupId) + { + if (mCurrentWorldGroups.ContainsKey(groupId)) + { + Group group = mCurrentWorldGroups[groupId]; + group.SendGroupPackets(session); + } + } + + public void SendGroupDataToAllMembers(ulong groupId) + { + if (mCurrentWorldGroups.ContainsKey(groupId)) + { + Group group = mCurrentWorldGroups[groupId]; + foreach (GroupMember member in group.BuildMemberList()) + group.SendGroupPackets(mServer.GetSession(member.actorId)); + } + } + + public void DeleteGroup(ulong id) + { + if (!mCurrentWorldGroups.ContainsKey(id)) + return; + Group group = mCurrentWorldGroups[id]; + if (group is Party) + mPartyManager.DeleteParty(group.groupIndex); + else if (group is Linkshell) + mLinkshellManager.DeleteLinkshell(group.groupIndex); + else if (group is Relation) + mRelationGroupManager.DeleteRelationGroup(group.groupIndex); + } + + public void IncrementGroupIndex() + { + mRunningGroupIndex++; + } + + public ulong GetGroupIndex() + { + return mRunningGroupIndex; + } + + public bool SendGroupInit(Session session, ulong groupId) + { + if (mCurrentWorldGroups.ContainsKey(groupId)) + { + mCurrentWorldGroups[groupId].SendInitWorkValues(session); + return true; + } + return false; + } + + public PartyManager GetPartyManager() + { + return mPartyManager; + } + + public RetainerGroupManager GetRetainerManager() + { + return mRetainerGroupManager; + } + + public LinkshellManager GetLinkshellManager() + { + return mLinkshellManager; + } } }