Fixed battle npcs appearing strangely (no nameplate, wrong colour, etc), and implemented content groups!

This commit is contained in:
Filip Maj 2017-04-15 16:33:56 -04:00
parent c6307dde35
commit 2de4934c41
21 changed files with 826 additions and 422 deletions

View File

@ -76,6 +76,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="actors\area\PrivateArea.cs" /> <Compile Include="actors\area\PrivateArea.cs" />
<Compile Include="actors\area\PrivateAreaContent.cs" />
<Compile Include="actors\area\SpawnLocation.cs" /> <Compile Include="actors\area\SpawnLocation.cs" />
<Compile Include="actors\area\Zone.cs" /> <Compile Include="actors\area\Zone.cs" />
<Compile Include="actors\chara\npc\ActorClass.cs" /> <Compile Include="actors\chara\npc\ActorClass.cs" />
@ -88,11 +89,12 @@
<Compile Include="actors\director\Director.cs" /> <Compile Include="actors\director\Director.cs" />
<Compile Include="actors\EventList.cs" /> <Compile Include="actors\EventList.cs" />
<Compile Include="actors\group\ContentGroup.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\Group.cs" />
<Compile Include="actors\group\MonsterParty.cs" /> <Compile Include="actors\group\MonsterParty.cs" />
<Compile Include="actors\group\Party.cs" /> <Compile Include="actors\group\Party.cs" />
<Compile Include="actors\group\Relation.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\GroupGlobalSave.cs" />
<Compile Include="actors\group\Work\GroupGlobalTemp.cs" /> <Compile Include="actors\group\Work\GroupGlobalTemp.cs" />
<Compile Include="actors\group\Work\GroupMemberSave.cs" /> <Compile Include="actors\group\Work\GroupMemberSave.cs" />
@ -209,9 +211,13 @@
<Compile Include="packets\send\groups\GroupMember.cs" /> <Compile Include="packets\send\groups\GroupMember.cs" />
<Compile Include="packets\send\groups\GroupMembersBeginPacket.cs" /> <Compile Include="packets\send\groups\GroupMembersBeginPacket.cs" />
<Compile Include="packets\send\groups\GroupMembersEndPacket.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\GroupMembersX08Packet.cs" />
<Compile Include="packets\send\groups\ContentMembersX16Packet.cs" />
<Compile Include="packets\send\groups\GroupMembersX16Packet.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\GroupMembersX32Packet.cs" />
<Compile Include="packets\send\groups\ContentMembersX64Packet.cs" />
<Compile Include="packets\send\groups\GroupMembersX64Packet.cs" /> <Compile Include="packets\send\groups\GroupMembersX64Packet.cs" />
<Compile Include="packets\send\groups\SynchGroupWorkValuesPacket.cs" /> <Compile Include="packets\send\groups\SynchGroupWorkValuesPacket.cs" />
<Compile Include="packets\send\player\InfoRequestResponsePacket.cs" /> <Compile Include="packets\send\player\InfoRequestResponsePacket.cs" />

View File

