Kicked/Promote leader added but broke login. D/Cing now.

This commit is contained in:
Filip Maj 2016-12-21 18:02:50 -05:00
parent e89b7557b3
commit 16c9b741bf
30 changed files with 1120 additions and 211 deletions

View File

@ -81,10 +81,9 @@
<Compile Include="actors\chara\player\Equipment.cs" />
<Compile Include="actors\chara\player\Inventory.cs" />
<Compile Include="actors\chara\Work.cs" />
<Compile Include="actors\group\GroupInvitationRelationGroup.cs" />
<Compile Include="actors\group\LinkshellGroup.cs" />
<Compile Include="actors\group\PartyGroup.cs" />
<Compile Include="actors\group\RetainerGroup.cs" />
<Compile Include="actors\group\Group.cs" />
<Compile Include="actors\group\Party.cs" />
<Compile Include="actors\group\Relation.cs" />
<Compile Include="actors\group\work\ContentWork.cs" />
<Compile Include="actors\debug\Debug.cs" />
<Compile Include="actors\director\Director.cs" />
@ -94,7 +93,6 @@
<Compile Include="actors\director\quest\QuestDirectorMan0u001.cs" />
<Compile Include="actors\director\WeatherDirector.cs" />
<Compile Include="actors\EventList.cs" />
<Compile Include="actors\group\Group.cs" />
<Compile Include="actors\group\work\GroupGlobalSave.cs" />
<Compile Include="actors\group\work\GroupGlobalTemp.cs" />
<Compile Include="actors\group\work\GroupMemberSave.cs" />
@ -288,6 +286,7 @@
<Compile Include="packets\WorldPackets\Send\Group\CreateLinkshellPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\DeleteLinkshellPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\ModifyLinkshellPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\PartyModifyPacket.cs" />
<Compile Include="packets\WorldPackets\Send\SessionBeginConfirmPacket.cs" />
<Compile Include="packets\WorldPackets\Send\SessionEndConfirmPacket.cs" />
<Compile Include="Program.cs" />

View File

@ -248,7 +248,7 @@ namespace FFXIVClassic_Map_Server
break;
//Party Window Opened, Request State
case 0x01C5:
client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(session.id, true, true, 1), true, false));
client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(session.id, false, false, 0), true, false));
break;
//Search Recruiting
case 0x01C7:

View File

@ -33,6 +33,8 @@ 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;
public WorldManager(Server server)
@ -700,37 +702,41 @@ namespace FFXIVClassic_Map_Server
//World server sent a party member list synch packet to the zone server. Add and update players that may be a part of it.
public void PartyMemberListRecieved(PartySyncPacket syncPacket)
{
Party group;
//If no members on this server, get out or clean
if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId) && syncPacket.memberActorIds.Length == 0)
return;
else if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId) && syncPacket.memberActorIds.Length == 0)
NoMembersInParty(currentPlayerParties[syncPacket.partyGroupId]);
//Get or create group
if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId))
lock (currentPlayerParties)
{
group = new Party(syncPacket.partyGroupId, syncPacket.owner);
currentPlayerParties.Add(syncPacket.partyGroupId, group);
}
else
group = currentPlayerParties[syncPacket.partyGroupId];
Party group;
currentPlayerParties[syncPacket.partyGroupId].members = syncPacket.memberActorIds.ToList();
//If no members on this server, get out or clean
if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId) && syncPacket.memberActorIds.Length == 0)
return;
else if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId) && syncPacket.memberActorIds.Length == 0)
NoMembersInParty(currentPlayerParties[syncPacket.partyGroupId]);
//Add group to everyone
foreach (uint member in currentPlayerParties[syncPacket.partyGroupId].members)
{
Session session = Server.GetServer().GetSession(member);
//Get or create group
if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId))
{
group = new Party(syncPacket.partyGroupId, syncPacket.owner);
currentPlayerParties.Add(syncPacket.partyGroupId, group);
}
else
group = currentPlayerParties[syncPacket.partyGroupId];
if (session == null)
continue;
group.members = syncPacket.memberActorIds.ToList();
Player player = session.GetActor();
if (player == null)
continue;
player.SetParty(group);
//Add group to everyone
for (int i = 0; i < group.members.Count; i++ )
{
uint member = group.members[i];
Session session = Server.GetServer().GetSession(member);
if (session == null)
continue;
Player player = session.GetActor();
if (player == null)
continue;
player.SetParty(group);
}
}
}

View File

@ -17,6 +17,7 @@ using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group;
namespace FFXIVClassic_Map_Server.Actors
{
@ -1290,8 +1291,10 @@ namespace FFXIVClassic_Map_Server.Actors
return false;
}
public void PartyOustPlayer()
{
public void PartyOustPlayer(string name)
{
SubPacket oustPacket = PartyModifyPacket.BuildPacket(playerSession, 1, name);
QueuePacket(oustPacket);
}
public void PartyLeave()
@ -1302,8 +1305,10 @@ namespace FFXIVClassic_Map_Server.Actors
{
}
public void PartyPromote()
public void PartyPromote(string name)
{
SubPacket promotePacket = PartyModifyPacket.BuildPacket(playerSession, 0, name);
QueuePacket(promotePacket);
}
//A party member list packet came, set the party

View File

@ -20,14 +20,14 @@ namespace FFXIVClassic_Map_Server.actors.group
members.Add(leaderCharaId);
}
public void SetLeader(uint actorId)
public void SetLeader(uint leaderCharaId)
{
partyGroupWork._globalTemp.owner = (ulong)((actorId << 32) | 0xB36F92);
partyGroupWork._globalTemp.owner = (ulong)(((ulong)leaderCharaId << 32) | 0xB36F92);
}
public uint GetLeader()
{
return (uint)((partyGroupWork._globalTemp.owner >> 32) & 0xFFFFFFFF);
return (uint)((ulong)(partyGroupWork._globalTemp.owner >> 32) & 0xFFFFFFFF);
}
public bool IsInParty(uint charaId)

