1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-20 11:47:48 +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>
<Compile Include="actors\area\PrivateArea.cs" />
<Compile Include="actors\area\PrivateAreaContent.cs" />
<Compile Include="actors\area\SpawnLocation.cs" />
<Compile Include="actors\area\Zone.cs" />
<Compile Include="actors\chara\npc\ActorClass.cs" />
@ -88,11 +89,12 @@
<Compile Include="actors\director\Director.cs" />
<Compile Include="actors\EventList.cs" />
<Compile Include="actors\group\ContentGroup.cs" />
<Compile Include="actors\group\Work\ContentGroupWork.cs" />
<Compile Include="actors\group\Work\GlobalTemp.cs" />
<Compile Include="actors\group\Group.cs" />
<Compile Include="actors\group\MonsterParty.cs" />
<Compile Include="actors\group\Party.cs" />
<Compile Include="actors\group\Relation.cs" />
<Compile Include="actors\group\Work\ContentWork.cs" />
<Compile Include="actors\group\Work\GroupGlobalSave.cs" />
<Compile Include="actors\group\Work\GroupGlobalTemp.cs" />
<Compile Include="actors\group\Work\GroupMemberSave.cs" />
@ -209,9 +211,13 @@
<Compile Include="packets\send\groups\GroupMember.cs" />
<Compile Include="packets\send\groups\GroupMembersBeginPacket.cs" />
<Compile Include="packets\send\groups\GroupMembersEndPacket.cs" />
<Compile Include="packets\send\groups\ContentMembersX08Packet.cs" />
<Compile Include="packets\send\groups\GroupMembersX08Packet.cs" />
<Compile Include="packets\send\groups\ContentMembersX16Packet.cs" />
<Compile Include="packets\send\groups\GroupMembersX16Packet.cs" />
<Compile Include="packets\send\groups\ContentMembersX32Packet.cs" />
<Compile Include="packets\send\groups\GroupMembersX32Packet.cs" />
<Compile Include="packets\send\groups\ContentMembersX64Packet.cs" />
<Compile Include="packets\send\groups\GroupMembersX64Packet.cs" />
<Compile Include="packets\send\groups\SynchGroupWorkValuesPacket.cs" />
<Compile Include="packets\send\player\InfoRequestResponsePacket.cs" />

View file

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

View file

@ -36,13 +36,16 @@ namespace FFXIVClassic_Map_Server
private Dictionary<uint, ActorClass> actorClasses = new Dictionary<uint,ActorClass>();
private Dictionary<ulong, Party> currentPlayerParties = new Dictionary<ulong, Party>(); //GroupId, Party object
private Object groupLock = new Object();
private Server mServer;
private const int MILIS_LOOPTIME = 10;
private Timer mZoneTimer;
//Content Groups
public Dictionary<ulong, Group> mContentGroups = new Dictionary<ulong, Group>();
private Object groupLock = new Object();
public ulong groupIndexId = 1;
public WorldManager(Server server)
{
mServer = server;
@ -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)
{
SubPacket packet = CreateLinkshellPacket.BuildPacket(player.playerSession, name, crest, player.actorId);

View file

@ -46,11 +46,6 @@ namespace FFXIVClassic_Map_Server.Actors
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)
: base(id)
{
@ -293,7 +288,7 @@ namespace FFXIVClassic_Map_Server.Actors
#endregion
public Actor FindActorInZone(uint id)
public Actor FindActorInArea(uint id)
{
if (!mActorList.ContainsKey(id))
return null;
@ -388,6 +383,29 @@ namespace FFXIVClassic_Map_Server.Actors
AddActorToZone(npc);
}
public Npc SpawnActor(uint classId, string uniqueId, float x, float y, float z, float rot = 0, ushort state = 0, uint animId = 0)
{
ActorClass actorClass = Server.GetWorldManager().GetActorClass(classId);
if (actorClass == null)
return null;
uint zoneId;
if (this is PrivateArea)
zoneId = ((PrivateArea)this).GetParentZone().actorId;
else
zoneId = actorId;
Npc npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null);
npc.LoadEventConditions(actorClass.eventConditions);
AddActorToZone(npc);
return npc;
}
public Director GetWeatherDirector()
{
return mWeatherDirector;
@ -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)
{
lock (directorLock)
@ -481,5 +474,6 @@ namespace FFXIVClassic_Map_Server.Actors
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
{
Dictionary<string, Dictionary<uint, PrivateArea>> privateAreas = new Dictionary<string, Dictionary<uint, PrivateArea>>();
Dictionary<string, List<PrivateArea>> instancedPrivateAreas = new Dictionary<string, List<PrivateArea>>();
Dictionary<string, List<PrivateAreaContent>> contentAreas = new Dictionary<string, List<PrivateAreaContent>>();
public Zone(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid)
: base(id, zoneName, regionId, className, bgmDay, bgmNight, bgmBattle, isIsolated, isInn, canRideChocobo, canStealth, isInstanceRaid)
@ -93,5 +93,28 @@ namespace FFXIVClassic_Map_Server.actors.area
}
}
public Actor FindActorInZone(uint id)
{
if (!mActorList.ContainsKey(id))
{
foreach(Dictionary<uint, PrivateArea> paList in privateAreas.Values)
{
foreach(PrivateArea pa in paList.Values)
{
Actor actor = pa.FindActorInArea(id);
if (actor != null)
return actor;
}
}
return null;
}
else
return mActorList[id];
}
public void CreateContentArea()
{
}
}
}

