mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-02 19:42:05 -04:00
Fixed battle npcs appearing strangely (no nameplate, wrong colour, etc), and implemented content groups!
This commit is contained in:
parent
c6307dde35
commit
2de4934c41
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user