View File

@ -25,11 +25,10 @@ namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
try
{
partyGroupId = binReader.ReadUInt64();
uint owner = binReader.ReadUInt32();
owner = binReader.ReadUInt32();
uint numMembers = binReader.ReadUInt32();
memberActorIds = new uint[numMembers];
PartyGroup group = new PartyGroup(partyGroupId, owner);
for (int i = 0; i < numMembers; i++)
memberActorIds[i] = binReader.ReadUInt32();
}

View File

@ -0,0 +1,30 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{
class PartyModifyPacket
{
public const ushort OPCODE = 0x1020;
public const uint PACKET_SIZE = 0x48;
public static SubPacket BuildPacket(Session session, ushort command, string name)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt16)command);
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
}
}
return new SubPacket(true, OPCODE, session.id, session.id, data);
}
}
}

View File

@ -23,15 +23,15 @@ namespace FFXIVClassic_Map_Server.packets.send.group
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt64)group.groupId);
binWriter.Write((UInt32)group.groupTypeId);
binWriter.Write((Int32)group.localizedNamed);
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.groupName), 0, Encoding.ASCII.GetByteCount(group.groupName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(group.groupName));
binWriter.Write(Encoding.ASCII.GetBytes(group.GetGroupName()), 0, Encoding.ASCII.GetByteCount(group.GetGroupName()) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(group.GetGroupName()));
}
}

View File

@ -33,15 +33,15 @@ namespace FFXIVClassic_Map_Server.packets.send.group
Group group = groups[offset+i];
binWriter.Write((UInt64)group.groupId);
binWriter.Write((UInt32)group.groupTypeId);
binWriter.Write((Int32)group.localizedNamed);
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.groupName), 0, Encoding.ASCII.GetByteCount(group.groupName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(group.groupName));
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);

View File

@ -16,7 +16,7 @@ namespace FFXIVClassic_Map_Server.packets.send.groups
public static SubPacket buildPacket(uint playerActorID, Group group)
{
return buildPacket(playerActorID, group.groupId);
return buildPacket(playerActorID, group.groupIndex);
}
public static SubPacket buildPacket(uint playerActorID, ulong groupId)

View File

@ -33,17 +33,17 @@ namespace FFXIVClassic_Map_Server.packets.send.group
//Write list id
binWriter.Write((UInt64)3);
binWriter.Write((UInt64)group.groupId);
binWriter.Write((UInt64)group.groupIndex);
binWriter.Write((UInt64)0);
binWriter.Write((UInt64)group.groupId);
binWriter.Write((UInt64)group.groupIndex);
//This seems to change depending on what the list is for
binWriter.Write((UInt32)group.groupTypeId);
binWriter.Write((UInt32)group.GetTypeId());
binWriter.Seek(0x40, SeekOrigin.Begin);
//This is for Linkshell
binWriter.Write((UInt32)group.localizedNamed);
binWriter.Write(Encoding.ASCII.GetBytes(group.groupName), 0, Encoding.ASCII.GetByteCount(group.groupName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(group.groupName));
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);
@ -52,7 +52,7 @@ namespace FFXIVClassic_Map_Server.packets.send.group
binWriter.Write((UInt32)0x6D);
binWriter.Write((UInt32)0x6D);
binWriter.Write((UInt32)group.members.Count);
binWriter.Write((UInt32)group.GetMemberCount());
}
}

View File

@ -27,8 +27,8 @@ namespace FFXIVClassic_Map_Server.packets.send.group
binWriter.Write((UInt64)locationCode);
binWriter.Write((UInt64)sequenceId);
//Write List Info
binWriter.Write((UInt64)group.groupId);
binWriter.Write((UInt32)group.members.Count);
binWriter.Write((UInt64)group.groupIndex);
binWriter.Write((UInt32)group.GetMemberCount());
}
}

View File

@ -27,7 +27,7 @@ namespace FFXIVClassic_Map_Server.packets.send.group
binWriter.Write((UInt64)locationCode);
binWriter.Write((UInt64)sequenceId);
//Write List Info
binWriter.Write((UInt64)group.groupId);
binWriter.Write((UInt64)group.groupIndex);
}
}

View File

