Built subpackets to let the zone servers talk to the world server. Implemented cross-server zoning but the E2 packet or something isn't being sent.

This commit is contained in:
Filip Maj 2016-12-03 12:19:59 -05:00
parent 58fda93b45
commit e30831fdc5
27 changed files with 674 additions and 113 deletions

View file

@ -258,6 +258,8 @@ namespace FFXIVClassic_Map_Server
positionY = @y,
positionZ = @z,
rotation = @rot,
destinationZoneId = @destZone,
destinationSpawnType = @destSpawn,
currentZoneId = @zoneId
WHERE id = @charaId
";
@ -269,6 +271,8 @@ namespace FFXIVClassic_Map_Server
cmd.Parameters.AddWithValue("@z", player.positionZ);
cmd.Parameters.AddWithValue("@rot", player.rotation);
cmd.Parameters.AddWithValue("@zoneId", player.zoneId);
cmd.Parameters.AddWithValue("@destZone", player.destinationZone);
cmd.Parameters.AddWithValue("@destSpawn", player.destinationSpawnType);
cmd.ExecuteNonQuery();
}
@ -402,7 +406,9 @@ namespace FFXIVClassic_Map_Server
tribe,
restBonus,
achievementPoints,
playTime
playTime,
destinationZoneId,
destinationSpawnType
FROM characters WHERE id = @charId";
cmd = new MySqlCommand(query, conn);
@ -419,8 +425,7 @@ namespace FFXIVClassic_Map_Server
player.oldRotation = player.rotation = reader.GetFloat(4);
player.currentMainState = reader.GetUInt16(5);
player.zoneId = reader.GetUInt32(6);
player.isZoning = true;
player.zone = Server.GetWorldManager().GetZone(player.zoneId);
player.isZoning = true;
player.gcCurrent = reader.GetByte(7);
player.gcRankLimsa = reader.GetByte(8);
player.gcRankGridania = reader.GetByte(9);
@ -434,6 +439,13 @@ namespace FFXIVClassic_Map_Server
player.playerWork.restBonusExpRate = reader.GetInt32(17);
player.achievementPoints = reader.GetUInt32(18);
player.playTime = reader.GetUInt32(19);
player.destinationZone = reader.GetUInt32("destinationZoneId");
player.destinationSpawnType = reader.GetByte("destinationSpawnType");
if (player.destinationZone != 0)
player.zoneId = player.destinationZone;
player.zone = Server.GetWorldManager().GetZone(player.zoneId);
}
}

View file

@ -256,6 +256,10 @@
<Compile Include="packets\send\_0xE2Packet.cs" />
<Compile Include="packets\receive\PingPacket.cs" />
<Compile Include="packets\receive\UpdatePlayerPositionPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\SessionEndPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\SessionBeginPacket.cs" />
<Compile Include="packets\WorldPackets\Send\SessionBeginConfirmPacket.cs" />
<Compile Include="packets\WorldPackets\Send\SessionEndConfirmPacket.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="lua\LuaUtils.cs" />
@ -280,6 +284,7 @@
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
<Compile Include="packets\WorldPackets\Send\WorldRequestZoneChangePacket.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">

View file

