More group work. Added packet operations to the world server so it can send global group info.

This commit is contained in:
Filip Maj 2016-12-15 12:19:44 -05:00
parent 6c409e93a9
commit 1148619ca5
30 changed files with 1173 additions and 43 deletions

View file

@ -0,0 +1,41 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.Actor.Group;
using FFXIVClassic_World_Server.DataObjects.Group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class CreateNamedGroup
{
public const ushort OPCODE = 0x0188;
public const uint PACKET_SIZE = 0x60;
public static SubPacket buildPacket(uint sessionId, Group group)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt64)group.groupIndex);
binWriter.Write((UInt32)group.GetTypeId());
binWriter.Write((Int32)group.GetGroupLocalizedName());
binWriter.Write((UInt16)0x121C);
binWriter.Seek(0x20, SeekOrigin.Begin);
binWriter.Write(Encoding.ASCII.GetBytes(group.GetGroupName()), 0, Encoding.ASCII.GetByteCount(group.GetGroupName()) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(group.GetGroupName()));
}
}
return new SubPacket(OPCODE, sessionId, sessionId, data);
}
}
}

View file

@ -0,0 +1,55 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.Actor.Group;
using FFXIVClassic_World_Server.DataObjects.Group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class CreateNamedGroupMultiple
{
public const ushort OPCODE = 0x0189;
public const uint PACKET_SIZE = 0x228;
public static SubPacket buildPacket(uint playerActorID, Group[] groups, ref int offset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max = 8;
if (groups.Length - offset <= 8)
max = groups.Length - offset;
for (int i = 0; i < max; i++)
{
binWriter.Seek(i * 0x40, SeekOrigin.Begin);
Group group = groups[offset+i];
binWriter.Write((UInt64)group.groupIndex);
binWriter.Write((UInt32)group.GetTypeId());
binWriter.Write((Int32)group.GetGroupLocalizedName());
binWriter.Write((UInt16)0x121C);
binWriter.Seek(0x20, SeekOrigin.Begin);
binWriter.Write(Encoding.ASCII.GetBytes(group.GetGroupName()), 0, Encoding.ASCII.GetByteCount(group.GetGroupName()) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(group.GetGroupName()));
}
binWriter.Seek(0x200, SeekOrigin.Begin);
binWriter.Write((Byte)max);
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View file

@ -0,0 +1,44 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.Actor.Group;
using FFXIVClassic_World_Server.DataObjects.Group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class DeleteGroupPacket
{
public const ushort OPCODE = 0x0143;
public const uint PACKET_SIZE = 0x40;
public static SubPacket buildPacket(uint sessionId, Group group)
{
return buildPacket(sessionId, group.groupIndex);
}
public static SubPacket buildPacket(uint sessionId, ulong groupId)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
//Write control num ????
binWriter.Write((UInt64)3);
//Write Ids
binWriter.Write((UInt64)groupId);
binWriter.Write((UInt64)0);
binWriter.Write((UInt64)groupId);
}
}
return new SubPacket(OPCODE, sessionId, sessionId, data);
}
}
}

View file

@ -0,0 +1,61 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.DataObjects.Group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class GroupHeaderPacket
{
public const uint TYPEID_RETAINER = 0x13881;
public const uint TYPEID_PARTY = 0x2711;
public const uint TYPEID_LINKSHELL = 0x4E22;
public const ushort OPCODE = 0x017C;
public const uint PACKET_SIZE = 0x98;
public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, Group group)
{
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 list id
binWriter.Write((UInt64)3);
binWriter.Write((UInt64)group.groupIndex);
binWriter.Write((UInt64)0);
binWriter.Write((UInt64)group.groupIndex);
//This seems to change depending on what the list is for
binWriter.Write((UInt32)group.GetTypeId());
binWriter.Seek(0x40, SeekOrigin.Begin);
//This is for Linkshell
binWriter.Write((UInt32)group.GetGroupLocalizedName());
binWriter.Write(Encoding.ASCII.GetBytes(group.GetGroupName()), 0, Encoding.ASCII.GetByteCount(group.GetGroupName()) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(group.GetGroupName()));
binWriter.Seek(0x64, SeekOrigin.Begin);
binWriter.Write((UInt32)0x6D);
binWriter.Write((UInt32)0x6D);
binWriter.Write((UInt32)0x6D);
binWriter.Write((UInt32)0x6D);
binWriter.Write((UInt32)group.GetMemberCount());
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View file

@ -0,0 +1,24 @@
using FFXIVClassic.Common;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class GroupMember
{
public uint actorId;
public int localizedName;
public uint unknown2;
public bool flag1;
public bool isOnline;
public string name;
public GroupMember(uint actorId, int localizedName, uint unknown2, bool flag1, bool isOnline, string name)
{
this.actorId = actorId;
this.localizedName = localizedName;
this.unknown2 = unknown2;
this.flag1 = flag1;
this.isOnline = isOnline;
this.name = name;
}
}
}