@ -48,6 +48,17 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
return new List<GroupMember>();
}
public void SendGroupPacketsAll(List<uint> sessionIds)
{
for (int i = 0; i < sessionIds.Count; i++)
{
Session session = Server.GetServer().GetSession(sessionIds[i]);
if (session != null)
SendGroupPackets(session);
}
}
public void SendGroupPackets(Session session)
{
ulong time = Utils.MilisUnixTimeStampUTC();

View File

@ -20,6 +20,90 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
members.Add(leaderCharaId);
}
public void SetLeaderPlayerRequest(Session requestSession, string name)
{
if (GetLeader() != requestSession.sessionId)
{
requestSession.SendGameMessage(30428, 0x20, Server.GetServer().GetNameForId(requestSession.sessionId));
return;
}
uint newLeader = GetIdForName(name);
if (newLeader == 0)
{
requestSession.SendGameMessage(30575, 0x20);
return;
}
else if (newLeader == GetLeader())
{
requestSession.SendGameMessage(30563, 0x20, name);
return;
}
SetLeader(newLeader);
SendLeaderWorkToAllMembers();
for (int i = 0; i < members.Count; i++)
{
Session session = Server.GetServer().GetSession(members[i]);
if (session == null)
continue;
session.SendGameMessage(30429, 0x20, Server.GetServer().GetNameForId(members[i]));
}
Server.GetServer().GetWorldManager().SendPartySync(this);
}
public void KickPlayerRequest(Session requestSession, string name)
{
if (GetLeader() != requestSession.sessionId)
{
requestSession.SendGameMessage(30428, 0x20, Server.GetServer().GetNameForId(requestSession.sessionId));
return;
}
uint kickedMemberId = GetIdForName(name);
if (kickedMemberId == 0)
{
requestSession.SendGameMessage(30575, 0x20);
return;
}
for (int i = 0; i < members.Count; i++)
{
Session session = Server.GetServer().GetSession(members[i]);
if (session == null)
continue;
if (members[i] == kickedMemberId)
session.SendGameMessage(30410, 0x20);
else
session.SendGameMessage(30428, 0x20, (Object)name);
}
//All good, remove
members.Remove(kickedMemberId);
SendGroupPacketsAll(members);
Server.GetServer().GetWorldManager().SendPartySync(this);
}
public void SendLeaderWorkToAllMembers()
{
for (int i = 0; i < members.Count; i++)
{
SynchGroupWorkValuesPacket leaderUpdate = new SynchGroupWorkValuesPacket(groupIndex);
leaderUpdate.addProperty(this, "partyGroupWork._globalTemp.owner");
leaderUpdate.setTarget("partyGroupWork/leader");
Session session = Server.GetServer().GetSession(members[i]);
if (session == null)
continue;
else
session.clientConnection.QueuePacket(leaderUpdate.buildPacket(session.sessionId, session.sessionId), true, false);
}
}
public void SetLeader(uint actorId)
{
partyGroupWork._globalTemp.owner = (ulong)((actorId << 32) | 0xB36F92);
@ -30,10 +114,22 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
return (uint)((partyGroupWork._globalTemp.owner >> 32) & 0xFFFFFFFF);
}
public uint GetIdForName(string name)
{
for (int i = 0; i < members.Count; i++)
{
if (Server.GetServer().GetNameForId(members[i]).Equals(name))
{
return members[i];
}
}
return 0;
}
public bool IsInParty(uint charaId)
{
return members.Contains(charaId);
}
}
public override void SendInitWorkValues(Session session)
{
@ -64,5 +160,6 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
return groupMembers;
}
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace FFXIVClassic_World_Server.DataObjects
{
class LuaParam
{
public int typeID;
public Object value;
public LuaParam(int type, Object value)
{
this.typeID = type;
this.value = value;
}
}
}

View File