@ -182,7 +182,7 @@ namespace FFXIVClassic_Map_Server
if (ownerActor == null) if (ownerActor == null)
{ {
//Is it a instance actor? //Is it a instance actor?
ownerActor = session.GetActor().zone.FindActorInZone(session.GetActor().currentEventOwner); ownerActor = session.GetActor().zone.FindActorInArea(session.GetActor().currentEventOwner);
if (ownerActor == null) if (ownerActor == null)
{ {
//Is it a Director? //Is it a Director?
@ -238,7 +238,7 @@ namespace FFXIVClassic_Map_Server
//Group Created Confirm //Group Created Confirm
case 0x0133: case 0x0133:
GroupCreatedPacket groupCreated = new GroupCreatedPacket(subpacket.data); GroupCreatedPacket groupCreated = new GroupCreatedPacket(subpacket.data);
Server.GetWorldManager().SendGroupInit(session, groupCreated.groupId);
break; break;
/* RECRUITMENT */ /* RECRUITMENT */
//Start Recruiting //Start Recruiting

View File

@ -36,13 +36,16 @@ namespace FFXIVClassic_Map_Server
private Dictionary<uint, ActorClass> actorClasses = new Dictionary<uint,ActorClass>(); private Dictionary<uint, ActorClass> actorClasses = new Dictionary<uint,ActorClass>();
private Dictionary<ulong, Party> currentPlayerParties = new Dictionary<ulong, Party>(); //GroupId, Party object private Dictionary<ulong, Party> currentPlayerParties = new Dictionary<ulong, Party>(); //GroupId, Party object
private Object groupLock = new Object();
private Server mServer; private Server mServer;
private const int MILIS_LOOPTIME = 10; private const int MILIS_LOOPTIME = 10;
private Timer mZoneTimer; 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) public WorldManager(Server server)
{ {
mServer = server; mServer = server;
@ -693,6 +696,68 @@ namespace FFXIVClassic_Map_Server
//LoadNPCs(zone.actorId); //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) public void RequestWorldLinkshellCreate(Player player, string name, ushort crest)
{ {
@ -857,7 +922,7 @@ namespace FFXIVClassic_Map_Server
{ {
Actor a = zone.FindActorInZone(charId); Actor a = zone.FindActorInZone(charId);
if (a != null) if (a != null)
return a; return a;
} }
return null; return null;
} }

View File

@ -1,376 +1,371 @@
using FFXIVClassic_Map_Server; using FFXIVClassic_Map_Server;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.area; using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.actors.chara.npc; using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.dataobjects.chara; using FFXIVClassic_Map_Server.dataobjects.chara;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
using MoonSharp.Interpreter; using MoonSharp.Interpreter;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FFXIVClassic_Map_Server.packets.send; using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.actors.group; using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.actors.director; using FFXIVClassic_Map_Server.actors.director;
namespace FFXIVClassic_Map_Server.Actors namespace FFXIVClassic_Map_Server.Actors
{ {
class Area : Actor class Area : Actor
{ {
public string zoneName; public string zoneName;
public ushort regionId; public ushort regionId;
public bool isIsolated, canStealth, isInn, canRideChocobo, isInstanceRaid; public bool isIsolated, canStealth, isInn, canRideChocobo, isInstanceRaid;
public ushort weatherNormal, weatherCommon, weatherRare; public ushort weatherNormal, weatherCommon, weatherRare;
public ushort bgmDay, bgmNight, bgmBattle; public ushort bgmDay, bgmNight, bgmBattle;
protected string classPath; protected string classPath;
public int boundingGridSize = 50; public int boundingGridSize = 50;
public int minX = -1000, minY = -1000, maxX = 1000, maxY = 1000; public int minX = -1000, minY = -1000, maxX = 1000, maxY = 1000;
protected int numXBlocks, numYBlocks; protected int numXBlocks, numYBlocks;
protected int halfWidth, halfHeight; protected int halfWidth, halfHeight;
private Dictionary<uint, Director> currentDirectors = new Dictionary<uint, Director>(); private Dictionary<uint, Director> currentDirectors = new Dictionary<uint, Director>();
private Object directorLock = new Object(); private Object directorLock = new Object();
private uint directorIdCount = 0; private uint directorIdCount = 0;
protected Director mWeatherDirector; 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;
//Content Groups protected List<SpawnLocation> mSpawnLocations = new List<SpawnLocation>();
public Dictionary<ulong, Group> mContentGroups = new Dictionary<ulong, Group>(); protected Dictionary<uint, Actor> mActorList = new Dictionary<uint, Actor>();
private Object groupLock = new Object(); protected List<Actor>[,] mActorBlock;
public ulong groupIndexId = 0;
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) 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.zoneName = zoneName;
this.canStealth = canStealth; this.regionId = regionId;
this.isIsolated = isIsolated; this.canStealth = canStealth;
this.isInn = isInn; this.isIsolated = isIsolated;
this.canRideChocobo = canRideChocobo; this.isInn = isInn;
this.isInstanceRaid = isInstanceRaid; this.canRideChocobo = canRideChocobo;
this.isInstanceRaid = isInstanceRaid;
this.bgmDay = bgmDay;
this.bgmNight = bgmNight; this.bgmDay = bgmDay;
this.bgmBattle = bgmBattle; this.bgmNight = bgmNight;
this.bgmBattle = bgmBattle;
this.displayNameId = 0;
this.customDisplayName = "_areaMaster"; this.displayNameId = 0;
this.actorName = String.Format("_areaMaster@{0:X5}",id<<8); this.customDisplayName = "_areaMaster";
this.actorName = String.Format("_areaMaster@{0:X5}",id<<8);
this.className = className;
this.className = className;
numXBlocks = (maxX - minX) / boundingGridSize;
numYBlocks = (maxY - minY) / boundingGridSize; numXBlocks = (maxX - minX) / boundingGridSize;
mActorBlock = new List<Actor>[numXBlocks, numYBlocks]; numYBlocks = (maxY - minY) / boundingGridSize;
halfWidth = numXBlocks / 2; mActorBlock = new List<Actor>[numXBlocks, numYBlocks];
halfHeight = numYBlocks / 2; halfWidth = numXBlocks / 2;
halfHeight = numYBlocks / 2;
for (int y = 0; y < numYBlocks; y++)
{ for (int y = 0; y < numYBlocks; y++)
for (int x = 0; x < numXBlocks; x++ ) {
{ for (int x = 0; x < numXBlocks; x++ )
mActorBlock[x, y] = new List<Actor>(); {
} mActorBlock[x, y] = new List<Actor>();
} }
}
}
}
public override SubPacket CreateScriptBindPacket(uint playerActorId)
{ 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); List<LuaParam> lParams;
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, "ZoneDefault", 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)
{ public override BasePacket GetSpawnPackets(uint playerActorId)
List<SubPacket> subpackets = new List<SubPacket>(); {
subpackets.Add(CreateAddActorPacket(playerActorId, 0)); List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateSpeedPacket(playerActorId)); subpackets.Add(CreateAddActorPacket(playerActorId, 0));
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1)); subpackets.Add(CreateSpeedPacket(playerActorId));
subpackets.Add(CreateNamePacket(playerActorId)); subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1));
subpackets.Add(CreateStatePacket(playerActorId)); subpackets.Add(CreateNamePacket(playerActorId));
subpackets.Add(CreateIsZoneingPacket(playerActorId)); subpackets.Add(CreateStatePacket(playerActorId));
subpackets.Add(CreateScriptBindPacket(playerActorId)); subpackets.Add(CreateIsZoneingPacket(playerActorId));
return BasePacket.CreatePacket(subpackets, true, false); subpackets.Add(CreateScriptBindPacket(playerActorId));
} return BasePacket.CreatePacket(subpackets, true, false);
}
#region Actor Management
#region Actor Management
public void AddActorToZone(Actor actor)
{ public void AddActorToZone(Actor actor)
if (!mActorList.ContainsKey(actor.actorId)) {
mActorList.Add(actor.actorId, actor); if (!mActorList.ContainsKey(actor.actorId))
mActorList.Add(actor.actorId, actor);
int gridX = (int)actor.positionX / boundingGridSize;
int gridY = (int)actor.positionZ / boundingGridSize; int gridX = (int)actor.positionX / boundingGridSize;
int gridY = (int)actor.positionZ / boundingGridSize;
gridX += halfWidth;
gridY += halfHeight; gridX += halfWidth;
gridY += halfHeight;
//Boundries
if (gridX < 0) //Boundries
gridX = 0; if (gridX < 0)
if (gridX >= numXBlocks) gridX = 0;
gridX = numXBlocks - 1; if (gridX >= numXBlocks)
if (gridY < 0) gridX = numXBlocks - 1;
gridY = 0; if (gridY < 0)
if (gridY >= numYBlocks) gridY = 0;
gridY = numYBlocks - 1; if (gridY >= numYBlocks)
gridY = numYBlocks - 1;
lock (mActorBlock)
mActorBlock[gridX, gridY].Add(actor); lock (mActorBlock)
} mActorBlock[gridX, gridY].Add(actor);
}
public void RemoveActorFromZone(Actor actor)
{ public void RemoveActorFromZone(Actor actor)
mActorList.Remove(actor.actorId); {
mActorList.Remove(actor.actorId);
int gridX = (int)actor.positionX / boundingGridSize;
int gridY = (int)actor.positionZ / boundingGridSize; int gridX = (int)actor.positionX / boundingGridSize;
int gridY = (int)actor.positionZ / boundingGridSize;
gridX += halfWidth;
gridY += halfHeight; gridX += halfWidth;
gridY += halfHeight;
//Boundries
if (gridX < 0) //Boundries
gridX = 0; if (gridX < 0)
if (gridX >= numXBlocks) gridX = 0;
gridX = numXBlocks - 1; if (gridX >= numXBlocks)
if (gridY < 0) gridX = numXBlocks - 1;
gridY = 0; if (gridY < 0)
if (gridY >= numYBlocks) gridY = 0;
gridY = numYBlocks - 1; if (gridY >= numYBlocks)
gridY = numYBlocks - 1;
lock (mActorBlock)
mActorBlock[gridX, gridY].Remove(actor); lock (mActorBlock)
} mActorBlock[gridX, gridY].Remove(actor);
}
public void UpdateActorPosition(Actor actor)
{ public void UpdateActorPosition(Actor actor)
int gridX = (int)actor.positionX / boundingGridSize; {
int gridY = (int)actor.positionZ / boundingGridSize; int gridX = (int)actor.positionX / boundingGridSize;
int gridY = (int)actor.positionZ / boundingGridSize;
gridX += halfWidth;
gridY += halfHeight; gridX += halfWidth;
gridY += halfHeight;
//Boundries
if (gridX < 0) //Boundries
gridX = 0; if (gridX < 0)
if (gridX >= numXBlocks) gridX = 0;
gridX = numXBlocks - 1; if (gridX >= numXBlocks)
if (gridY < 0) gridX = numXBlocks - 1;
gridY = 0; if (gridY < 0)
if (gridY >= numYBlocks) gridY = 0;
gridY = numYBlocks - 1; if (gridY >= numYBlocks)
gridY = numYBlocks - 1;
int gridOldX = (int)actor.oldPositionX / boundingGridSize;
int gridOldY = (int)actor.oldPositionZ / boundingGridSize; int gridOldX = (int)actor.oldPositionX / boundingGridSize;
int gridOldY = (int)actor.oldPositionZ / boundingGridSize;
gridOldX += halfWidth;
gridOldY += halfHeight; gridOldX += halfWidth;
gridOldY += halfHeight;
//Boundries
if (gridOldX < 0) //Boundries
gridOldX = 0; if (gridOldX < 0)
if (gridOldX >= numXBlocks) gridOldX = 0;
gridOldX = numXBlocks - 1; if (gridOldX >= numXBlocks)
if (gridOldY < 0) gridOldX = numXBlocks - 1;
gridOldY = 0; if (gridOldY < 0)
if (gridOldY >= numYBlocks) gridOldY = 0;
gridOldY = numYBlocks - 1; if (gridOldY >= numYBlocks)
gridOldY = numYBlocks - 1;
//Still in same block
if (gridX == gridOldX && gridY == gridOldY) //Still in same block
return; if (gridX == gridOldX && gridY == gridOldY)
return;
lock (mActorBlock)
{ lock (mActorBlock)
mActorBlock[gridOldX, gridOldY].Remove(actor); {
mActorBlock[gridX, gridY].Add(actor); mActorBlock[gridOldX, gridOldY].Remove(actor);
} mActorBlock[gridX, gridY].Add(actor);
} }
}
public List<Actor> GetActorsAroundPoint(float x, float y, int checkDistance)
{ public List<Actor> GetActorsAroundPoint(float x, float y, int checkDistance)
checkDistance /= boundingGridSize; {
checkDistance /= boundingGridSize;
int gridX = (int)x/boundingGridSize;
int gridY = (int)y/boundingGridSize; int gridX = (int)x/boundingGridSize;
int gridY = (int)y/boundingGridSize;
gridX += halfWidth;
gridY += halfHeight; gridX += halfWidth;
gridY += halfHeight;
//Boundries
if (gridX < 0) //Boundries
gridX = 0; if (gridX < 0)
if (gridX >= numXBlocks) gridX = 0;
gridX = numXBlocks - 1; if (gridX >= numXBlocks)
if (gridY < 0) gridX = numXBlocks - 1;
gridY = 0; if (gridY < 0)
if (gridY >= numYBlocks) gridY = 0;
gridY = numYBlocks - 1; if (gridY >= numYBlocks)
gridY = numYBlocks - 1;
List<Actor> result = new List<Actor>();
List<Actor> result = new List<Actor>();
for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++)
{ for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++)
for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++) {
{ for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++)
result.AddRange(mActorBlock[gx, gy]); {
} result.AddRange(mActorBlock[gx, gy]);
} }
}
//Remove players if isolation zone
if (isIsolated) //Remove players if isolation zone
{ if (isIsolated)
for (int i = 0; i < result.Count; i++) {
{ for (int i = 0; i < result.Count; i++)
if (result[i] is Player) {
result.RemoveAt(i); if (result[i] is Player)
} result.RemoveAt(i);
} }
}
return result;
} return result;
}
public List<Actor> GetActorsAroundActor(Actor actor, int checkDistance)
{ public List<Actor> GetActorsAroundActor(Actor actor, int checkDistance)
checkDistance /= boundingGridSize; {
checkDistance /= boundingGridSize;
int gridX = (int)actor.positionX / boundingGridSize;
int gridY = (int)actor.positionZ / boundingGridSize; int gridX = (int)actor.positionX / boundingGridSize;
int gridY = (int)actor.positionZ / boundingGridSize;
gridX += halfWidth;
gridY += halfHeight; gridX += halfWidth;
gridY += halfHeight;
//Boundries
if (gridX < 0) //Boundries
gridX = 0; if (gridX < 0)
if (gridX >= numXBlocks) gridX = 0;
gridX = numXBlocks - 1; if (gridX >= numXBlocks)
if (gridY < 0) gridX = numXBlocks - 1;
gridY = 0; if (gridY < 0)
if (gridY >= numYBlocks) gridY = 0;
gridY = numYBlocks - 1; if (gridY >= numYBlocks)
gridY = numYBlocks - 1;
List<Actor> result = new List<Actor>();
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 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++) {
{ for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++)
result.AddRange(mActorBlock[gx, gy]); {
} result.AddRange(mActorBlock[gx, gy]);
} }
}
//Remove players if isolation zone
if (isIsolated) //Remove players if isolation zone
{ if (isIsolated)
for (int i = 0; i < result.Count; i++) {
{ for (int i = 0; i < result.Count; i++)
if (result[i] is Player) {
result.RemoveAt(i); if (result[i] is Player)
} result.RemoveAt(i);
} }
}
return result;
} return result;
}
#endregion
#endregion
public Actor FindActorInZone(uint id)
{ public Actor FindActorInArea(uint id)
if (!mActorList.ContainsKey(id)) {
return null; if (!mActorList.ContainsKey(id))
return mActorList[id]; return null;
return mActorList[id];
} }
public Actor FindActorInZoneByUniqueID(string uniqueId) public Actor FindActorInZoneByUniqueID(string uniqueId)
{ {
foreach (Actor a in mActorList.Values) foreach (Actor a in mActorList.Values)
{ {
if (a is Npc) if (a is Npc)
{ {
if (((Npc)a).GetUniqueId().ToLower().Equals(uniqueId)) if (((Npc)a).GetUniqueId().ToLower().Equals(uniqueId))
return a; return a;
} }
} }
return null; return null;
} }
public Player FindPCInZone(string name) public Player FindPCInZone(string name)
{ {
foreach (Actor a in mActorList.Values) foreach (Actor a in mActorList.Values)
{ {
if (a is Player) if (a is Player)
{ {
if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower())) if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower()))
return (Player)a; return (Player)a;
} }
} }
return null; return null;
} }
public Player FindPCInZone(uint id) public Player FindPCInZone(uint id)
{ {
if (!mActorList.ContainsKey(id)) if (!mActorList.ContainsKey(id))
return null; return null;
return (Player)mActorList[id]; return (Player)mActorList[id];
} }
public void Clear() public void Clear()
{ {
//Clear All //Clear All
mActorList.Clear(); mActorList.Clear();
for (int y = 0; y < numYBlocks; y++) for (int y = 0; y < numYBlocks; y++)
{ {
for (int x = 0; x < numXBlocks; x++) for (int x = 0; x < numXBlocks; x++)
{ {
mActorBlock[x, y].Clear(); mActorBlock[x, y].Clear();
} }
} }
} }
public void BroadcastPacketAroundActor(Actor actor, SubPacket packet) public void BroadcastPacketAroundActor(Actor actor, SubPacket packet)
{ {
if (isIsolated) if (isIsolated)
return; return;
List<Actor> aroundActor = GetActorsAroundActor(actor, 50); List<Actor> aroundActor = GetActorsAroundActor(actor, 50);
foreach (Actor a in aroundActor) foreach (Actor a in aroundActor)
{ {
if (a is Player) if (a is Player)
{ {
if (isIsolated && packet.header.sourceId != a.actorId) if (isIsolated && packet.header.sourceId != a.actorId)
continue; continue;
SubPacket clonedPacket = new SubPacket(packet, actor.actorId); SubPacket clonedPacket = new SubPacket(packet, actor.actorId);
Player p = (Player)a; Player p = (Player)a;
p.QueuePacket(clonedPacket); p.QueuePacket(clonedPacket);
} }
} }
} }
public void SpawnActor(SpawnLocation location) public void SpawnActor(SpawnLocation location)
{ {
ActorClass actorClass = Server.GetWorldManager().GetActorClass(location.classId); ActorClass actorClass = Server.GetWorldManager().GetActorClass(location.classId);
if (actorClass == null) if (actorClass == null)
return; return;
uint zoneId; uint zoneId;
@ -378,21 +373,44 @@ namespace FFXIVClassic_Map_Server.Actors
if (this is PrivateArea) if (this is PrivateArea)
zoneId = ((PrivateArea)this).GetParentZone().actorId; zoneId = ((PrivateArea)this).GetParentZone().actorId;
else else
zoneId = actorId; 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 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); npc.LoadEventConditions(actorClass.eventConditions);
AddActorToZone(npc); 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() public Director GetWeatherDirector()
{ {
return mWeatherDirector; return mWeatherDirector;
} }
public void ChangeWeather(ushort weather, ushort transitionTime, Player player, bool zoneWide = false) public void ChangeWeather(ushort weather, ushort transitionTime, Player player, bool zoneWide = false)
{ {
weatherNormal = weather; 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) public Director CreateDirector(string path)
{ {
@ -472,7 +465,7 @@ namespace FFXIVClassic_Map_Server.Actors
return currentDirectors[id]; return currentDirectors[id];
return null; return null;
} }
public void Update(double deltaTime) public void Update(double deltaTime)
{ {
lock (mActorList) lock (mActorList)
@ -480,6 +473,7 @@ namespace FFXIVClassic_Map_Server.Actors
foreach (Actor a in mActorList.Values) foreach (Actor a in mActorList.Values)
a.Update(deltaTime); a.Update(deltaTime);
} }
} }
}
} }
}