View file

@ -3,6 +3,7 @@ using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.group;
using FFXIVClassic_Map_Server.Actors.Chara;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.utils;
namespace FFXIVClassic_Map_Server.Actors
{
@ -87,6 +88,18 @@ namespace FFXIVClassic_Map_Server.Actors
player.QueuePacket(SetActorQuestGraphicPacket.BuildPacket(player.actorId, actorId, graphicNum));
}
public void SetCurrentContentGroup(uint groupType, Player player = null)
{
charaWork.currentContentGroup = groupType;
if (player != null)
{
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/currentContentGroup", this, actorId);
propPacketUtil.AddProperty("charaWork.currentContentGroup");
player.QueuePackets(propPacketUtil.Done());
}
}
}
}

View file

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

View file

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

View file

@ -1,7 +1,11 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.actors.group.Work;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.group;
using FFXIVClassic_Map_Server.packets.send.groups;
using FFXIVClassic_Map_Server.utils;
using System;
using System.Collections.Generic;
using System.Linq;
@ -12,17 +16,33 @@ namespace FFXIVClassic_Map_Server.actors.group
{
class ContentGroup : Group
{
public ContentGroupWork contentGroupWork = new ContentGroupWork();
private Director director;
private List<uint> members = new List<uint>();
public ContentGroup(ulong groupIndex, uint[] initialMembers) : base(groupIndex)
public ContentGroup(ulong groupIndex, Director director, uint[] initialMembers) : base(groupIndex)
{
if (initialMembers != null)
{
for (int i = 0; i < initialMembers.Length; i++)
members.Add(initialMembers[i]);
}
public void AddMember(uint memberId)
this.director = director;
contentGroupWork._globalTemp.director = (ulong)director.actorId << 32;
}
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);
}
@ -44,18 +64,68 @@ namespace FFXIVClassic_Map_Server.actors.group
return groupMembers;
}
public override int GetMemberCount()
{
return members.Count;
}
public override void SendInitWorkValues(Session session)
{
SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex);
groupWork.addProperty(this, "contentGroupWork._globalTemp.director");
groupWork.addByte(Utils.MurmurHash2("contentGroupWork.property[0]", 0), 1);
groupWork.setTarget("/_init");
SubPacket test = groupWork.buildPacket(session.id, session.id);
test.DebugPrintSubPacket();
session.QueuePacket(test, true, false);
}
public override void SendGroupPackets(Session session)
{
ulong time = Utils.MilisUnixTimeStampUTC();
List<GroupMember> members = BuildMemberList(session.id);
session.QueuePacket(GroupHeaderPacket.buildPacket(session.id, session.GetActor().zoneId, time, this), true, false);
session.QueuePacket(GroupMembersBeginPacket.buildPacket(session.id, session.GetActor().zoneId, time, this), true, false);
int currentIndex = 0;
while (true)
{
if (GetMemberCount() - currentIndex >= 64)
session.QueuePacket(ContentMembersX64Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex), true, false);
else if (GetMemberCount() - currentIndex >= 32)
session.QueuePacket(ContentMembersX32Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex), true, false);
else if (GetMemberCount() - currentIndex >= 16)
session.QueuePacket(ContentMembersX16Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex), true, false);
else if (GetMemberCount() - currentIndex > 0)
session.QueuePacket(ContentMembersX08Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex), true, false);
else
break;
}
session.QueuePacket(GroupMembersEndPacket.buildPacket(session.id, session.GetActor().zoneId, time, this), true, false);
}
public void SendCurrentContentSync(Actor currentContentChanged)
{
foreach (uint memberId in members)
{
Session session = Server.GetServer().GetSession(memberId);
if (session != null)
{
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/currentContentGroup", currentContentChanged, session.id);
propPacketUtil.AddProperty("charaWork.currentContentGroup");
session.GetActor().QueuePackets(propPacketUtil.Done());
}
}
}
public override uint GetTypeId()
{
return Group.ContentGroup_SimpleContentGroup24A;
return Group.ContentGroup_SimpleContentGroup24B;
}

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();
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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.actors.group.Work
{
class ContentWork
class GlobalTemp
{
public GroupGlobalTemp _globalTemp = new GroupGlobalTemp();
public ulong director;
}
}

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.flag1 = flag1;
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((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++;

View file

@ -108,7 +108,7 @@ namespace FFXIVClassic_Map_Server.packets.send.groups
string[] split = name.Split('.');
int arrayIndex = 0;
if (!(split[0].Equals("work") || split[0].Equals("partyGroupWork")))
if (!(split[0].Equals("work") || split[0].Equals("partyGroupWork") || split[0].Equals("contentGroupWork")))
return;
Object curObj = group;