@ -0,0 +1,380 @@
using FFXIVClassic.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FFXIVClassic_World_Server.DataObjects
{
class LuaUtils
{
public class Type7Param
{
public uint actorId;
public byte unknown;
public byte slot;
public byte inventoryType;
public Type7Param(uint actorId, byte unknown, byte slot, byte inventoryType)
{
this.actorId = actorId;
this.unknown = unknown;
this.slot = slot;
this.inventoryType = inventoryType;
}
}
public class Type9Param
{
public ulong item1;
public ulong item2;
public Type9Param(ulong item1, ulong item2)
{
this.item1 = item1;
this.item2 = item2;
}
}
public static List<LuaParam> ReadLuaParams(BinaryReader reader)
{
List<LuaParam> luaParams = new List<LuaParam>();
bool isDone = false;
while (true)
{
byte code = reader.ReadByte();
object value = null;
bool wasNil = false;
switch (code)
{
case 0x0: //Int32
value = Utils.SwapEndian(reader.ReadInt32());
break;
case 0x1: //Int32
value = Utils.SwapEndian(reader.ReadUInt32());
break;
case 0x2: //Null Termed String
List<byte> list = new List<byte>();
while(true){
byte readByte = reader.ReadByte();
if (readByte == 0)
break;
list.Add(readByte);
}
value = Encoding.ASCII.GetString(list.ToArray());
break;
case 0x3: //Boolean True
value = true;
break;
case 0x4: //Boolean False
value = false;
break;
case 0x5: //Nil
wasNil = true;
break;
case 0x6: //Actor (By Id)
value = Utils.SwapEndian(reader.ReadUInt32());
break;
case 0x7: //Weird one used for inventory
uint type7ActorId = Utils.SwapEndian(reader.ReadUInt32());
byte type7Unknown = reader.ReadByte();
byte type7Slot = reader.ReadByte();
byte type7InventoryType = reader.ReadByte();
value = new Type7Param(type7ActorId, type7Unknown, type7Slot, type7InventoryType);
break;
case 0x9: //Two Longs (only storing first one)
value = new Type9Param(Utils.SwapEndian(reader.ReadUInt64()), Utils.SwapEndian(reader.ReadUInt64()));
break;
case 0xC: //Byte
value = reader.ReadByte();
break;
case 0x1B: //Short?
value = reader.ReadUInt16();
break;
case 0xF: //End
isDone = true;
continue;
}
if (isDone)
break;
if (value != null)
luaParams.Add(new LuaParam(code, value));
else if (wasNil)
luaParams.Add(new LuaParam(code, value));
}
return luaParams;
}
public static void WriteLuaParams(BinaryWriter writer, List<LuaParam> luaParams)
{
foreach (LuaParam l in luaParams)
{
if (l.typeID == 0x1)
writer.Write((Byte)0);
else
writer.Write((Byte)l.typeID);
switch (l.typeID)
{
case 0x0: //Int32
writer.Write((Int32)Utils.SwapEndian((Int32)l.value));
break;
case 0x1: //Int32
writer.Write((UInt32)Utils.SwapEndian((UInt32)l.value));
break;
case 0x2: //Null Termed String
string sv = (string)l.value;
writer.Write(Encoding.ASCII.GetBytes(sv), 0, Encoding.ASCII.GetByteCount(sv));
writer.Write((Byte)0);
break;
case 0x3: //Boolean True
break;
case 0x4: //Boolean False
break;
case 0x5: //Nil
break;
case 0x6: //Actor (By Id)
writer.Write((UInt32)Utils.SwapEndian((UInt32)l.value));
break;
case 0x7: //Weird one used for inventory
Type7Param type7 = (Type7Param)l.value;
writer.Write((UInt32)Utils.SwapEndian((UInt32)type7.actorId));
writer.Write((Byte)type7.unknown);
writer.Write((Byte)type7.slot);
writer.Write((Byte)type7.inventoryType);
break;
case 0x9: //Two Longs (only storing first one)
writer.Write((UInt64)Utils.SwapEndian(((Type9Param)l.value).item1));
writer.Write((UInt64)Utils.SwapEndian(((Type9Param)l.value).item2));
break;
case 0xC: //Byte
writer.Write((Byte)l.value);
break;
case 0x1B: //Short?
break;
case 0xF: //End
continue;
}
}
writer.Write((Byte)0xF);
}
public static List<LuaParam> ReadLuaParams(byte[] bytesIn)
{
List<LuaParam> luaParams = new List<LuaParam>();
using (MemoryStream memStream = new MemoryStream(bytesIn))
{
using (BinaryReader reader = new BinaryReader(memStream))
{
bool isDone = false;
while (true)
{
byte code = reader.ReadByte();
object value = null;
bool wasNil = false;
switch (code)
{
case 0x0: //Int32
value = Utils.SwapEndian(reader.ReadInt32());
break;
case 0x1: //Int32
value = Utils.SwapEndian(reader.ReadUInt32());
break;
case 0x2: //Null Termed String
List<byte> list = new List<byte>();
while (true)
{
byte readByte = reader.ReadByte();
if (readByte == 0)
break;
list.Add(readByte);
}
value = Encoding.ASCII.GetString(list.ToArray());
break;
case 0x3: //Boolean True
value = true;
break;
case 0x4: //Boolean False
value = false;
break;
case 0x5: //Nil
wasNil = true;
break;
case 0x6: //Actor (By Id)
value = Utils.SwapEndian(reader.ReadUInt32());
break;
case 0x7: //Weird one used for inventory
uint type7ActorId = Utils.SwapEndian(reader.ReadUInt32());
byte type7Unknown = reader.ReadByte();
byte type7Slot = reader.ReadByte();
byte type7InventoryType = reader.ReadByte();
value = new Type7Param(type7ActorId, type7Unknown, type7Slot, type7InventoryType);
break;
case 0x9: //Two Longs (only storing first one)
value = new Type9Param(Utils.SwapEndian(reader.ReadUInt64()), Utils.SwapEndian(reader.ReadUInt64()));
break;
case 0xC: //Byte
value = reader.ReadByte();
break;
case 0x1B: //Short?
value = reader.ReadUInt16();
break;
case 0xF: //End
isDone = true;
continue;
}
if (isDone)
break;
if (value != null)
luaParams.Add(new LuaParam(code, value));
else if (wasNil)
luaParams.Add(new LuaParam(code, value));
}
}
}
return luaParams;
}
public static List<LuaParam> CreateLuaParamList(params object[] list)
{
List<LuaParam> luaParams = new List<LuaParam>();
foreach (object o in list)
{
if (o != null && o.GetType().IsArray)
{
Array arrayO = (Array)o;
foreach (object o2 in arrayO)
AddToList(o2, luaParams);
}
else
AddToList(o, luaParams);
}
return luaParams;
}
private static void AddToList(object o, List<LuaParam> luaParams)
{
if (o is int)
{
luaParams.Add(new LuaParam(0x0, (int)o));
}
else if (o is uint)
{
luaParams.Add(new LuaParam(0x1, (uint)o));
}
else if (o is Double)
{
if (((double)o) % 1 == 0)
luaParams.Add(new LuaParam(0x0, (int)(double)o));
}
else if (o is string)
{
luaParams.Add(new LuaParam(0x2, (string)o));
}
else if (o is bool)
{
if (((bool)o))
luaParams.Add(new LuaParam(0x3, null));
else
luaParams.Add(new LuaParam(0x4, null));
}
else if (o == null)
{
luaParams.Add(new LuaParam(0x5, null));
}
else if (o is Type7Param)
{
luaParams.Add(new LuaParam(0x7, (Type7Param)o));
}
else if (o is Type9Param)
{
luaParams.Add(new LuaParam(0x9, (Type9Param)o));
}
else if (o is byte)
{
luaParams.Add(new LuaParam(0xC, (byte)o));
}
}
public static object[] CreateLuaParamObjectList(List <LuaParam> luaParams)
{
object[] list = new object[luaParams.Count];
for (int i = 0; i < list.Length; i++)
list[i] = luaParams[i].value;
return list;
}
public static string DumpParams(List<LuaParam> lParams)
{
if (lParams == null)
return "Param list was null?";
string dumpString = "";
for (int i = 0; i < lParams.Count; i++)
{
switch (lParams[i].typeID)
{
case 0x0: //Int32
dumpString += String.Format("0x{0:X}", (int)lParams[i].value);
break;
case 0x1: //Int32
dumpString += String.Format("0x{0:X}", (uint)lParams[i].value);
break;
case 0x2: //Null Termed String
dumpString += String.Format("\"{0}\"", (string)lParams[i].value);
break;
case 0x3: //Boolean True
dumpString += "true";
break;
case 0x4: //Boolean False
dumpString += "false";
break;
case 0x5: //NULL???
dumpString += "nil";
break;
case 0x6: //Actor (By Id)
dumpString += String.Format("0x{0:X}", (uint)lParams[i].value);
break;
case 0x7: //Weird one used for inventory
Type7Param type7Param = ((Type7Param)lParams[i].value);
dumpString += String.Format("Type7 Param: (0x{0:X}, 0x{1:X}, 0x{2:X}, 0x{3:X})", type7Param.actorId, type7Param.unknown, type7Param.slot, type7Param.inventoryType);
break;
case 0xC: //Byte
dumpString += String.Format("0x{0:X}", (byte)lParams[i].value);
break;
case 0x9: //Long (+ 8 bytes ignored)
Type9Param type9Param = ((Type9Param)lParams[i].value);
dumpString += String.Format("Type9 Param: (0x{0:X}, 0x{1:X})", type9Param.item1, type9Param.item2);
break;
case 0x1B: //Short?
dumpString += String.Format("0x{0:X}", (ushort)lParams[i].value);
break;
case 0xF: //End
break;
}
if (i != lParams.Count - 1)
dumpString += ", ";
}
return dumpString;
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using FFXIVClassic_World_Server.Packets.Send.Subpackets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
@ -28,6 +29,30 @@ namespace FFXIVClassic_World_Server.DataObjects
connection.owner = this;
Database.LoadZoneSessionInfo(this);
}
public void SendGameMessage( ushort textId, byte log, params object[] msgParams)
{
if (msgParams == null || msgParams.Length == 0)
clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, 0x5FF80001, textId, log), true, false);
else
clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, 0x5FF80001, textId, log, LuaUtils.CreateLuaParamList(msgParams)), true, false);
}
public void SendGameMessage( ushort textId, byte log, string customSender, params object[] msgParams)
{
if (msgParams == null || msgParams.Length == 0)
clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, 0x5FF80001, textId, customSender, log), true, false);
else
clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, 0x5FF80001, textId, customSender, log, LuaUtils.CreateLuaParamList(msgParams)), true, false);
}
public void SendGameMessage(ushort textId, byte log, uint displayId, params object[] msgParams)
{
if (msgParams == null || msgParams.Length == 0)
clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, 0x5FF80001, textId, displayId, log), true, false);
else
clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, 0x5FF80001, textId, displayId, log, LuaUtils.CreateLuaParamList(msgParams)), true, false);
}
}
}