View file

@ -0,0 +1,37 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.DataObjects.Group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class GroupMembersBeginPacket
{
public const ushort OPCODE = 0x017D;
public const uint PACKET_SIZE = 0x40;
public static SubPacket buildPacket(uint playerActorID, uint locationCode, ulong sequenceId, Group group)
{
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 List Info
binWriter.Write((UInt64)group.groupIndex);
binWriter.Write((UInt32)group.GetMemberCount());
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View file

@ -0,0 +1,38 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.Actor.Group;
using FFXIVClassic_World_Server.DataObjects.Group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class GroupMembersEndPacket
{
public const ushort OPCODE = 0x017E;
public const uint PACKET_SIZE = 0x38;
public static SubPacket buildPacket(uint sessionId, uint locationCode, ulong sequenceId, Group group)
{
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 List Info
binWriter.Write((UInt64)group.groupIndex);
}
}
return new SubPacket(OPCODE, sessionId, sessionId, data);
}
}
}

View file

@ -0,0 +1,54 @@
using FFXIVClassic.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class GroupMembersX08Packet
{
public const ushort OPCODE = 0x017F;
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 + (0x30 * i), SeekOrigin.Begin);
GroupMember entry = entries[i];
binWriter.Write((UInt32)entry.actorId);
binWriter.Write((Int32)entry.localizedName);
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++;
}
//Write Count
binWriter.Seek(0x10 + (0x30 * 8), SeekOrigin.Begin);
binWriter.Write(max);
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

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_World_Server.Packets.Send.Subpackets.Groups
{
class GroupMembersX16Packet
{
public const ushort OPCODE = 0x0180;
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 = 16;
if (entries.Count-offset < 16)
max = entries.Count - offset;
for (int i = 0; i < max; i++)
{
binWriter.Seek(0x10 + (0x30 * i), SeekOrigin.Begin);
GroupMember entry = entries[i];
binWriter.Write((UInt32)entry.actorId);
binWriter.Write((Int32)entry.localizedName);
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++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

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_World_Server.Packets.Send.Subpackets.Groups
{
class GroupMembersX32Packet
{
public const ushort OPCODE = 0x0181;
public const uint PACKET_SIZE = 0x630;
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 + (0x30 * i), SeekOrigin.Begin);
GroupMember entry = entries[i];
binWriter.Write((UInt32)entry.actorId);
binWriter.Write((Int32)entry.localizedName);
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++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

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_World_Server.Packets.Send.Subpackets.Groups
{
class GroupMembersX64Packet
{
public const ushort OPCODE = 0x0182;
public const uint PACKET_SIZE = 0xC30;
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 + (0x30 * i), SeekOrigin.Begin);
GroupMember entry = entries[i];
binWriter.Write((UInt32)entry.actorId);
binWriter.Write((Int32)entry.localizedName);
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++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View file

@ -0,0 +1,211 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.Actor.Group;
using FFXIVClassic_World_Server.DataObjects.Group;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups
{
class SynchGroupWorkValuesPacket
{
public const ushort OPCODE = 0x017A;
public const uint PACKET_SIZE = 0xB0;
private const ushort MAXBYTES = 0x98;
private ushort runningByteTotal = 0;
private byte[] data = new byte[PACKET_SIZE - 0x20];
private bool isMore = false;
private MemoryStream mem;
private BinaryWriter binWriter;
public SynchGroupWorkValuesPacket(ulong listId)
{
mem = new MemoryStream(data);
binWriter = new BinaryWriter(mem);
binWriter.Write((UInt64)listId);
binWriter.Seek(1, SeekOrigin.Current);
}
public void closeStreams()
{
binWriter.Dispose();
mem.Dispose();
}
public bool addByte(uint id, byte value)
{
if (runningByteTotal + 6 > MAXBYTES)
return false;
binWriter.Write((byte)1);
binWriter.Write((UInt32)id);
binWriter.Write((byte)value);
runningByteTotal += 6;
return true;
}
public bool addShort(uint id, ushort value)
{
if (runningByteTotal + 7 > MAXBYTES)
return false;
binWriter.Write((byte)2);
binWriter.Write((UInt32)id);
binWriter.Write((UInt16)value);
runningByteTotal += 7;
return true;
}
public bool addInt(uint id, uint value)
{
if (runningByteTotal + 9 > MAXBYTES)
return false;
binWriter.Write((byte)4);
binWriter.Write((UInt32)id);
binWriter.Write((UInt32)value);
runningByteTotal += 9;
return true;
}
public bool addLong(uint id, ulong value)
{
if (runningByteTotal + 13 > MAXBYTES)
return false;
binWriter.Write((byte)8);
binWriter.Write((UInt32)id);
binWriter.Write((UInt64)value);
runningByteTotal += 13;
return true;
}
public bool addBuffer(uint id, byte[] buffer)
{
if (runningByteTotal + 5 + buffer.Length > MAXBYTES)
return false;
binWriter.Write((byte)buffer.Length);
binWriter.Write((UInt32)id);
binWriter.Write(buffer);
runningByteTotal += (ushort)(5 + buffer.Length);
return true;
}
public void addProperty(Group group, string name)
{
string[] split = name.Split('.');
int arrayIndex = 0;
if (!(split[0].Equals("work") || split[0].Equals("partyGroupWork")))
return;
Object curObj = group;
for (int i = 0; i < split.Length; i++)
{
//For arrays
if (split[i].Contains('['))
{
if (split[i].LastIndexOf(']') - split[i].IndexOf('[') <= 0)
return;
arrayIndex = Convert.ToInt32(split[i].Substring(split[i].IndexOf('[') + 1, split[i].Length - split[i].LastIndexOf(']')));
split[i] = split[i].Substring(0, split[i].IndexOf('['));
if (i != split.Length - 1)
{
curObj = curObj.GetType().GetField(split[i]).GetValue(curObj);
curObj = ((Array)curObj).GetValue(arrayIndex);
i++;
}
}
FieldInfo field = curObj.GetType().GetField(split[i]);
if (field == null)
return;
curObj = field.GetValue(curObj);
if (curObj == null)
return;
}
if (curObj == null)
return;
else
{
//Array, we actually care whats inside
if (curObj.GetType().IsArray)
{
if (((Array)curObj).Length <= arrayIndex)
return;
curObj = ((Array)curObj).GetValue(arrayIndex);
}
if (curObj == null)
return;
//Cast to the proper object and add to packet
uint id = Utils.MurmurHash2(name, 0);
if (curObj is bool)
addByte(id, (byte)(((bool)curObj) ? 1 : 0));
else if (curObj is byte)
addByte(id, (byte)curObj);
else if (curObj is ushort)
addShort(id, (ushort)curObj);
else if (curObj is short)
addShort(id, (ushort)(short)curObj);
else if (curObj is uint)
addInt(id, (uint)curObj);
else if (curObj is int)
addInt(id, (uint)(int)curObj);
else if (curObj is long)
addLong(id, (ulong)(long)curObj);
else if (curObj is ulong)
addLong(id, (ulong)curObj);
else if (curObj is float)
addBuffer(id, BitConverter.GetBytes((float)curObj));
else
return;
}
}
public void setIsMore(bool flag)
{
isMore = flag;
}
public void setTarget(string target)
{
binWriter.Write((byte)(isMore ? 0x62 + target.Length : 0x82 + target.Length));
binWriter.Write(Encoding.ASCII.GetBytes(target));
runningByteTotal += (ushort)(1 + Encoding.ASCII.GetByteCount(target));
}
public SubPacket buildPacket(uint playerActorID, uint actorID)
{
binWriter.Seek(0x8, SeekOrigin.Begin);
binWriter.Write((byte)runningByteTotal);
closeStreams();
SubPacket packet = new SubPacket(OPCODE, playerActorID, actorID, data);
return packet;
}
}
}