1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-20 19:57:46 +00:00

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;
@ -694,6 +697,68 @@ namespace FFXIVClassic_Map_Server
} }
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)
{ {
SubPacket packet = CreateLinkshellPacket.BuildPacket(player.playerSession, name, crest, player.actorId); SubPacket packet = CreateLinkshellPacket.BuildPacket(player.playerSession, name, crest, player.actorId);

View file

@ -46,11 +46,6 @@ namespace FFXIVClassic_Map_Server.Actors
LuaScript areaScript; LuaScript areaScript;
//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) 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) : base(id)
{ {
@ -293,7 +288,7 @@ namespace FFXIVClassic_Map_Server.Actors
#endregion #endregion
public Actor FindActorInZone(uint id) public Actor FindActorInArea(uint id)
{ {
if (!mActorList.ContainsKey(id)) if (!mActorList.ContainsKey(id))
return null; return null;
@ -388,6 +383,29 @@ namespace FFXIVClassic_Map_Server.Actors
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;
@ -414,31 +432,6 @@ 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)
{ {
lock (directorLock) lock (directorLock)
@ -481,5 +474,6 @@ namespace FFXIVClassic_Map_Server.Actors
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,17 +16,33 @@ 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);
} }
@ -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;