View File

@ -193,6 +193,41 @@ namespace FFXIVClassic_World_Server
return members;
}
public static Linkshell GetLinkshell(ulong groupIndex, string lsName)
{
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
{
try
{
conn.Open();
MySqlCommand cmd = new MySqlCommand("SELECT id, name, crestIcon, master FROM server_linkshells WHERE name = @lsName", conn);
cmd.Parameters.AddWithValue("@lsName", lsName);
using (MySqlDataReader Reader = cmd.ExecuteReader())
{
while (Reader.Read())
{
ulong lsId = Reader.GetUInt64("id");
string name = Reader.GetString("name");
ushort crest = Reader.GetUInt16("crestIcon");
uint master = Reader.GetUInt32("master");
Linkshell linkshell = new Linkshell(lsId, groupIndex, name, crest, master, 0xa);
return linkshell;
}
}
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
}
finally
{
conn.Dispose();
}
}
return null;
}
public static Linkshell GetLinkshell(ulong groupIndex, ulong lsId)
{
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))

View File

@ -83,12 +83,15 @@
<Compile Include="DataObjects\Group\Relation.cs" />
<Compile Include="DataObjects\Group\RetainerGroup.cs" />
<Compile Include="DataObjects\Group\RetainerGroupMember.cs" />
<Compile Include="DataObjects\LuaParam.cs" />
<Compile Include="DataObjects\LuaUtils.cs" />
<Compile Include="DataObjects\ZoneServer.cs" />
<Compile Include="DataObjects\Session.cs" />
<Compile Include="LinkshellManager.cs" />
<Compile Include="PacketProcessor.cs" />
<Compile Include="Packets\Receive\HelloPacket.cs" />
<Compile Include="Packets\Receive\Subpackets\GroupCreatedPacket.cs" />
<Compile Include="Packets\Send\Subpackets\GameMessagePacket.cs" />
<Compile Include="Packets\Send\Subpackets\Groups\CreateNamedGroup.cs" />
<Compile Include="Packets\Send\Subpackets\Groups\CreateNamedGroupMultiple.cs" />
<Compile Include="Packets\Send\Subpackets\Groups\DeleteGroupPacket.cs" />
@ -105,22 +108,19 @@
<Compile Include="Packets\Send\_0x2Packet.cs" />
<Compile Include="Packets\Send\_0x7Packet.cs" />
<Compile Include="Packets\Send\_0x8PingPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\PartyLeavePacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\PartyModifyPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\SetActiveLinkshellPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\ModifyLinkshellPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\CreateRelationPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\CreateLinkshellPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\GetGroupPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\DeleteLinkshellPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\GroupMemberChangePacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\SessionBeginConfirmPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\WorldRequestZoneChangePacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\SessionEndConfirmPacket.cs" />
<Compile Include="Packets\WorldPackets\Send\ErrorPacket.cs" />
<Compile Include="Packets\WorldPackets\Send\Group\PartySyncPacket.cs" />
<Compile Include="Packets\WorldPackets\Send\Group\GroupWorkValuesPacket.cs" />
<Compile Include="Packets\WorldPackets\Send\Group\GroupMemberListPacket.cs" />
<Compile Include="Packets\WorldPackets\Send\Group\GroupMemberListEndPacket.cs" />
<Compile Include="Packets\WorldPackets\Send\Group\GroupMemberListStartPacket.cs" />
<Compile Include="Packets\WorldPackets\Send\SessionBeginPacket.cs" />
<Compile Include="Packets\WorldPackets\Send\SessionEndPacket.cs" />
<Compile Include="PartyManager.cs" />