View 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)
{
}
}
}

View File

@ -16,7 +16,7 @@ namespace FFXIVClassic_Map_Server.actors.area
class Zone : Area class Zone : Area
{ {
Dictionary<string, Dictionary<uint, PrivateArea>> privateAreas = new Dictionary<string, Dictionary<uint, PrivateArea>>(); 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) 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) : 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()
{
}
} }
} }

View File

@ -3,6 +3,7 @@ using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group; using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.Actors.Chara; using FFXIVClassic_Map_Server.Actors.Chara;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.utils;
namespace FFXIVClassic_Map_Server.Actors namespace FFXIVClassic_Map_Server.Actors
{ {
@ -87,6 +88,18 @@ namespace FFXIVClassic_Map_Server.Actors
player.QueuePacket(SetActorQuestGraphicPacket.BuildPacket(player.actorId, actorId, graphicNum)); 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());
}
}
} }
} }

View File

@ -206,6 +206,9 @@ namespace FFXIVClassic_Map_Server.Actors
{ {
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this, playerActorId); ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this, playerActorId);
//Potential
propPacketUtil.AddProperty("charaWork.battleSave.potencial");
//Properties //Properties
for (int i = 0; i < charaWork.property.Length; i++) for (int i = 0; i < charaWork.property.Length; i++)
{ {

View File

@ -5,6 +5,6 @@
public ushort pushCommand; public ushort pushCommand;
public int pushCommandSub; public int pushCommandSub;
public byte pushCommandPriority; public byte pushCommandPriority;
public byte hateType; public byte hateType = 1;
} }
} }