@ -17,7 +17,9 @@ using FFXIVClassic_Map_Server.packets.receive.recruitment;
using FFXIVClassic_Map_Server.packets.send.recruitment;
using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send;
using FFXIVClassic_Map_Server.packets.WorldPackets.Receive;
namespace FFXIVClassic_Map_Server
{
@ -32,23 +34,36 @@ namespace FFXIVClassic_Map_Server
public void ProcessPacket(ZoneConnection client, SubPacket subpacket)
{
Session session = mServer.GetSession(subpacket.header.targetId);
Session session = mServer.GetSession(subpacket.header.targetId);
if (session == null && subpacket.gameMessage.opcode != 0x1000)
return;
//Normal Game Opcode
switch (subpacket.gameMessage.opcode)
{
//World Server - End Session
//World Server - Session Begin
case 0x1000:
session.GetActor().CleanupAndSave();
break;
//World Server - End Session and Zone
case 0x1001:
subpacket.DebugPrintSubPacket();
session = mServer.AddSession(subpacket.header.targetId);
session.GetActor().CleanupAndSave();
if (session.GetActor().destinationZone != 0)
Server.GetWorldManager().DoZoneIn(session.GetActor(), false, session.GetActor().destinationSpawnType);
client.FlushQueuedSendPackets();
break;
//World Server - Begin Session
case 0x1002:
break;
//World Server - Session End
case 0x1001:
SessionEndPacket endSessionPacket = new SessionEndPacket(subpacket.data);
if (endSessionPacket.destinationZoneId == 0)
session.GetActor().CleanupAndSave();
else
session.GetActor().CleanupAndSave(endSessionPacket.destinationZoneId, endSessionPacket.destinationSpawnType, endSessionPacket.destinationX, endSessionPacket.destinationY, endSessionPacket.destinationZ, endSessionPacket.destinationRot);
client.QueuePacket(SessionEndConfirmPacket.BuildPacket(session, endSessionPacket.destinationZoneId), true, false);
client.FlushQueuedSendPackets();
break;
//Ping
case 0x0001:
//subpacket.DebugPrintSubPacket();
@ -60,12 +75,12 @@ namespace FFXIVClassic_Map_Server
case 0x0002:
subpacket.DebugPrintSubPacket();
session = mServer.AddSession(subpacket.header.targetId);
client.QueuePacket(_0x2Packet.BuildPacket(session.id), true, false);
client.QueuePacket(_0x2Packet.BuildPacket(session.id), true, false);
Server.GetWorldManager().DoLogin(session.GetActor());
LuaEngine.OnBeginLogin(session.GetActor());
Server.GetWorldManager().DoZoneIn(session.GetActor(), true, 0x1);
LuaEngine.OnLogin(session.GetActor());
client.FlushQueuedSendPackets();
@ -98,7 +113,6 @@ namespace FFXIVClassic_Map_Server
//Update Position
case 0x00CA:
//Update Position
subpacket.DebugPrintSubPacket();
UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
session.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
session.GetActor().SendInstanceUpdate();

View file

@ -95,6 +95,9 @@ namespace FFXIVClassic_Map_Server
public Session AddSession(uint id)
{
if (mSessionList.ContainsKey(id))
return mSessionList[id];
Session session = new Session(id);
mSessionList.Add(id, session);
return session;
@ -104,8 +107,7 @@ namespace FFXIVClassic_Map_Server
{
if (mSessionList.ContainsKey(id))
{
mSessionList[id].GetActor().CleanupAndSave();
mSessionList.Remove(id);
mSessionList.Remove(id);
}
}
@ -244,6 +246,11 @@ namespace FFXIVClassic_Map_Server
#endregion
public static ZoneConnection GetWorldConnection()
{
return mWorldConnection;
}
public static Server GetServer()
{
return mSelf;
@ -252,12 +259,7 @@ namespace FFXIVClassic_Map_Server
public static CommandProcessor GetCommandProcessor()
{
return mCommandProcessor;
}
public static ZoneConnection GetWorldConnection()
{
return mWorldConnection;
}
}
public static WorldManager GetWorldManager()
{

View file

@ -384,9 +384,8 @@ namespace FFXIVClassic_Map_Server
oldZone.AddActorToZone(player);
}
var message = "WorldManager.DoZoneChange: unable to change areas, new area is not valid.";
player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM, "[Debug]", message);
Program.Log.Debug(message);
Program.Log.Debug("Request to change to zone not on this server by: {0}.", player.customDisplayName);
RequestWorldServerZoneChange(player, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation);
return;
}
@ -450,8 +449,8 @@ namespace FFXIVClassic_Map_Server
}
}
//Login Zone In
public void DoLogin(Player player)
//Session started, zone into world
public void DoZoneIn(Player player, bool isLogin, ushort spawnType)
{
//Add player to new zone and update
Zone zone = GetZone(player.zoneId);
@ -462,15 +461,19 @@ namespace FFXIVClassic_Map_Server
//Set the current zone and add player
player.zone = zone;
LuaEngine.OnBeginLogin(player);
zone.AddActorToZone(player);
//Send packets
player.SendZoneInPackets(this, 0x1);
if (!isLogin)
{
player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId), true, false);
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x0), true, false);
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x0), true, false);
}
LuaEngine.OnLogin(player);
player.SendZoneInPackets(this, spawnType);
LuaEngine.OnZoneIn(player);
}
@ -485,6 +488,12 @@ namespace FFXIVClassic_Map_Server
}
private void RequestWorldServerZoneChange(Player player, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
{
ZoneConnection zc = Server.GetWorldConnection();
zc.RequestZoneChange(player.playerSession.id, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation);
}
public Player GetPCInWorld(string name)
{
foreach (Zone zone in zoneList.Values)

View file

@ -70,7 +70,7 @@ namespace FFXIVClassic_Map_Server.Actors
return SetActorSpeedPacket.BuildPacket(actorId, playerActorId);
}
public SubPacket CreateSpawnPositonPacket(uint playerActorId, uint spawnType)
public SubPacket CreateSpawnPositonPacket(uint playerActorId, ushort spawnType)
{
SubPacket spawnPacket;
if (!spawnedFirstTime && playerActorId == actorId)
@ -91,7 +91,7 @@ namespace FFXIVClassic_Map_Server.Actors
return spawnPacket;
}
public SubPacket CreateSpawnTeleportPacket(uint playerActorId, uint spawnType)
public SubPacket CreateSpawnTeleportPacket(uint playerActorId, ushort spawnType)
{
SubPacket spawnPacket;
@ -223,7 +223,7 @@ namespace FFXIVClassic_Map_Server.Actors
return GetSpawnPackets(playerActorId, 0x1);
}
public virtual BasePacket GetSpawnPackets(uint playerActorId, uint spawnType)
public virtual BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType)
{
List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateAddActorPacket(playerActorId, 8));