View File

@ -11,9 +11,10 @@ namespace FFXIVClassic_World_Server
{
private WorldManager mWorldManager;
private Object mGroupLockReference;
private Dictionary<ulong, Group> mCurrentWorldGroupsReference;
private Dictionary<ulong, Linkshell> mLinkshellList = new Dictionary<ulong, Linkshell>();
private Dictionary<string, ulong> mNameToIdLookup = new Dictionary<string, ulong>();
private Dictionary<ulong, Group> mCurrentWorldGroupsReference; //GroupId, LS
private Dictionary<ulong, Linkshell> mLinkshellList = new Dictionary<ulong, Linkshell>(); //GroupId, LS
private Dictionary<ulong, Linkshell> mLSIdToIdLookup = new Dictionary<ulong, Linkshell>(); //Name, GroupId
private Dictionary<string, ulong> mNameToIdLookup = new Dictionary<string, ulong>(); //Name, GroupId
public LinkshellManager(WorldManager worldManager, Object groupLock, Dictionary<ulong, Group> worldGroupList)
{
@ -162,14 +163,31 @@ namespace FFXIVClassic_World_Server
if (mNameToIdLookup.ContainsKey(name))
return (Linkshell)mCurrentWorldGroupsReference[mNameToIdLookup[name]];
else
return null;
{
lock (mGroupLockReference)
{
Linkshell ls = Database.GetLinkshell(mWorldManager.GetGroupIndex(), name);
ls.LoadMembers();
if (ls != null)
{
mLinkshellList.Add(ls.groupIndex, ls);
mNameToIdLookup.Add(ls.name, ls.groupIndex);
mCurrentWorldGroupsReference.Add(ls.groupIndex, ls);
mWorldManager.IncrementGroupIndex();
return ls;
}
else
return null;
}
}
}
//Get a single linkshell group either already instantiated or make one from the db
public Linkshell GetLinkshell(ulong lsId)
{
if (mLinkshellList.ContainsKey(lsId))
return mLinkshellList[lsId];
if (mLSIdToIdLookup.ContainsKey(lsId))
return mLSIdToIdLookup[lsId];
else
{
lock (mGroupLockReference)
@ -181,6 +199,7 @@ namespace FFXIVClassic_World_Server
{
mLinkshellList.Add(ls.groupIndex, ls);
mNameToIdLookup.Add(ls.name, ls.groupIndex);
mLSIdToIdLookup.Add(ls.dbId, ls);
mCurrentWorldGroupsReference.Add(ls.groupIndex, ls);
mWorldManager.IncrementGroupIndex();
return ls;

View File

@ -0,0 +1,348 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.DataObjects;
namespace FFXIVClassic_World_Server.Packets.Send.Subpackets
{
class GameMessagePacket
{
private const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR1 = 0x157;
private const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR2 = 0x158;
private const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR3 = 0x159;
private const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR4 = 0x15a;
private const ushort OPCODE_GAMEMESSAGE_WITH_ACTOR5 = 0x15b;
private const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER1 = 0x15c;
private const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER2 = 0x15d;
private const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER3 = 0x15e;
private const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER4 = 0x15f;
private const ushort OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER5 = 0x160;
private const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER1 = 0x161;
private const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER2 = 0x162;
private const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER3 = 0x163;
private const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER4 = 0x164;
private const ushort OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER5 = 0x165;
private const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR1 = 0x166;
private const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR2 = 0x167;
private const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR3 = 0x168;
private const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR4 = 0x169;
private const ushort OPCODE_GAMEMESSAGE_WITHOUT_ACTOR5 = 0x16a;
private const ushort SIZE_GAMEMESSAGE_WITH_ACTOR1 = 0x30;
private const ushort SIZE_GAMEMESSAGE_WITH_ACTOR2 = 0x38;
private const ushort SIZE_GAMEMESSAGE_WITH_ACTOR3 = 0x40;
private const ushort SIZE_GAMEMESSAGE_WITH_ACTOR4 = 0x50;
private const ushort SIZE_GAMEMESSAGE_WITH_ACTOR5 = 0x70;
private const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER1 = 0x48;
private const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER2 = 0x58;
private const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER3 = 0x68;
private const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER4 = 0x78;
private const ushort SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER5 = 0x98;
private const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER1 = 0x30;
private const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER2 = 0x38;
private const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER3 = 0x40;
private const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER4 = 0x50;
private const ushort SIZE_GAMEMESSAGE_WITH_DISPID_SENDER5 = 0x60;
private const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR1 = 0x28;
private const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR2 = 0x38;
private const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR3 = 0x38;
private const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR4 = 0x48;
private const ushort SIZE_GAMEMESSAGE_WITHOUT_ACTOR5 = 0x68;
public static SubPacket BuildPacket(uint sourceId, uint targetId, uint actorId, uint textOwnerActorId, ushort textId, byte log)
{
byte[] data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR1 - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)actorId);
binWriter.Write((UInt32)textOwnerActorId);
binWriter.Write((UInt16)textId);
binWriter.Write((UInt16)log);
}
}
return new SubPacket(OPCODE_GAMEMESSAGE_WITH_ACTOR1, sourceId, targetId, data);
}
public static SubPacket BuildPacket(uint sourceId, uint targetId, uint actorId, uint textOwnerActorId, ushort textId, byte log, List<LuaParam> lParams)
{
int lParamsSize = findSizeOfParams(lParams);
byte[] data;
ushort opcode;
if (lParamsSize <= 0x8)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR2 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_ACTOR2;
}
else if (lParamsSize <= 0x10)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR3 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_ACTOR3;
}
else if (lParamsSize <= 0x20)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR4 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_ACTOR4;
}
else
{
data = new byte[SIZE_GAMEMESSAGE_WITH_ACTOR5 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_ACTOR5;
}
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)actorId);
binWriter.Write((UInt32)textOwnerActorId);
binWriter.Write((UInt16)textId);
binWriter.Write((UInt16)log);
LuaUtils.WriteLuaParams(binWriter, lParams);
if (lParamsSize <= 0x14-12)
{
binWriter.Seek(0x14, SeekOrigin.Begin);
binWriter.Write((UInt32)8);
}
}
}
return new SubPacket(opcode, sourceId, targetId, data);
}
public static SubPacket BuildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, string sender, byte log)
{
byte[] data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER1 - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)textOwnerActorId);
binWriter.Write((UInt16)textId);
binWriter.Write((UInt16)log);
binWriter.Write(Encoding.ASCII.GetBytes(sender), 0, Encoding.ASCII.GetByteCount(sender) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(sender));
}
}
return new SubPacket(OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER1, sourceId, targetId, data);
}
public static SubPacket BuildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, string sender, byte log, List<LuaParam> lParams)
{
int lParamsSize = findSizeOfParams(lParams);
byte[] data;
ushort opcode;
if (lParamsSize <= 0x8)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER2 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER2;
}
else if (lParamsSize <= 0x10)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER3 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER3;
}
else if (lParamsSize <= 0x20)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER4 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER4;
}
else
{
data = new byte[SIZE_GAMEMESSAGE_WITH_CUSTOM_SENDER5 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_CUSTOM_SENDER5;
}
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)textOwnerActorId);
binWriter.Write((UInt16)textId);
binWriter.Write((UInt16)log);
binWriter.Write(Encoding.ASCII.GetBytes(sender), 0, Encoding.ASCII.GetByteCount(sender) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(sender));
LuaUtils.WriteLuaParams(binWriter, lParams);
if (lParamsSize <= 0x14 - 12)
{
binWriter.Seek(0x30, SeekOrigin.Begin);
binWriter.Write((UInt32)8);
}
}
}
return new SubPacket(opcode, sourceId, targetId, data);
}
public static SubPacket BuildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, uint senderDisplayNameId, byte log)
{
byte[] data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER1 - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)senderDisplayNameId);
binWriter.Write((UInt32)textOwnerActorId);
binWriter.Write((UInt16)textId);
binWriter.Write((UInt16)log);
}
}
return new SubPacket(OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER1, sourceId, targetId, data);
}
public static SubPacket BuildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, uint senderDisplayNameId, byte log, List<LuaParam> lParams)
{
int lParamsSize = findSizeOfParams(lParams);
byte[] data;
ushort opcode;
if (lParamsSize <= 0x8)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER2 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER2;
}
else if (lParamsSize <= 0x10)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER3 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER3;
}
else if (lParamsSize <= 0x20)
{
data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER4 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER4;
}
else
{
data = new byte[SIZE_GAMEMESSAGE_WITH_DISPID_SENDER5 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITH_DISPID_SENDER5;
}
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)senderDisplayNameId);
binWriter.Write((UInt32)textOwnerActorId);
binWriter.Write((UInt16)textId);
binWriter.Write((UInt16)log);
LuaUtils.WriteLuaParams(binWriter, lParams);
if (lParamsSize <= 0x14 - 12)
{
binWriter.Seek(0x14, SeekOrigin.Begin);
binWriter.Write((UInt32)8);
}
}
}
return new SubPacket(opcode, sourceId, targetId, data);
}
public static SubPacket BuildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, byte log)
{
byte[] data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR1 - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)textOwnerActorId);
binWriter.Write((UInt16)textId);
binWriter.Write((UInt16)log);
}
}
return new SubPacket(OPCODE_GAMEMESSAGE_WITHOUT_ACTOR1, sourceId, targetId, data);
}
public static SubPacket BuildPacket(uint sourceId, uint targetId, uint textOwnerActorId, ushort textId, byte log, List<LuaParam> lParams)
{
int lParamsSize = findSizeOfParams(lParams);
byte[] data;
ushort opcode;
if (lParamsSize <= 0x8)
{
data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR2 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITHOUT_ACTOR2;
}
else if (lParamsSize <= 0x10)
{
data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR3 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITHOUT_ACTOR3;
}
else if (lParamsSize <= 0x20)
{
data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR4 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITHOUT_ACTOR4;
}
else
{
data = new byte[SIZE_GAMEMESSAGE_WITHOUT_ACTOR5 - 0x20];
opcode = OPCODE_GAMEMESSAGE_WITHOUT_ACTOR5;
}
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)textOwnerActorId);
binWriter.Write((UInt16)textId);
binWriter.Write((UInt16)log);
LuaUtils.WriteLuaParams(binWriter, lParams);
if (lParamsSize <= 0x8)
{
binWriter.Seek(0x10, SeekOrigin.Begin);
binWriter.Write((UInt32)8);
}
}
}
return new SubPacket(opcode, sourceId, targetId, data);
}
private static int findSizeOfParams(List<LuaParam> lParams)
{
int total = 0;
foreach (LuaParam l in lParams)
{
switch (l.typeID)
{
case 0:
case 1:
case 2:
total += 1 + 0x20;
break;
case 6:
total += 5;
break;
case 3:
case 4:
case 5:
total += 1;
break;
}
}
return total + 1;
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
{
class PartyLeavePacket
{
public bool invalidPacket = false;
public bool isDisband;
public PartyLeavePacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
isDisband = binReader.ReadByte() == 1;
}
catch (Exception)
{
invalidPacket = true;
}
}
}
}
}
}