View File

@ -552,7 +552,6 @@ namespace FFXIVClassic_Map_Server.Actors
director.GetSpawnPackets(actorId).DebugPrintPacket(); director.GetSpawnPackets(actorId).DebugPrintPacket();
QueuePacket(director.GetSpawnPackets(actorId)); QueuePacket(director.GetSpawnPackets(actorId));
QueuePacket(director.GetInitPackets(actorId)); QueuePacket(director.GetInitPackets(actorId));
//QueuePacket(director.GetSetEventStatusPackets(actorId));
} }
} }
@ -634,7 +633,7 @@ namespace FFXIVClassic_Map_Server.Actors
public void ChangeAnimation(uint animId) public void ChangeAnimation(uint animId)
{ {
Actor a = zone.FindActorInZone(currentTarget); Actor a = zone.FindActorInArea(currentTarget);
if (a is Npc) if (a is Npc)
((Npc)a).animationId = animId; ((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) public void RemoveDirector(Director director)
{ {
if (!ownedDirectors.Contains(director)) if (!ownedDirectors.Contains(director))

View File

@ -1,7 +1,11 @@
using FFXIVClassic.Common; 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.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group; using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups; using FFXIVClassic_Map_Server.packets.send.groups;
using FFXIVClassic_Map_Server.utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -12,20 +16,36 @@ namespace FFXIVClassic_Map_Server.actors.group
{ {
class ContentGroup : Group class ContentGroup : Group
{ {
public ContentGroupWork contentGroupWork = new ContentGroupWork();
private Director director;
private List<uint> members = new List<uint>(); 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++) if (initialMembers != null)
members.Add(initialMembers[i]); {
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); SendGroupPacketsAll(members);
} }
public void RemoveMember(uint memberId) public void RemoveMember(uint memberId)
{ {
members.Remove(memberId); members.Remove(memberId);
@ -44,18 +64,68 @@ namespace FFXIVClassic_Map_Server.actors.group
return groupMembers; return groupMembers;
} }
public override int GetMemberCount()
{
return members.Count;
}
public override void SendInitWorkValues(Session session) 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"); groupWork.setTarget("/_init");
SubPacket test = groupWork.buildPacket(session.id, session.id); SubPacket test = groupWork.buildPacket(session.id, session.id);
test.DebugPrintSubPacket();
session.QueuePacket(test, true, false); 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() public override uint GetTypeId()
{ {
return Group.ContentGroup_SimpleContentGroup24A; return Group.ContentGroup_SimpleContentGroup24B;
} }

View File

@ -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(); ulong time = Utils.MilisUnixTimeStampUTC();
List<GroupMember> members = BuildMemberList(session.id); List<GroupMember> members = BuildMemberList(session.id);

View File

@ -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];
}
}

View File

@ -2,12 +2,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group.Work namespace FFXIVClassic_Map_Server.actors.group.Work
{ {
class ContentWork class GlobalTemp
{ {
public GroupGlobalTemp _globalTemp = new GroupGlobalTemp(); public ulong director;
} }
} }

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -18,7 +18,7 @@ namespace FFXIVClassic_Map_Server.packets.send.group
this.unknown2 = unknown2; this.unknown2 = unknown2;
this.flag1 = flag1; this.flag1 = flag1;
this.isOnline = isOnline; this.isOnline = isOnline;
this.name = name; this.name = name == null ? "" : name;
} }
} }
} }

View File

@ -38,6 +38,7 @@ namespace FFXIVClassic_Map_Server.packets.send.group
binWriter.Write((UInt32)entry.unknown2); binWriter.Write((UInt32)entry.unknown2);
binWriter.Write((Byte)(entry.flag1? 1 : 0)); binWriter.Write((Byte)(entry.flag1? 1 : 0));
binWriter.Write((Byte)(entry.isOnline? 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)); binWriter.Write(Encoding.ASCII.GetBytes(entry.name), 0, Encoding.ASCII.GetByteCount(entry.name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(entry.name));
offset++; offset++;

View File

@ -108,7 +108,7 @@ namespace FFXIVClassic_Map_Server.packets.send.groups
string[] split = name.Split('.'); string[] split = name.Split('.');
int arrayIndex = 0; 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; return;
Object curObj = group; Object curObj = group;