View file

@ -116,7 +116,7 @@ namespace FFXIVClassic_Map_Server.Actors
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
}
public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType)
public override BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType)
{
List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateAddActorPacket(playerActorId));

View file

@ -83,7 +83,9 @@ namespace FFXIVClassic_Map_Server.Actors
public Coroutine currentEventRunning;
//Player Info
//Player Info
public uint destinationZone;
public ushort destinationSpawnType;
public uint[] timers = new uint[20];
public ushort currentJob;
public uint currentTitle;
@ -257,9 +259,9 @@ namespace FFXIVClassic_Map_Server.Actors
else
lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", false, false, false, false, false, true);
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
}
public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType)
}
public override BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType)
{
List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateAddActorPacket(playerActorId, 8));
@ -646,14 +648,47 @@ namespace FFXIVClassic_Map_Server.Actors
}
public void CleanupAndSave()
{
{
playerSession.LockUpdates(true);
//Remove actor from zone and main server list
zone.RemoveActorFromZone(this);
//Set Destination to 0
this.destinationZone = 0;
this.destinationSpawnType = 0;
//Save Player
Database.SavePlayerPlayTime(this);
Database.SavePlayerPosition(this);
Program.Log.Info("{0} has been logged out and saved.", this.customDisplayName);
Database.SavePlayerPosition(this);
Server.GetServer().RemoveSession(playerSession.id);
Program.Log.Info("{0} has been removed from the session list.", this.customDisplayName);
}
public void CleanupAndSave(uint destinationZone, ushort spawnType, float destinationX, float destinationY, float destinationZ, float destinationRot)
{
playerSession.LockUpdates(true);
//Remove actor from zone and main server list
zone.RemoveActorFromZone(this);
//Set destination
this.destinationZone = destinationZone;
this.destinationSpawnType = spawnType;
this.positionX = destinationX;
this.positionY = destinationY;
this.positionZ = destinationZ;
this.rotation = destinationRot;
//Save Player
Database.SavePlayerPlayTime(this);
Database.SavePlayerPosition(this);
Server.GetServer().RemoveSession(playerSession.id);
Program.Log.Info("{0} has been removed from the session list.", this.customDisplayName);
}
public Area GetZone()

View file

@ -20,6 +20,8 @@ namespace FFXIVClassic_Map_Server.dataobjects
public uint languageCode = 1;
private uint lastPingPacket = Utils.UnixTimeStampUTC();
public bool isUpdatesLocked = false;
public string errorMessage = "";
public Session(uint sessionId)
@ -63,6 +65,9 @@ namespace FFXIVClassic_Map_Server.dataobjects
public void UpdatePlayerActorPosition(float x, float y, float z, float rot, ushort moveState)
{
if (isUpdatesLocked)
return;
playerActor.oldPositionX = playerActor.positionX;
playerActor.oldPositionY = playerActor.positionY;
playerActor.oldPositionZ = playerActor.positionZ;
@ -80,6 +85,9 @@ namespace FFXIVClassic_Map_Server.dataobjects
public void UpdateInstance(List<Actor> list)
{
if (isUpdatesLocked)
return;
List<BasePacket> basePackets = new List<BasePacket>();
List<SubPacket> RemoveActorSubpackets = new List<SubPacket>();
List<SubPacket> posUpdateSubpackets = new List<SubPacket>();
@ -132,5 +140,10 @@ namespace FFXIVClassic_Map_Server.dataobjects
actorInstanceList.Clear();
}
public void LockUpdates(bool f)
{
isUpdatesLocked = f;
}
}
}