View File

@ -1,19 +1,21 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
{
class GroupMemberChangePacket
class PartyModifyPacket
{
public const int GROUP_MEMBER_ADD = 0;
public const int GROUP_MEMBER_REMOVE = 0;
public bool invalidPacket = false;
public uint controlCode;
public ulong groupId;
public uint memberId;
public GroupMemberChangePacket(byte[] data)
public const ushort MODIFY_LEADER = 0;
public const ushort MODIFY_KICKPLAYER = 1;
public ushort command;
public string name;
public PartyModifyPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
@ -21,9 +23,8 @@ namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
{
try
{
controlCode = binReader.ReadUInt32();
groupId = binReader.ReadUInt64();
memberId = binReader.ReadUInt32();
command = binReader.ReadUInt16();
name = Encoding.ASCII.GetString(binReader.ReadBytes(0x20)).Trim(new[] { '\0' });
}
catch (Exception)
{

View File

@ -1,28 +0,0 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.DataObjects;
using System;
using System.IO;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Send.Group
{
class GroupMemberListEndPacket
{
public const ushort OPCODE = 0x1022;
public const uint PACKET_SIZE = 0x28;
public static SubPacket BuildPacket(Session session, ulong groupId)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt64)groupId);
}
}
return new SubPacket(true, OPCODE, 0, session.sessionId, data);
}
}
}

