mirror of
				https://bitbucket.org/Ioncannon/project-meteor-server.git
				synced 2025-05-20 08:26:59 -04:00 
			
		
		
		
	Fixed battle npcs appearing strangely (no nameplate, wrong colour, etc), and implemented content groups!
This commit is contained in:
		| @@ -76,6 +76,7 @@ | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Compile Include="actors\area\PrivateArea.cs" /> | ||||
|     <Compile Include="actors\area\PrivateAreaContent.cs" /> | ||||
|     <Compile Include="actors\area\SpawnLocation.cs" /> | ||||
|     <Compile Include="actors\area\Zone.cs" /> | ||||
|     <Compile Include="actors\chara\npc\ActorClass.cs" /> | ||||
| @@ -88,11 +89,12 @@ | ||||
|     <Compile Include="actors\director\Director.cs" /> | ||||
|     <Compile Include="actors\EventList.cs" /> | ||||
|     <Compile Include="actors\group\ContentGroup.cs" /> | ||||
|     <Compile Include="actors\group\Work\ContentGroupWork.cs" /> | ||||
|     <Compile Include="actors\group\Work\GlobalTemp.cs" /> | ||||
|     <Compile Include="actors\group\Group.cs" /> | ||||
|     <Compile Include="actors\group\MonsterParty.cs" /> | ||||
|     <Compile Include="actors\group\Party.cs" /> | ||||
|     <Compile Include="actors\group\Relation.cs" /> | ||||
|     <Compile Include="actors\group\Work\ContentWork.cs" /> | ||||
|     <Compile Include="actors\group\Work\GroupGlobalSave.cs" /> | ||||
|     <Compile Include="actors\group\Work\GroupGlobalTemp.cs" /> | ||||
|     <Compile Include="actors\group\Work\GroupMemberSave.cs" /> | ||||
| @@ -209,9 +211,13 @@ | ||||
|     <Compile Include="packets\send\groups\GroupMember.cs" /> | ||||
|     <Compile Include="packets\send\groups\GroupMembersBeginPacket.cs" /> | ||||
|     <Compile Include="packets\send\groups\GroupMembersEndPacket.cs" /> | ||||
|     <Compile Include="packets\send\groups\ContentMembersX08Packet.cs" /> | ||||
|     <Compile Include="packets\send\groups\GroupMembersX08Packet.cs" /> | ||||
|     <Compile Include="packets\send\groups\ContentMembersX16Packet.cs" /> | ||||
|     <Compile Include="packets\send\groups\GroupMembersX16Packet.cs" /> | ||||
|     <Compile Include="packets\send\groups\ContentMembersX32Packet.cs" /> | ||||
|     <Compile Include="packets\send\groups\GroupMembersX32Packet.cs" /> | ||||
|     <Compile Include="packets\send\groups\ContentMembersX64Packet.cs" /> | ||||
|     <Compile Include="packets\send\groups\GroupMembersX64Packet.cs" /> | ||||
|     <Compile Include="packets\send\groups\SynchGroupWorkValuesPacket.cs" /> | ||||
|     <Compile Include="packets\send\player\InfoRequestResponsePacket.cs" /> | ||||
|   | ||||
| @@ -182,7 +182,7 @@ namespace FFXIVClassic_Map_Server | ||||
|                         if (ownerActor == null) | ||||
|                         { | ||||
|                             //Is it a instance actor? | ||||
|                             ownerActor = session.GetActor().zone.FindActorInZone(session.GetActor().currentEventOwner); | ||||
|                             ownerActor = session.GetActor().zone.FindActorInArea(session.GetActor().currentEventOwner); | ||||
|                             if (ownerActor == null) | ||||
|                             { | ||||
|                                 //Is it a Director? | ||||
| @@ -238,7 +238,7 @@ namespace FFXIVClassic_Map_Server | ||||
|                     //Group Created Confirm | ||||
|                     case 0x0133: | ||||
|                         GroupCreatedPacket groupCreated = new GroupCreatedPacket(subpacket.data); | ||||
|  | ||||
|                         Server.GetWorldManager().SendGroupInit(session, groupCreated.groupId); | ||||
|                         break; | ||||
|                     /* RECRUITMENT */ | ||||
|                     //Start Recruiting | ||||
|   | ||||
| @@ -36,13 +36,16 @@ namespace FFXIVClassic_Map_Server | ||||
|         private Dictionary<uint, ActorClass> actorClasses = new Dictionary<uint,ActorClass>(); | ||||
|         private Dictionary<ulong, Party> currentPlayerParties = new Dictionary<ulong, Party>(); //GroupId, Party object | ||||
|  | ||||
|         private Object groupLock = new Object(); | ||||
|  | ||||
|         private Server mServer; | ||||
|  | ||||
|         private const int MILIS_LOOPTIME = 10; | ||||
|         private Timer mZoneTimer; | ||||
|  | ||||
|         //Content Groups | ||||
|         public Dictionary<ulong, Group> mContentGroups = new Dictionary<ulong, Group>(); | ||||
|         private Object groupLock = new Object(); | ||||
|         public ulong groupIndexId = 1; | ||||
|  | ||||
|         public WorldManager(Server server) | ||||
|         { | ||||
|             mServer = server; | ||||
| @@ -693,6 +696,68 @@ namespace FFXIVClassic_Map_Server | ||||
|             //LoadNPCs(zone.actorId); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public ContentGroup CreateContentGroup(Director director) | ||||
|         { | ||||
|             return CreateContentGroup(director, null); | ||||
|         } | ||||
|  | ||||
|         public ContentGroup CreateContentGroup(Director director, params Actor[] actors) | ||||
|         { | ||||
|             if (director == null) | ||||
|                 return null; | ||||
|  | ||||
|             lock (groupLock) | ||||
|             { | ||||
|                 uint[] initialMembers = null; | ||||
|  | ||||
|                 if (actors != null) | ||||
|                 { | ||||
|                     initialMembers = new uint[actors.Length]; | ||||
|                     for (int i = 0; i < actors.Length; i++) | ||||
|                         initialMembers[i] = actors[i].actorId; | ||||
|                 } | ||||
|  | ||||
|                 groupIndexId = groupIndexId | 0x3000000000000000; | ||||
|  | ||||
|                 ContentGroup contentGroup = new ContentGroup(groupIndexId, director, initialMembers); | ||||
|                 mContentGroups.Add(groupIndexId, contentGroup); | ||||
|                 groupIndexId++; | ||||
|                 if (initialMembers != null && initialMembers.Length != 0) | ||||
|                     contentGroup.SendAll(); | ||||
|  | ||||
|                 return contentGroup; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void DeleteContentGroup(ulong groupId) | ||||
|         { | ||||
|             lock (groupLock) | ||||
|             { | ||||
|                 if (mContentGroups.ContainsKey(groupId) && mContentGroups[groupId] is ContentGroup) | ||||
|                 { | ||||
|                     ContentGroup group = (ContentGroup)mContentGroups[groupId]; | ||||
|                     group.SendDeletePackets(); | ||||
|                     mContentGroups.Remove(groupId); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void CreateContentArea(String scriptPath) | ||||
|         { | ||||
|             LuaScript script = LuaEngine.LoadScript(scriptPath); | ||||
|          | ||||
|         } | ||||
|  | ||||
|         public bool SendGroupInit(Session session, ulong groupId) | ||||
|         { | ||||
|             if (mContentGroups.ContainsKey(groupId)) | ||||
|             { | ||||
|                 mContentGroups[groupId].SendInitWorkValues(session); | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|          | ||||
|         public void RequestWorldLinkshellCreate(Player player, string name, ushort crest) | ||||
|         { | ||||
| @@ -857,7 +922,7 @@ namespace FFXIVClassic_Map_Server | ||||
|             { | ||||
|                 Actor a = zone.FindActorInZone(charId); | ||||
|                 if (a != null) | ||||
|                     return a; | ||||
|                     return a;                 | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|   | ||||
| @@ -1,376 +1,371 @@ | ||||
| using FFXIVClassic_Map_Server; | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.actors.area; | ||||
| using FFXIVClassic_Map_Server.actors.chara.npc; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.dataobjects.chara; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| using MoonSharp.Interpreter; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using FFXIVClassic_Map_Server; | ||||
| using FFXIVClassic.Common; | ||||
|  | ||||
| using FFXIVClassic_Map_Server.actors.area; | ||||
| using FFXIVClassic_Map_Server.actors.chara.npc; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.dataobjects.chara; | ||||
| using FFXIVClassic_Map_Server.lua; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| using MoonSharp.Interpreter; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using FFXIVClassic_Map_Server.packets.send; | ||||
| using FFXIVClassic_Map_Server.actors.group; | ||||
| using FFXIVClassic_Map_Server.actors.director; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.Actors | ||||
| { | ||||
|     class Area : Actor | ||||
|     { | ||||
|         public string zoneName;         | ||||
|         public ushort regionId; | ||||
|         public bool isIsolated, canStealth, isInn, canRideChocobo, isInstanceRaid; | ||||
|         public ushort weatherNormal, weatherCommon, weatherRare; | ||||
|         public ushort bgmDay, bgmNight, bgmBattle; | ||||
|  | ||||
|         protected string classPath; | ||||
|  | ||||
|         public int boundingGridSize = 50; | ||||
|         public int minX = -1000, minY = -1000, maxX = 1000, maxY = 1000; | ||||
|         protected int numXBlocks, numYBlocks; | ||||
| namespace FFXIVClassic_Map_Server.Actors | ||||
| { | ||||
|     class Area : Actor | ||||
|     { | ||||
|         public string zoneName;         | ||||
|         public ushort regionId; | ||||
|         public bool isIsolated, canStealth, isInn, canRideChocobo, isInstanceRaid; | ||||
|         public ushort weatherNormal, weatherCommon, weatherRare; | ||||
|         public ushort bgmDay, bgmNight, bgmBattle; | ||||
|  | ||||
|         protected string classPath; | ||||
|  | ||||
|         public int boundingGridSize = 50; | ||||
|         public int minX = -1000, minY = -1000, maxX = 1000, maxY = 1000; | ||||
|         protected int numXBlocks, numYBlocks; | ||||
|         protected int halfWidth, halfHeight; | ||||
|  | ||||
|         private Dictionary<uint, Director> currentDirectors = new Dictionary<uint, Director>(); | ||||
|         private Object directorLock = new Object(); | ||||
|         private uint directorIdCount = 0; | ||||
|  | ||||
|         protected Director mWeatherDirector; | ||||
|  | ||||
|         protected List<SpawnLocation> mSpawnLocations = new List<SpawnLocation>(); | ||||
|         protected Dictionary<uint, Actor> mActorList = new Dictionary<uint, Actor>(); | ||||
|         protected List<Actor>[,] mActorBlock; | ||||
|  | ||||
|         LuaScript areaScript; | ||||
|         protected Director mWeatherDirector; | ||||
|  | ||||
|         //Content Groups | ||||
|         public Dictionary<ulong, Group> mContentGroups = new Dictionary<ulong, Group>(); | ||||
|         private Object groupLock = new Object(); | ||||
|         public ulong groupIndexId = 0; | ||||
|  | ||||
|         public Area(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid) | ||||
|             : base(id) | ||||
|         { | ||||
|  | ||||
|             this.zoneName = zoneName; | ||||
|             this.regionId = regionId; | ||||
|             this.canStealth = canStealth; | ||||
|             this.isIsolated = isIsolated; | ||||
|             this.isInn = isInn; | ||||
|             this.canRideChocobo = canRideChocobo; | ||||
|             this.isInstanceRaid = isInstanceRaid; | ||||
|  | ||||
|             this.bgmDay = bgmDay; | ||||
|             this.bgmNight = bgmNight; | ||||
|             this.bgmBattle = bgmBattle; | ||||
|  | ||||
|             this.displayNameId = 0; | ||||
|             this.customDisplayName = "_areaMaster"; | ||||
|             this.actorName = String.Format("_areaMaster@{0:X5}",id<<8); | ||||
|  | ||||
|             this.className = className; | ||||
|  | ||||
|             numXBlocks = (maxX - minX) / boundingGridSize; | ||||
|             numYBlocks = (maxY - minY) / boundingGridSize; | ||||
|             mActorBlock = new List<Actor>[numXBlocks, numYBlocks]; | ||||
|             halfWidth = numXBlocks / 2; | ||||
|             halfHeight = numYBlocks / 2; | ||||
|  | ||||
|             for (int y = 0; y < numYBlocks; y++) | ||||
|             { | ||||
|                 for (int x = 0; x < numXBlocks; x++ ) | ||||
|                 { | ||||
|                     mActorBlock[x, y] = new List<Actor>(); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|         } | ||||
|  | ||||
|         public override SubPacket CreateScriptBindPacket(uint playerActorId) | ||||
|         { | ||||
|             List<LuaParam> lParams; | ||||
|             lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "/Area/Zone/ZoneDefault", -1, (byte)1, true, false, false, false, false, false, false, false); | ||||
|             return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, "ZoneDefault", lParams); | ||||
|         } | ||||
|  | ||||
|         public override BasePacket GetSpawnPackets(uint playerActorId) | ||||
|         { | ||||
|             List<SubPacket> subpackets = new List<SubPacket>(); | ||||
|             subpackets.Add(CreateAddActorPacket(playerActorId, 0));             | ||||
|             subpackets.Add(CreateSpeedPacket(playerActorId)); | ||||
|             subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1)); | ||||
|             subpackets.Add(CreateNamePacket(playerActorId)); | ||||
|             subpackets.Add(CreateStatePacket(playerActorId)); | ||||
|             subpackets.Add(CreateIsZoneingPacket(playerActorId)); | ||||
|             subpackets.Add(CreateScriptBindPacket(playerActorId)); | ||||
|             return BasePacket.CreatePacket(subpackets, true, false); | ||||
|         } | ||||
|  | ||||
|         #region Actor Management | ||||
|  | ||||
|         public void AddActorToZone(Actor actor) | ||||
|         { | ||||
|             if (!mActorList.ContainsKey(actor.actorId)) | ||||
|                 mActorList.Add(actor.actorId, actor); | ||||
|  | ||||
|             int gridX = (int)actor.positionX / boundingGridSize; | ||||
|             int gridY = (int)actor.positionZ / boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             lock (mActorBlock) | ||||
|                 mActorBlock[gridX, gridY].Add(actor); | ||||
|         } | ||||
|  | ||||
|         public void RemoveActorFromZone(Actor actor) | ||||
|         { | ||||
|             mActorList.Remove(actor.actorId); | ||||
|  | ||||
|             int gridX = (int)actor.positionX / boundingGridSize; | ||||
|             int gridY = (int)actor.positionZ / boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             lock (mActorBlock) | ||||
|                 mActorBlock[gridX, gridY].Remove(actor); | ||||
|         } | ||||
|  | ||||
|         public void UpdateActorPosition(Actor actor) | ||||
|         { | ||||
|             int gridX = (int)actor.positionX / boundingGridSize; | ||||
|             int gridY = (int)actor.positionZ / boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             int gridOldX = (int)actor.oldPositionX / boundingGridSize; | ||||
|             int gridOldY = (int)actor.oldPositionZ / boundingGridSize; | ||||
|  | ||||
|             gridOldX += halfWidth; | ||||
|             gridOldY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridOldX < 0) | ||||
|                 gridOldX = 0; | ||||
|             if (gridOldX >= numXBlocks) | ||||
|                 gridOldX = numXBlocks - 1; | ||||
|             if (gridOldY < 0) | ||||
|                 gridOldY = 0; | ||||
|             if (gridOldY >= numYBlocks) | ||||
|                 gridOldY = numYBlocks - 1; | ||||
|  | ||||
|             //Still in same block | ||||
|             if (gridX == gridOldX && gridY == gridOldY) | ||||
|                 return; | ||||
|  | ||||
|             lock (mActorBlock) | ||||
|             { | ||||
|                 mActorBlock[gridOldX, gridOldY].Remove(actor); | ||||
|                 mActorBlock[gridX, gridY].Add(actor); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public List<Actor> GetActorsAroundPoint(float x, float y, int checkDistance) | ||||
|         { | ||||
|             checkDistance /= boundingGridSize; | ||||
|  | ||||
|             int gridX = (int)x/boundingGridSize; | ||||
|             int gridY = (int)y/boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             List<Actor> result = new List<Actor>(); | ||||
|  | ||||
|             for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++) | ||||
|             { | ||||
|                 for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++) | ||||
|                 { | ||||
|                     result.AddRange(mActorBlock[gx, gy]); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             //Remove players if isolation zone | ||||
|             if (isIsolated) | ||||
|             { | ||||
|                 for (int i = 0; i < result.Count; i++) | ||||
|                 { | ||||
|                     if (result[i] is Player) | ||||
|                         result.RemoveAt(i); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         public List<Actor> GetActorsAroundActor(Actor actor, int checkDistance) | ||||
|         { | ||||
|             checkDistance /= boundingGridSize; | ||||
|  | ||||
|             int gridX = (int)actor.positionX / boundingGridSize; | ||||
|             int gridY = (int)actor.positionZ / boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             List<Actor> result = new List<Actor>(); | ||||
|  | ||||
|             for (int gy = ((gridY - checkDistance) < 0 ? 0 : (gridY - checkDistance)); gy <= ((gridY + checkDistance) >= numYBlocks ? numYBlocks - 1 : (gridY + checkDistance)); gy++) | ||||
|             { | ||||
|                 for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++) | ||||
|                 { | ||||
|                     result.AddRange(mActorBlock[gx, gy]); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             //Remove players if isolation zone | ||||
|             if (isIsolated) | ||||
|             { | ||||
|                 for (int i = 0; i < result.Count; i++) | ||||
|                 { | ||||
|                     if (result[i] is Player) | ||||
|                         result.RemoveAt(i); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         public Actor FindActorInZone(uint id) | ||||
|         { | ||||
|             if (!mActorList.ContainsKey(id)) | ||||
|                 return null; | ||||
|             return mActorList[id]; | ||||
|         protected List<SpawnLocation> mSpawnLocations = new List<SpawnLocation>(); | ||||
|         protected Dictionary<uint, Actor> mActorList = new Dictionary<uint, Actor>(); | ||||
|         protected List<Actor>[,] mActorBlock; | ||||
|  | ||||
|         LuaScript areaScript; | ||||
|          | ||||
|         public Area(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid) | ||||
|             : base(id) | ||||
|         { | ||||
|  | ||||
|             this.zoneName = zoneName; | ||||
|             this.regionId = regionId; | ||||
|             this.canStealth = canStealth; | ||||
|             this.isIsolated = isIsolated; | ||||
|             this.isInn = isInn; | ||||
|             this.canRideChocobo = canRideChocobo; | ||||
|             this.isInstanceRaid = isInstanceRaid; | ||||
|  | ||||
|             this.bgmDay = bgmDay; | ||||
|             this.bgmNight = bgmNight; | ||||
|             this.bgmBattle = bgmBattle; | ||||
|  | ||||
|             this.displayNameId = 0; | ||||
|             this.customDisplayName = "_areaMaster"; | ||||
|             this.actorName = String.Format("_areaMaster@{0:X5}",id<<8); | ||||
|  | ||||
|             this.className = className; | ||||
|  | ||||
|             numXBlocks = (maxX - minX) / boundingGridSize; | ||||
|             numYBlocks = (maxY - minY) / boundingGridSize; | ||||
|             mActorBlock = new List<Actor>[numXBlocks, numYBlocks]; | ||||
|             halfWidth = numXBlocks / 2; | ||||
|             halfHeight = numYBlocks / 2; | ||||
|  | ||||
|             for (int y = 0; y < numYBlocks; y++) | ||||
|             { | ||||
|                 for (int x = 0; x < numXBlocks; x++ ) | ||||
|                 { | ||||
|                     mActorBlock[x, y] = new List<Actor>(); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|         } | ||||
|  | ||||
|         public override SubPacket CreateScriptBindPacket(uint playerActorId) | ||||
|         { | ||||
|             List<LuaParam> lParams; | ||||
|             lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "/Area/Zone/ZoneDefault", -1, (byte)1, true, false, false, false, false, false, false, false); | ||||
|             return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, "ZoneDefault", lParams); | ||||
|         } | ||||
|  | ||||
|         public override BasePacket GetSpawnPackets(uint playerActorId) | ||||
|         { | ||||
|             List<SubPacket> subpackets = new List<SubPacket>(); | ||||
|             subpackets.Add(CreateAddActorPacket(playerActorId, 0));             | ||||
|             subpackets.Add(CreateSpeedPacket(playerActorId)); | ||||
|             subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1)); | ||||
|             subpackets.Add(CreateNamePacket(playerActorId)); | ||||
|             subpackets.Add(CreateStatePacket(playerActorId)); | ||||
|             subpackets.Add(CreateIsZoneingPacket(playerActorId)); | ||||
|             subpackets.Add(CreateScriptBindPacket(playerActorId)); | ||||
|             return BasePacket.CreatePacket(subpackets, true, false); | ||||
|         } | ||||
|  | ||||
|         #region Actor Management | ||||
|  | ||||
|         public void AddActorToZone(Actor actor) | ||||
|         { | ||||
|             if (!mActorList.ContainsKey(actor.actorId)) | ||||
|                 mActorList.Add(actor.actorId, actor); | ||||
|  | ||||
|             int gridX = (int)actor.positionX / boundingGridSize; | ||||
|             int gridY = (int)actor.positionZ / boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             lock (mActorBlock) | ||||
|                 mActorBlock[gridX, gridY].Add(actor); | ||||
|         } | ||||
|  | ||||
|         public void RemoveActorFromZone(Actor actor) | ||||
|         { | ||||
|             mActorList.Remove(actor.actorId); | ||||
|  | ||||
|             int gridX = (int)actor.positionX / boundingGridSize; | ||||
|             int gridY = (int)actor.positionZ / boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             lock (mActorBlock) | ||||
|                 mActorBlock[gridX, gridY].Remove(actor); | ||||
|         } | ||||
|  | ||||
|         public void UpdateActorPosition(Actor actor) | ||||
|         { | ||||
|             int gridX = (int)actor.positionX / boundingGridSize; | ||||
|             int gridY = (int)actor.positionZ / boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             int gridOldX = (int)actor.oldPositionX / boundingGridSize; | ||||
|             int gridOldY = (int)actor.oldPositionZ / boundingGridSize; | ||||
|  | ||||
|             gridOldX += halfWidth; | ||||
|             gridOldY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridOldX < 0) | ||||
|                 gridOldX = 0; | ||||
|             if (gridOldX >= numXBlocks) | ||||
|                 gridOldX = numXBlocks - 1; | ||||
|             if (gridOldY < 0) | ||||
|                 gridOldY = 0; | ||||
|             if (gridOldY >= numYBlocks) | ||||
|                 gridOldY = numYBlocks - 1; | ||||
|  | ||||
|             //Still in same block | ||||
|             if (gridX == gridOldX && gridY == gridOldY) | ||||
|                 return; | ||||
|  | ||||
|             lock (mActorBlock) | ||||
|             { | ||||
|                 mActorBlock[gridOldX, gridOldY].Remove(actor); | ||||
|                 mActorBlock[gridX, gridY].Add(actor); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public List<Actor> GetActorsAroundPoint(float x, float y, int checkDistance) | ||||
|         { | ||||
|             checkDistance /= boundingGridSize; | ||||
|  | ||||
|             int gridX = (int)x/boundingGridSize; | ||||
|             int gridY = (int)y/boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             List<Actor> result = new List<Actor>(); | ||||
|  | ||||
|             for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++) | ||||
|             { | ||||
|                 for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++) | ||||
|                 { | ||||
|                     result.AddRange(mActorBlock[gx, gy]); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             //Remove players if isolation zone | ||||
|             if (isIsolated) | ||||
|             { | ||||
|                 for (int i = 0; i < result.Count; i++) | ||||
|                 { | ||||
|                     if (result[i] is Player) | ||||
|                         result.RemoveAt(i); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         public List<Actor> GetActorsAroundActor(Actor actor, int checkDistance) | ||||
|         { | ||||
|             checkDistance /= boundingGridSize; | ||||
|  | ||||
|             int gridX = (int)actor.positionX / boundingGridSize; | ||||
|             int gridY = (int)actor.positionZ / boundingGridSize; | ||||
|  | ||||
|             gridX += halfWidth; | ||||
|             gridY += halfHeight; | ||||
|  | ||||
|             //Boundries | ||||
|             if (gridX < 0) | ||||
|                 gridX = 0; | ||||
|             if (gridX >= numXBlocks) | ||||
|                 gridX = numXBlocks - 1; | ||||
|             if (gridY < 0) | ||||
|                 gridY = 0; | ||||
|             if (gridY >= numYBlocks) | ||||
|                 gridY = numYBlocks - 1; | ||||
|  | ||||
|             List<Actor> result = new List<Actor>(); | ||||
|  | ||||
|             for (int gy = ((gridY - checkDistance) < 0 ? 0 : (gridY - checkDistance)); gy <= ((gridY + checkDistance) >= numYBlocks ? numYBlocks - 1 : (gridY + checkDistance)); gy++) | ||||
|             { | ||||
|                 for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++) | ||||
|                 { | ||||
|                     result.AddRange(mActorBlock[gx, gy]); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             //Remove players if isolation zone | ||||
|             if (isIsolated) | ||||
|             { | ||||
|                 for (int i = 0; i < result.Count; i++) | ||||
|                 { | ||||
|                     if (result[i] is Player) | ||||
|                         result.RemoveAt(i); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         public Actor FindActorInArea(uint id) | ||||
|         { | ||||
|             if (!mActorList.ContainsKey(id)) | ||||
|                 return null; | ||||
|             return mActorList[id]; | ||||
|         } | ||||
|  | ||||
|         public Actor FindActorInZoneByUniqueID(string uniqueId) | ||||
|         { | ||||
|             foreach (Actor a in mActorList.Values) | ||||
|             { | ||||
|                 if (a is Npc) | ||||
|             foreach (Actor a in mActorList.Values) | ||||
|             { | ||||
|                 if (a is Npc) | ||||
|                 { | ||||
|                     if (((Npc)a).GetUniqueId().ToLower().Equals(uniqueId)) | ||||
|                         return a; | ||||
|                 } | ||||
|             } | ||||
|                     if (((Npc)a).GetUniqueId().ToLower().Equals(uniqueId)) | ||||
|                         return a; | ||||
|                 } | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public Player FindPCInZone(string name) | ||||
|         { | ||||
|             foreach (Actor a in mActorList.Values) | ||||
|             { | ||||
|                 if (a is Player) | ||||
|                 { | ||||
|                     if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower())) | ||||
|                         return (Player)a; | ||||
|                 } | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public Player FindPCInZone(uint id) | ||||
|         { | ||||
|             if (!mActorList.ContainsKey(id)) | ||||
|                 return null; | ||||
|             return (Player)mActorList[id]; | ||||
|         } | ||||
|  | ||||
|         public void Clear() | ||||
|         { | ||||
|             //Clear All | ||||
|             mActorList.Clear(); | ||||
|             for (int y = 0; y < numYBlocks; y++) | ||||
|             { | ||||
|                 for (int x = 0; x < numXBlocks; x++) | ||||
|                 { | ||||
|                     mActorBlock[x, y].Clear(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void BroadcastPacketAroundActor(Actor actor, SubPacket packet) | ||||
|         { | ||||
|             if (isIsolated) | ||||
|                 return; | ||||
|  | ||||
|             List<Actor> aroundActor = GetActorsAroundActor(actor, 50); | ||||
|             foreach (Actor a in aroundActor) | ||||
|             {                 | ||||
|                 if (a is Player) | ||||
|                 { | ||||
|                     if (isIsolated && packet.header.sourceId != a.actorId) | ||||
|                         continue; | ||||
|  | ||||
|                     SubPacket clonedPacket = new SubPacket(packet, actor.actorId); | ||||
|                     Player p = (Player)a;                         | ||||
|                     p.QueuePacket(clonedPacket); | ||||
|                 } | ||||
|             }             | ||||
|         } | ||||
|  | ||||
|         public void SpawnActor(SpawnLocation location) | ||||
|         { | ||||
|             ActorClass actorClass = Server.GetWorldManager().GetActorClass(location.classId); | ||||
|              | ||||
|             if (actorClass == null) | ||||
|         } | ||||
|  | ||||
|         public Player FindPCInZone(string name) | ||||
|         { | ||||
|             foreach (Actor a in mActorList.Values) | ||||
|             { | ||||
|                 if (a is Player) | ||||
|                 { | ||||
|                     if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower())) | ||||
|                         return (Player)a; | ||||
|                 } | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public Player FindPCInZone(uint id) | ||||
|         { | ||||
|             if (!mActorList.ContainsKey(id)) | ||||
|                 return null; | ||||
|             return (Player)mActorList[id]; | ||||
|         } | ||||
|  | ||||
|         public void Clear() | ||||
|         { | ||||
|             //Clear All | ||||
|             mActorList.Clear(); | ||||
|             for (int y = 0; y < numYBlocks; y++) | ||||
|             { | ||||
|                 for (int x = 0; x < numXBlocks; x++) | ||||
|                 { | ||||
|                     mActorBlock[x, y].Clear(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void BroadcastPacketAroundActor(Actor actor, SubPacket packet) | ||||
|         { | ||||
|             if (isIsolated) | ||||
|                 return; | ||||
|  | ||||
|             List<Actor> aroundActor = GetActorsAroundActor(actor, 50); | ||||
|             foreach (Actor a in aroundActor) | ||||
|             {                 | ||||
|                 if (a is Player) | ||||
|                 { | ||||
|                     if (isIsolated && packet.header.sourceId != a.actorId) | ||||
|                         continue; | ||||
|  | ||||
|                     SubPacket clonedPacket = new SubPacket(packet, actor.actorId); | ||||
|                     Player p = (Player)a;                         | ||||
|                     p.QueuePacket(clonedPacket); | ||||
|                 } | ||||
|             }             | ||||
|         } | ||||
|  | ||||
|         public void SpawnActor(SpawnLocation location) | ||||
|         { | ||||
|             ActorClass actorClass = Server.GetWorldManager().GetActorClass(location.classId); | ||||
|              | ||||
|             if (actorClass == null) | ||||
|                 return; | ||||
|  | ||||
|             uint zoneId; | ||||
| @@ -378,21 +373,44 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             if (this is PrivateArea) | ||||
|                 zoneId = ((PrivateArea)this).GetParentZone().actorId; | ||||
|             else | ||||
|                 zoneId = actorId; | ||||
|  | ||||
|             Npc npc = new Npc(mActorList.Count + 1, actorClass, location.uniqueId, this, location.x, location.y, location.z, location.rot, location.state, location.animId, null); | ||||
|  | ||||
|  | ||||
|             npc.LoadEventConditions(actorClass.eventConditions);             | ||||
|  | ||||
|             AddActorToZone(npc);                           | ||||
|         } | ||||
|  | ||||
|                 zoneId = actorId; | ||||
|  | ||||
|             Npc npc = new Npc(mActorList.Count + 1, actorClass, location.uniqueId, this, location.x, location.y, location.z, location.rot, location.state, location.animId, null); | ||||
|  | ||||
|  | ||||
|             npc.LoadEventConditions(actorClass.eventConditions);             | ||||
|  | ||||
|             AddActorToZone(npc);                           | ||||
|         } | ||||
|  | ||||
|         public Npc SpawnActor(uint classId, string uniqueId, float x, float y, float z, float rot = 0, ushort state = 0, uint animId = 0) | ||||
|         { | ||||
|             ActorClass actorClass = Server.GetWorldManager().GetActorClass(classId); | ||||
|  | ||||
|             if (actorClass == null) | ||||
|                 return null; | ||||
|  | ||||
|             uint zoneId; | ||||
|  | ||||
|             if (this is PrivateArea) | ||||
|                 zoneId = ((PrivateArea)this).GetParentZone().actorId; | ||||
|             else | ||||
|                 zoneId = actorId; | ||||
|  | ||||
|             Npc npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null); | ||||
|  | ||||
|             npc.LoadEventConditions(actorClass.eventConditions); | ||||
|  | ||||
|             AddActorToZone(npc); | ||||
|  | ||||
|             return npc; | ||||
|         } | ||||
|  | ||||
|         public Director GetWeatherDirector() | ||||
|         { | ||||
|             return mWeatherDirector; | ||||
|         } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public void ChangeWeather(ushort weather, ushort transitionTime, Player player, bool zoneWide = false) | ||||
|         { | ||||
|             weatherNormal = weather; | ||||
| @@ -412,32 +430,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void CreateContentGroup(uint[] initialMembers) | ||||
|         { | ||||
|             lock (groupLock) | ||||
|             { | ||||
|                 ContentGroup contentGroup = new ContentGroup(groupIndexId, initialMembers == null ? new uint[0] : initialMembers); | ||||
|                 mContentGroups.Add(groupIndexId, contentGroup); | ||||
|                 groupIndexId++; | ||||
|                 if (initialMembers != null && initialMembers.Length != 0)                 | ||||
|                     contentGroup.SendAll();                 | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void DeleteContentGroup(ulong groupId) | ||||
|         { | ||||
|             lock (groupLock) | ||||
|             { | ||||
|                 if (mContentGroups.ContainsKey(groupId) && mContentGroups[groupId] is ContentGroup) | ||||
|                 { | ||||
|                     ContentGroup group = (ContentGroup) mContentGroups[groupId]; | ||||
|                     group.SendDeletePackets(); | ||||
|                     mContentGroups.Remove(groupId); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         }                 | ||||
|  | ||||
|         public Director CreateDirector(string path) | ||||
|         { | ||||
| @@ -472,7 +465,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|                 return currentDirectors[id]; | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public void Update(double deltaTime) | ||||
|         { | ||||
|             lock (mActorList) | ||||
| @@ -480,6 +473,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|                 foreach (Actor a in mActorList.Values) | ||||
|                     a.Update(deltaTime); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										16
									
								
								FFXIVClassic Map Server/actors/area/PrivateAreaContent.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								FFXIVClassic Map Server/actors/area/PrivateAreaContent.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.actors.area | ||||
| { | ||||
|     class PrivateAreaContent : PrivateArea | ||||
|     { | ||||
|         public PrivateAreaContent(Zone parent, uint id, string className, string privateAreaName, uint privateAreaType) | ||||
|             : base(parent, id, className, privateAreaName, privateAreaType, 0, 0, 0) | ||||
|         {          | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -16,7 +16,7 @@ namespace FFXIVClassic_Map_Server.actors.area | ||||
|     class Zone : Area | ||||
|     {         | ||||
|         Dictionary<string, Dictionary<uint, PrivateArea>> privateAreas = new Dictionary<string, Dictionary<uint, PrivateArea>>(); | ||||
|         Dictionary<string, List<PrivateArea>> instancedPrivateAreas = new Dictionary<string, List<PrivateArea>>(); | ||||
|         Dictionary<string, List<PrivateAreaContent>> contentAreas = new Dictionary<string, List<PrivateAreaContent>>(); | ||||
|  | ||||
|         public Zone(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid) | ||||
|             : base(id, zoneName, regionId, className, bgmDay, bgmNight, bgmBattle, isIsolated, isInn, canRideChocobo, canStealth, isInstanceRaid) | ||||
| @@ -93,5 +93,28 @@ namespace FFXIVClassic_Map_Server.actors.area | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public Actor FindActorInZone(uint id) | ||||
|         { | ||||
|             if (!mActorList.ContainsKey(id)) | ||||
|             { | ||||
|                 foreach(Dictionary<uint, PrivateArea> paList in privateAreas.Values) | ||||
|                 { | ||||
|                     foreach(PrivateArea pa in paList.Values) | ||||
|                     { | ||||
|                         Actor actor = pa.FindActorInArea(id); | ||||
|                         if (actor != null) | ||||
|                             return actor; | ||||
|                     } | ||||
|                 } | ||||
|                 return null; | ||||
|             } | ||||
|             else | ||||
|                 return mActorList[id]; | ||||
|         } | ||||
|  | ||||
|         public void CreateContentArea() | ||||
|         { | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.actors.group; | ||||
| using FFXIVClassic_Map_Server.Actors.Chara; | ||||
| using FFXIVClassic_Map_Server.packets.send.actor; | ||||
| using FFXIVClassic_Map_Server.utils; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.Actors | ||||
| { | ||||
| @@ -87,6 +88,18 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             player.QueuePacket(SetActorQuestGraphicPacket.BuildPacket(player.actorId, actorId, graphicNum)); | ||||
|         } | ||||
|  | ||||
|         public void SetCurrentContentGroup(uint groupType, Player player = null) | ||||
|         { | ||||
|             charaWork.currentContentGroup = groupType; | ||||
|  | ||||
|             if (player != null) | ||||
|             { | ||||
|                 ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/currentContentGroup", this, actorId); | ||||
|                 propPacketUtil.AddProperty("charaWork.currentContentGroup"); | ||||
|                 player.QueuePackets(propPacketUtil.Done()); | ||||
|             } | ||||
|         }         | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -206,6 +206,9 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|         { | ||||
|             ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this, playerActorId); | ||||
|  | ||||
|             //Potential | ||||
|             propPacketUtil.AddProperty("charaWork.battleSave.potencial"); | ||||
|  | ||||
|             //Properties | ||||
|             for (int i = 0; i < charaWork.property.Length; i++) | ||||
|             { | ||||
|   | ||||
| @@ -5,6 +5,6 @@ | ||||
|         public ushort pushCommand; | ||||
|         public int pushCommandSub; | ||||
|         public byte pushCommandPriority; | ||||
|         public byte hateType;                 | ||||
|         public byte hateType = 1;                 | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -552,7 +552,6 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|                 director.GetSpawnPackets(actorId).DebugPrintPacket(); | ||||
|                 QueuePacket(director.GetSpawnPackets(actorId)); | ||||
|                 QueuePacket(director.GetInitPackets(actorId)); | ||||
|                 //QueuePacket(director.GetSetEventStatusPackets(actorId)); | ||||
|             }         | ||||
|  | ||||
|         } | ||||
| @@ -634,7 +633,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|  | ||||
|         public void ChangeAnimation(uint animId) | ||||
|         { | ||||
|             Actor a = zone.FindActorInZone(currentTarget); | ||||
|             Actor a = zone.FindActorInArea(currentTarget); | ||||
|             if (a is Npc) | ||||
|                 ((Npc)a).animationId = animId; | ||||
|         } | ||||
| @@ -1323,6 +1322,13 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void SendDirectorPackets(Director director) | ||||
|         { | ||||
|             director.GetSpawnPackets(actorId).DebugPrintPacket(); | ||||
|             QueuePacket(director.GetSpawnPackets(actorId)); | ||||
|             QueuePacket(director.GetInitPackets(actorId));         | ||||
|         } | ||||
|  | ||||
|         public void RemoveDirector(Director director) | ||||
|         { | ||||
|             if (!ownedDirectors.Contains(director)) | ||||
|   | ||||
| @@ -1,7 +1,11 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using FFXIVClassic_Map_Server.actors.director; | ||||
| using FFXIVClassic_Map_Server.actors.group.Work; | ||||
| using FFXIVClassic_Map_Server.Actors; | ||||
| using FFXIVClassic_Map_Server.dataobjects; | ||||
| using FFXIVClassic_Map_Server.packets.send.group; | ||||
| using FFXIVClassic_Map_Server.packets.send.groups; | ||||
| using FFXIVClassic_Map_Server.utils; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| @@ -12,20 +16,36 @@ namespace FFXIVClassic_Map_Server.actors.group | ||||
| { | ||||
|     class ContentGroup : Group | ||||
|     { | ||||
|         public ContentGroupWork contentGroupWork = new ContentGroupWork(); | ||||
|         private Director director; | ||||
|         private List<uint> members = new List<uint>(); | ||||
|  | ||||
|         public ContentGroup(ulong groupIndex, uint[] initialMembers) : base(groupIndex) | ||||
|         public ContentGroup(ulong groupIndex, Director director, uint[] initialMembers) : base(groupIndex) | ||||
|         { | ||||
|             for (int i = 0; i < initialMembers.Length; i++) | ||||
|                 members.Add(initialMembers[i]); | ||||
|             if (initialMembers != null) | ||||
|             { | ||||
|                 for (int i = 0; i < initialMembers.Length; i++) | ||||
|                     members.Add(initialMembers[i]); | ||||
|             } | ||||
|  | ||||
|             this.director = director; | ||||
|             contentGroupWork._globalTemp.director = (ulong)director.actorId << 32; | ||||
|         } | ||||
|  | ||||
|         public void AddMember(uint memberId) | ||||
|         public void AddMember(Actor actor) | ||||
|         { | ||||
|             members.Add(memberId); | ||||
|             if (actor == null) | ||||
|                 return; | ||||
|  | ||||
|             members.Add(actor.actorId); | ||||
|             if (actor is Character) | ||||
|             { | ||||
|                 ((Character)actor).SetCurrentContentGroup(GetTypeId()); | ||||
|                 SendCurrentContentSync(actor); | ||||
|             } | ||||
|             SendGroupPacketsAll(members); | ||||
|         } | ||||
|  | ||||
|          | ||||
|         public void RemoveMember(uint memberId) | ||||
|         { | ||||
|             members.Remove(memberId); | ||||
| @@ -44,18 +64,68 @@ namespace FFXIVClassic_Map_Server.actors.group | ||||
|             return groupMembers; | ||||
|         } | ||||
|  | ||||
|         public override int GetMemberCount() | ||||
|         { | ||||
|             return members.Count; | ||||
|         } | ||||
|  | ||||
|         public override void SendInitWorkValues(Session session) | ||||
|         { | ||||
|             SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex);             | ||||
|             SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex); | ||||
|             groupWork.addProperty(this, "contentGroupWork._globalTemp.director"); | ||||
|             groupWork.addByte(Utils.MurmurHash2("contentGroupWork.property[0]", 0), 1); | ||||
|             groupWork.setTarget("/_init"); | ||||
|  | ||||
|             SubPacket test = groupWork.buildPacket(session.id, session.id); | ||||
|             test.DebugPrintSubPacket(); | ||||
|             session.QueuePacket(test, true, false); | ||||
|         } | ||||
|  | ||||
|         public override void SendGroupPackets(Session session) | ||||
|         { | ||||
|             ulong time = Utils.MilisUnixTimeStampUTC(); | ||||
|             List<GroupMember> members = BuildMemberList(session.id); | ||||
|  | ||||
|             session.QueuePacket(GroupHeaderPacket.buildPacket(session.id, session.GetActor().zoneId, time, this), true, false); | ||||
|             session.QueuePacket(GroupMembersBeginPacket.buildPacket(session.id, session.GetActor().zoneId, time, this), true, false); | ||||
|  | ||||
|             int currentIndex = 0; | ||||
|  | ||||
|             while (true) | ||||
|             { | ||||
|                 if (GetMemberCount() - currentIndex >= 64) | ||||
|                     session.QueuePacket(ContentMembersX64Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex), true, false); | ||||
|                 else if (GetMemberCount() - currentIndex >= 32) | ||||
|                     session.QueuePacket(ContentMembersX32Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex), true, false); | ||||
|                 else if (GetMemberCount() - currentIndex >= 16) | ||||
|                     session.QueuePacket(ContentMembersX16Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex), true, false); | ||||
|                 else if (GetMemberCount() - currentIndex > 0) | ||||
|                     session.QueuePacket(ContentMembersX08Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex), true, false); | ||||
|                 else | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|             session.QueuePacket(GroupMembersEndPacket.buildPacket(session.id, session.GetActor().zoneId, time, this), true, false); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public void SendCurrentContentSync(Actor currentContentChanged) | ||||
|         { | ||||
|             foreach (uint memberId in members) | ||||
|             { | ||||
|                 Session session = Server.GetServer().GetSession(memberId); | ||||
|                 if (session != null) | ||||
|                 { | ||||
|                     ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/currentContentGroup", currentContentChanged, session.id); | ||||
|                     propPacketUtil.AddProperty("charaWork.currentContentGroup"); | ||||
|                     session.GetActor().QueuePackets(propPacketUtil.Done()); | ||||
|                 } | ||||
|             }             | ||||
|         } | ||||
|  | ||||
|         public override uint GetTypeId() | ||||
|         { | ||||
|             return Group.ContentGroup_SimpleContentGroup24A; | ||||
|             return Group.ContentGroup_SimpleContentGroup24B; | ||||
|         } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -115,7 +115,7 @@ namespace FFXIVClassic_Map_Server.actors.group | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public void SendGroupPackets(Session session) | ||||
|         public virtual void SendGroupPackets(Session session) | ||||
|         { | ||||
|             ulong time = Utils.MilisUnixTimeStampUTC(); | ||||
|             List<GroupMember> members = BuildMemberList(session.id); | ||||
|   | ||||
| @@ -0,0 +1,13 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.actors.group.Work | ||||
| { | ||||
|     class ContentGroupWork | ||||
|     { | ||||
|         public GlobalTemp _globalTemp = new GlobalTemp(); | ||||
|         public bool[] property = new bool[32]; | ||||
|     } | ||||
| } | ||||
| @@ -2,12 +2,11 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| 
 | ||||
| namespace FFXIVClassic_Map_Server.actors.group.Work | ||||
| { | ||||
|     class ContentWork | ||||
|     class GlobalTemp | ||||
|     { | ||||
|         public GroupGlobalTemp _globalTemp = new GroupGlobalTemp(); | ||||
|         public ulong director; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,51 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.group | ||||
| { | ||||
|     class ContentMembersX08Packet | ||||
|     { | ||||
|         public const ushort OPCODE = 0x0183; | ||||
|         public const uint PACKET_SIZE = 0x1B8; | ||||
|  | ||||
|         public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, List<GroupMember> entries, ref int offset) | ||||
|         { | ||||
|             byte[] data = new byte[PACKET_SIZE - 0x20]; | ||||
|  | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryWriter binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     //Write List Header | ||||
|                     binWriter.Write((UInt64)locationCode); | ||||
|                     binWriter.Write((UInt64)sequenceId); | ||||
|                     //Write Entries | ||||
|                     int max = 8; | ||||
|                     if (entries.Count-offset < 8) | ||||
|                         max = entries.Count - offset; | ||||
|                     for (int i = 0; i < max; i++) | ||||
|                     { | ||||
|                         binWriter.Seek(0x10 + (0xC * i), SeekOrigin.Begin); | ||||
|  | ||||
|                         GroupMember entry = entries[i]; | ||||
|                         binWriter.Write((UInt32)entry.actorId); | ||||
|                         binWriter.Write((UInt32)1001); //Layout ID | ||||
|                         binWriter.Write((UInt32)1); //? | ||||
|  | ||||
|                         offset++; | ||||
|                     } | ||||
|                     //Write Count | ||||
|                     binWriter.Seek(0x10 + (0xC * 8), SeekOrigin.Begin); | ||||
|                     binWriter.Write(max); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return new SubPacket(OPCODE, playerActorID, playerActorID, data); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,48 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.group | ||||
| { | ||||
|     class ContentMembersX16Packet | ||||
|     { | ||||
|         public const ushort OPCODE = 0x0184; | ||||
|         public const uint PACKET_SIZE = 0xF0; | ||||
|  | ||||
|         public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, List<GroupMember> entries, ref int offset) | ||||
|         { | ||||
|             byte[] data = new byte[PACKET_SIZE - 0x20]; | ||||
|  | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryWriter binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     //Write List Header | ||||
|                     binWriter.Write((UInt64)locationCode); | ||||
|                     binWriter.Write((UInt64)sequenceId); | ||||
|                     //Write Entries | ||||
|                     int max = 16; | ||||
|                     if (entries.Count-offset < 16) | ||||
|                         max = entries.Count - offset; | ||||
|                     for (int i = 0; i < max; i++) | ||||
|                     { | ||||
|                         binWriter.Seek(0x10 + (0xC * i), SeekOrigin.Begin); | ||||
|  | ||||
|                         GroupMember entry = entries[i]; | ||||
|                         binWriter.Write((UInt32)entry.actorId); | ||||
|                         binWriter.Write((UInt32)1001); | ||||
|                         binWriter.Write((UInt32)1); | ||||
|  | ||||
|                         offset++; | ||||
|                     }                     | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return new SubPacket(OPCODE, playerActorID, playerActorID, data); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,48 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.group | ||||
| { | ||||
|     class ContentMembersX32Packet | ||||
|     { | ||||
|         public const ushort OPCODE = 0x0185; | ||||
|         public const uint PACKET_SIZE = 0x1B0; | ||||
|  | ||||
|         public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, List<GroupMember> entries, ref int offset) | ||||
|         { | ||||
|             byte[] data = new byte[PACKET_SIZE - 0x20]; | ||||
|  | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryWriter binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     //Write List Header | ||||
|                     binWriter.Write((UInt64)locationCode); | ||||
|                     binWriter.Write((UInt64)sequenceId); | ||||
|                     //Write Entries | ||||
|                     int max = 32; | ||||
|                     if (entries.Count-offset < 32) | ||||
|                         max = entries.Count - offset; | ||||
|                     for (int i = 0; i < max; i++) | ||||
|                     { | ||||
|                         binWriter.Seek(0x10 + (0xC * i), SeekOrigin.Begin); | ||||
|  | ||||
|                         GroupMember entry = entries[i]; | ||||
|                         binWriter.Write((UInt32)entry.actorId); | ||||
|                         binWriter.Write((UInt32)1001); | ||||
|                         binWriter.Write((UInt32)1); | ||||
|  | ||||
|                         offset++; | ||||
|                     }                     | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return new SubPacket(OPCODE, playerActorID, playerActorID, data); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,48 @@ | ||||
| using FFXIVClassic.Common; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace FFXIVClassic_Map_Server.packets.send.group | ||||
| { | ||||
|     class ContentMembersX64Packet | ||||
|     { | ||||
|         public const ushort OPCODE = 0x0186; | ||||
|         public const uint PACKET_SIZE = 0x330; | ||||
|  | ||||
|         public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, List<GroupMember> entries, ref int offset) | ||||
|         { | ||||
|             byte[] data = new byte[PACKET_SIZE - 0x20]; | ||||
|  | ||||
|             using (MemoryStream mem = new MemoryStream(data)) | ||||
|             { | ||||
|                 using (BinaryWriter binWriter = new BinaryWriter(mem)) | ||||
|                 { | ||||
|                     //Write List Header | ||||
|                     binWriter.Write((UInt64)locationCode); | ||||
|                     binWriter.Write((UInt64)sequenceId); | ||||
|                     //Write Entries | ||||
|                     int max = 64; | ||||
|                     if (entries.Count - offset < 64) | ||||
|                         max = entries.Count - offset; | ||||
|                     for (int i = 0; i < max; i++) | ||||
|                     { | ||||
|                         binWriter.Seek(0x10 + (0xC * i), SeekOrigin.Begin); | ||||
|  | ||||
|                         GroupMember entry = entries[i]; | ||||
|                         binWriter.Write((UInt32)entry.actorId); | ||||
|                         binWriter.Write((UInt32)1001); | ||||
|                         binWriter.Write((UInt32)1); | ||||
|  | ||||
|                         offset++; | ||||
|                     }                    | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return new SubPacket(OPCODE, playerActorID, playerActorID, data); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -18,7 +18,7 @@ namespace FFXIVClassic_Map_Server.packets.send.group | ||||
|             this.unknown2 = unknown2; | ||||
|             this.flag1 = flag1; | ||||
|             this.isOnline = isOnline; | ||||
|             this.name = name; | ||||
|             this.name = name == null ? "" : name; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -38,6 +38,7 @@ namespace FFXIVClassic_Map_Server.packets.send.group | ||||
|                         binWriter.Write((UInt32)entry.unknown2); | ||||
|                         binWriter.Write((Byte)(entry.flag1? 1 : 0)); | ||||
|                         binWriter.Write((Byte)(entry.isOnline? 1 : 0)); | ||||
|  | ||||
|                         binWriter.Write(Encoding.ASCII.GetBytes(entry.name), 0, Encoding.ASCII.GetByteCount(entry.name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(entry.name)); | ||||
|  | ||||
|                         offset++; | ||||
|   | ||||
| @@ -108,7 +108,7 @@ namespace FFXIVClassic_Map_Server.packets.send.groups | ||||
|             string[] split = name.Split('.'); | ||||
|             int arrayIndex = 0; | ||||
|  | ||||
|             if (!(split[0].Equals("work") || split[0].Equals("partyGroupWork"))) | ||||
|             if (!(split[0].Equals("work") || split[0].Equals("partyGroupWork") || split[0].Equals("contentGroupWork"))) | ||||
|                 return; | ||||
|  | ||||
|             Object curObj = group; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user