View file

@ -5,6 +5,7 @@ using FFXIVClassic.Common;
using System.Collections.Concurrent;
using System.Net;
using System.Collections.Generic;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send;
namespace FFXIVClassic_Map_Server.dataobjects
{
@ -63,5 +64,11 @@ namespace FFXIVClassic_Map_Server.dataobjects
if (socket.Connected)
socket.Disconnect(false);
}
public void RequestZoneChange(uint sessionId, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
{
WorldRequestZoneChangePacket.BuildPacket(sessionId, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation).DebugPrintSubPacket();
QueuePacket(WorldRequestZoneChangePacket.BuildPacket(sessionId, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation), true, false);
}
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{
class SessionBeginPacket
{
public bool invalidPacket = false;
public SessionBeginPacket(byte[] data)
{
}
}
}

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{
class SessionEndPacket
{
public uint destinationZoneId;
public ushort destinationSpawnType;
public float destinationX;
public float destinationY;
public float destinationZ;
public float destinationRot;
public bool invalidPacket = false;
public SessionEndPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
destinationZoneId = binReader.ReadUInt32();
destinationSpawnType = binReader.ReadUInt16();
destinationX = binReader.ReadSingle();
destinationY = binReader.ReadSingle();
destinationZ = binReader.ReadSingle();
destinationRot = binReader.ReadSingle();
}
catch (Exception)
{
invalidPacket = true;
}
}
}
}
}
}

View file

@ -0,0 +1,27 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send
{
class SessionBeginConfirmPacket
{
public const ushort OPCODE = 0x1000;
public const uint PACKET_SIZE = 0x28;
public static SubPacket BuildPacket(Session session, ushort errorCode = 0)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)session.id);
binWriter.Write((UInt16)errorCode);
}
}
return new SubPacket(true, OPCODE, 0, session.id, data);
}
}
}

View file

@ -0,0 +1,28 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send
{
class SessionEndConfirmPacket
{
public const ushort OPCODE = 0x1001;
public const uint PACKET_SIZE = 0x30;
public static SubPacket BuildPacket(Session session, uint destinationZone, ushort errorCode = 0)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)session.id);
binWriter.Write((UInt16)errorCode);
binWriter.Write((UInt32)destinationZone);
}
}
return new SubPacket(true, OPCODE, 0, session.id, data);
}
}
}

View file

@ -0,0 +1,37 @@
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.WorldPackets.Send
{
class WorldRequestZoneChangePacket
{
public const ushort OPCODE = 0x1002;
public const uint PACKET_SIZE = 0x048;
public static SubPacket BuildPacket(uint sessionId, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)sessionId);
binWriter.Write((UInt32)destinationZoneId);
binWriter.Write((UInt16)spawnType);
binWriter.Write((Single)spawnX);
binWriter.Write((Single)spawnY);
binWriter.Write((Single)spawnZ);
binWriter.Write((Single)spawnRotation);
}
}
return new SubPacket(OPCODE, sessionId, sessionId, data);
}
}
}

View file

@ -24,7 +24,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor
public const float INNPOS_Z = 165.050003f;
public const float INNPOS_ROT = -1.530000f;
public static SubPacket BuildPacket(uint sourceActorID, uint targetActorID, uint actorId, float x, float y, float z, float rotation, uint spawnType, bool isZoningPlayer)
public static SubPacket BuildPacket(uint sourceActorID, uint targetActorID, uint actorId, float x, float y, float z, float rotation, ushort spawnType, bool isZoningPlayer)
{
byte[] data = new byte[PACKET_SIZE-0x20];