View File

@ -1,31 +0,0 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.DataObjects;
using System;
using System.IO;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Send.Group
{
class GroupMemberListPacket
{
public const ushort OPCODE = 0x1021;
public const uint PACKET_SIZE = 0x2C;
public static SubPacket BuildPacket(Session session, ulong groupId, uint numMembersInPacket)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt64)groupId);
binWriter.Write((UInt32)numMembersInPacket);
//Members
}
}
return new SubPacket(true, OPCODE, 0, session.sessionId, data);
}
}
}

View File

@ -1,30 +0,0 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.DataObjects;
using System;
using System.IO;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Send.Group
{
class GroupMemberListStartPacket
{
public const ushort OPCODE = 0x1020;
public const uint PACKET_SIZE = 0x30;
public static SubPacket BuildPacket(Session session, int resultCode, ulong groupId, int numMembers)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32) resultCode);
binWriter.Write((UInt64) groupId);
binWriter.Write((UInt32) numMembers);
}
}
return new SubPacket(true, OPCODE, 0, session.sessionId, data);
}
}
}

View File

@ -1,29 +0,0 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.DataObjects;
using System;
using System.IO;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Send.Group
{
class GroupWorkValuesPacket
{
public const ushort OPCODE = 0x1023;
public const uint PACKET_SIZE = 0x80;
public static SubPacket BuildPacket(Session session, ulong groupId)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt64)groupId);
//Write data
}
}
return new SubPacket(true, OPCODE, 0, session.sessionId, data);
}
}
}

View File

@ -199,7 +199,25 @@ namespace FFXIVClassic_World_Server
GetWorldManager().DoZoneServerChange(session, zoneChangePacket.destinationZoneId, "", zoneChangePacket.destinationSpawnType, zoneChangePacket.destinationX, zoneChangePacket.destinationY, zoneChangePacket.destinationZ, zoneChangePacket.destinationRot);
}
break;
break;
//Change leader or kick
case 0x1020:
PartyModifyPacket partyModifyPacket = new PartyModifyPacket(subpacket.data);
Party pt = mWorldManager.GetPartyManager().GetParty(subpacket.header.targetId);
if (pt.GetMemberCount() <= 1)
return;
if (partyModifyPacket.command == PartyModifyPacket.MODIFY_LEADER)
pt.SetLeaderPlayerRequest(GetSession(subpacket.header.sourceId), partyModifyPacket.name);
else if (partyModifyPacket.command == PartyModifyPacket.MODIFY_KICKPLAYER)
pt.KickPlayerRequest(GetSession(subpacket.header.sourceId), partyModifyPacket.name);
break;
//Party Resign or Disband
case 0x1021:
break;
//Linkshell create request
case 0x1025:
CreateLinkshellPacket createLinkshellPacket = new CreateLinkshellPacket(subpacket.data);

View File

@ -212,13 +212,13 @@ namespace FFXIVClassic_World_Server
//Send party, retainer, ls groups
Party pt = mPartyManager.GetParty(session.sessionId);
mPartyManager.AddToParty(pt.groupIndex, 156);
mPartyManager.AddToParty(pt.groupIndex, 157);
mPartyManager.AddToParty(pt.groupIndex, 158);
mPartyManager.AddToParty(pt.groupIndex, 159);
mPartyManager.AddToParty(pt.groupIndex, 160);
mPartyManager.AddToParty(pt.groupIndex, 161);
mPartyManager.AddToParty(pt.groupIndex, 162);
if (session.sessionId == 0x6c)
{
mPartyManager.AddToParty(pt.groupIndex, 156);
}
pt.SendGroupPackets(session);
SendPartySync(pt);
mRetainerGroupManager.GetRetainerGroup(session.sessionId).SendGroupPackets(session);
@ -238,12 +238,18 @@ namespace FFXIVClassic_World_Server
}
public void SendPartySync(Party party)
{
{
List<ZoneServer> alreadySent = new List<ZoneServer>();
foreach (uint member in party.members)
{
Session session = Server.GetServer().GetSession(member);
if (session == null)
continue;
if (alreadySent.Contains(session.routing1))
continue;
alreadySent.Add(session.routing1);
SubPacket syncPacket = PartySyncPacket.BuildPacket(session, party);
session.routing1.SendPacket(syncPacket);
}