有待进一步修复角色数据生成至大厅

This commit is contained in:
Longfeng Qin 2024-09-18 00:55:35 +08:00
parent 5a151be0da
commit 33ce4d4333
15 changed files with 317 additions and 68 deletions

View File

@ -981,12 +981,12 @@ namespace PSO2SERVER
ServerApp.Instance.Server.Clients[id].SendPacket(new TeleportTransferPacket(ObjectManager.Instance.getObjectByID("lobby", 443), destination));
context.SendPacket(0x8, 0xB, 0x0, ObjectManager.Instance.getObjectByID(443).GenerateSpawnBlob());
context.SendPacket(new ObjectSpawnPacket(ObjectManager.Instance.getObjectByID(443)));
var objects = ObjectManager.Instance.GetObjectsForZone("casino");
foreach (var obj in objects)
{
context.SendPacket(0x8, 0xB, 0x0, obj.GenerateSpawnBlob());
context.SendPacket(new ObjectSpawnPacket(obj));
}
@ -1021,7 +1021,7 @@ namespace PSO2SERVER
Things = new PSOObject.PSOObjectThing[0]
};
client.SendPacket(0x8, 0xB, 0x0, obj.GenerateSpawnBlob());
client.SendPacket(new ObjectSpawnPacket(obj));
}
private void RunLUA(string[] args, int length, string full, Client client)

View File

@ -160,7 +160,7 @@ namespace PSO2SERVER.Models
public sbyte Value3;
}
public enum SkinColor
public enum SkinColor : byte
{
RaceDefined,
Human,

View File

@ -89,7 +89,7 @@ namespace PSO2SERVER.Object
}
internal PSONPC[] getNPCSForZone(string zone)
internal PSONPC[] GetNpcSForZone(string zone)
{
List<PSONPC> npcs = new List<PSONPC>();
using (var db = new ServerEf())

View File

@ -23,10 +23,6 @@ namespace PSO2SERVER.Packets.Handlers
//var info = string.Format("[<--] 接收到的数据 (hex): ");
//Logger.WriteHex(info, data);
var setting = reader.ReadStruct<Character.CharParam>();
//reader.ReadBytes(12); // 12 unknown bytes
//reader.ReadByte(); // VoiceType
//reader.ReadBytes(5); // 5 unknown bytes
//reader.ReadUInt16(); // VoiceData
var name = reader.ReadFixedLengthUtf16(16);//玩家名称 宽字符
@ -76,10 +72,6 @@ namespace PSO2SERVER.Packets.Handlers
context.Character = newCharacter;
// Set Player ID
//var writer = new PacketWriter();
//writer.Write(0);
//writer.Write((uint) context.User.PlayerId);
//context.SendPacket(0x11, 0x07, 0, writer.ToArray());
context.SendPacket(new CharacterCreateResponsePacket(CharacterCreateResponsePacket.CharacterCreationStatus.Success, (uint)context.User.PlayerId));
// Spawn

View File

@ -0,0 +1,54 @@
using PSO2SERVER.Models;
using PSO2SERVER.Zone;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using static PSO2SERVER.Zone.Map;
namespace PSO2SERVER.Packets.PSOPackets
{
public class MapTransferPacket : Packet
{
private readonly Map _map;
private readonly int _playerid;
public MapTransferPacket(Map map, int PlayerId)
{
_map = map;
_playerid = PlayerId;
}
#region implemented abstract members of Packet
public override byte[] Build()
{
PacketWriter writer = new PacketWriter();
writer.WriteStruct(new ObjectHeader(3, EntityType.Map));
writer.WriteStruct(new ObjectHeader((uint)_playerid, EntityType.Player));
writer.Write(0x1); // 8 Zeros
writer.Write(0); // 8 Zeros
writer.Write(~(uint)_map.Type); // F4 FF FF FF
writer.Write(_map.MapID); // Map ID maybe
writer.Write((uint)_map.Flags);
writer.Write(_map.GenerationArgs.seed); // 81 8F E6 19 (Maybe seed)
writer.Write(_map.VariantID); // Randomgen enable / disable maybe
writer.Write(_map.GenerationArgs.xsize); // X Size
writer.Write(_map.GenerationArgs.ysize); // Y Size
writer.Write(1);
writer.Write(1);
writer.Write(~0); // FF FF FF FF FF FF FF FF
writer.Write(0x301);
return writer.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x03, 0x00, PacketFlags.None);
}
#endregion
}
}

View File

@ -1,6 +1,7 @@
using PSO2SERVER.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
@ -8,25 +9,24 @@ namespace PSO2SERVER.Packets.PSOPackets
{
public class LoadingLevelPacket : Packet
{
private readonly byte _subtype;
private readonly byte _type;
private readonly string _file;
public LoadingLevelPacket()
public LoadingLevelPacket(string file)
{
_type = 0x03;
_subtype = 0x24;
_file = file;
}
#region implemented abstract members of Packet
public override byte[] Build()
{
return new byte[0];
var setAreaPacket = File.ReadAllBytes("Resources\\quests\\" + _file + ".bin");
return setAreaPacket;
}
public override PacketHeader GetHeader()
{
return new PacketHeader(_type, _subtype, PacketFlags.PACKED);
return new PacketHeader(0x03, 0x24, PacketFlags.PACKED);
}
#endregion

View File

@ -8,13 +8,8 @@ namespace PSO2SERVER.Packets.PSOPackets
{
public class DespawnObjectPacket : Packet
{
private readonly byte _subtype;
private readonly byte _type;
public DespawnObjectPacket()
{
_type = 0x04;
_subtype = 0x06;
}
#region implemented abstract members of Packet
@ -26,11 +21,7 @@ namespace PSO2SERVER.Packets.PSOPackets
public override PacketHeader GetHeader()
{
return new PacketHeader
{
Type = _type,
Subtype = _subtype
};
return new PacketHeader(0x04, 0x06, PacketFlags.None);
}
#endregion

View File

@ -0,0 +1,37 @@
using Mysqlx.Crud;
using PSO2SERVER.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PSO2SERVER.Packets.PSOPackets
{
public class DespawnPlayerPacket : Packet
{
private readonly int _other_playerid;
private readonly int _user_playerid;
public DespawnPlayerPacket(int other_playerid, int user_playerid)
{
_other_playerid = other_playerid;
_user_playerid = user_playerid;
}
#region implemented abstract members of Packet
public override byte[] Build()
{
PacketWriter writer = new PacketWriter();
writer.WriteStruct(new ObjectHeader((uint)_other_playerid, EntityType.Player));
writer.WriteStruct(new ObjectHeader((uint)_user_playerid, EntityType.Player));
return writer.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x04, 0x3B, PacketFlags.OBJECT_RELATED);
}
#endregion
}
}

View File

@ -0,0 +1,34 @@
using PSO2SERVER.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PSO2SERVER.Packets.PSOPackets
{
public class SetPlayerIDPacket : Packet
{
private readonly uint _PlayerId;
public SetPlayerIDPacket(uint PlayerId)
{
_PlayerId = PlayerId;
}
#region implemented abstract members of Packet
public override byte[] Build()
{
var pkt = new PacketWriter();
pkt.WritePlayerHeader(_PlayerId);
return pkt.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x06, 0x00, PacketFlags.None);
}
#endregion
}
}

View File

@ -4,6 +4,16 @@ namespace PSO2SERVER.Packets.PSOPackets
{
public class CharacterSpawnPacket : Packet
{
public enum CharacterSpawnType
{
/// Spawned character is not related to the receiver.
Other = 0x27,
/// Spawned character is related to the receiver.
Myself = 0x2F,
Undefined = 0xFF,
}
private readonly Character _character;
public bool IsItMe = true;
public PSOLocation Position;
@ -41,18 +51,25 @@ namespace PSO2SERVER.Packets.PSOPackets
writer.Write((uint) 1); // 0x4C
writer.Write((uint) 53); // 0x50
writer.Write((uint) 0); // 0x54
writer.Write((uint) (IsItMe ? 47 : 39)); // 0x58
writer.Write((ushort) 559); // 0x5C
writer.Write((ushort) 306); // 0x5E
writer.Write((uint) _character.Player.PlayerId); // player ID copy
writer.Write((uint) 0); // "char array ugggghhhhh" according to PolarisLegacy
writer.Write((uint) 0); // "voiceParam_unknown4"
writer.Write((uint) 0); // "voiceParam_unknown8"
writer.Write((uint) (IsItMe ? 0x2F : 0x27)); // 0x58
writer.Write((ushort) 0); // 0x5C
writer.Write((ushort) 0); // 0x5E
writer.Write((uint)_character.CharacterId);
writer.Write((uint)_character.player_id);
writer.Write(_character.voice_type);
writer.Write((uint)_character.voice_pitch);
//writer.Write((uint)_character.CharacterId); // player ID copy
//writer.Write((uint)0); // "char array ugggghhhhh" according to PolarisLegacy
//writer.Write((uint)0); // "voiceParam_unknown4"
//writer.Write((uint)0); // "voiceParam_unknown8"
writer.WriteFixedLengthUtf16(_character.Name, 16);
writer.Write((uint) 0); // 0x90
writer.Write((uint)0); // 0x90
writer.WriteStruct(_character.Looks);
writer.WriteStruct(_character.Jobs);
writer.WriteFixedLengthUtf16("", 32); // title?
writer.Write((uint) 0); // 0x204
writer.Write((uint) 0); // gmflag?
writer.WriteFixedLengthUtf16(_character.Player.Nickname, 16); // nickname, maybe not 16 chars?

View File

@ -0,0 +1,47 @@
using Org.BouncyCastle.Utilities;
using PSO2SERVER.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using static PSO2SERVER.Models.PSOObject;
namespace PSO2SERVER.Packets.PSOPackets
{
public class ObjectSpawnPacket : Packet
{
private readonly PSOObject _obj;
public ObjectSpawnPacket(PSOObject obj)
{
_obj = obj;
}
#region implemented abstract members of Packet
public override byte[] Build()
{
PacketWriter writer = new PacketWriter();
writer.WriteStruct(_obj.Header);
writer.Write(_obj.Position);
writer.Seek(2, SeekOrigin.Current); // Padding I guess...
writer.WriteFixedLengthASCII(_obj.Name, 0x34);
writer.Write(_obj.ThingFlag);
writer.Write(_obj.Things.Length);
foreach (PSOObjectThing thing in _obj.Things)
{
writer.WriteStruct(thing);
}
return writer.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x08, 0x0B, PacketFlags.None);
}
#endregion
}
}

View File

@ -0,0 +1,61 @@
using Org.BouncyCastle.Utilities;
using PSO2SERVER.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using static PSO2SERVER.Models.PSOObject;
namespace PSO2SERVER.Packets.PSOPackets
{
public class NPCSpawnPacket : Packet
{
private readonly PSOObject _obj;
public NPCSpawnPacket(PSOObject obj)
{
_obj = obj;
}
#region implemented abstract members of Packet
public override byte[] Build()
{
PacketWriter writer = new PacketWriter();
writer.WriteStruct(_obj.Header);
writer.Write(_obj.Position);
writer.Seek(2, SeekOrigin.Current); // Padding I guess...
writer.WriteFixedLengthASCII(_obj.Name, 0x20);
writer.Write(0); // Padding?
writer.Write(new byte[0xC]); // Unknown, usually zero
writer.Write((UInt16)0);
writer.Write((UInt16)0);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)1101004800); // Always this
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)1);
writer.WriteMagic(1, 0x9FCD, 0xE7);
writer.Write((UInt32)0);
return writer.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x08, 0x0C, PacketFlags.None);
}
#endregion
}
}

View File

@ -58,7 +58,7 @@ namespace PSO2SERVER.Packets.PSOPackets
writer.Write(ch.voice_pitch);
writer.WriteFixedLengthUtf16(ch.Name, 16);
writer.Write((uint)0);
writer.WriteStruct(ch.Looks); // Note: 第4集之前创造的外观似乎不再有效了
writer.WriteStruct(ch.Looks);
writer.WriteStruct(ch.Jobs);
for (var i = 0; i < 0x90; i++)

View File

@ -203,6 +203,11 @@
<Compile Include="Packets\Handlers\03-ServerHandler\03-34-TeleportCasinoToLobby.cs" />
<Compile Include="Packets\Handlers\11-ClientHandler\11-41-CreateCharacterOne.cs" />
<Compile Include="Packets\Handlers\2F-SymbolHandler\2F-06-SymbolArtHandler.cs" />
<Compile Include="Packets\PSOPackets\03-ServerPacket\03-00-MapTransferPacket.cs" />
<Compile Include="Packets\PSOPackets\04-ObjectPacket\04-3B-DespawnPlayerPacket.cs" />
<Compile Include="Packets\PSOPackets\06-PlayerStatusPackets\06-00-SetPlayerIDPacket.cs" />
<Compile Include="Packets\PSOPackets\08-SpawnPacket\08-0C-NPCSpawnPacket.cs" />
<Compile Include="Packets\PSOPackets\08-SpawnPacket\08-0B-ObjectSpawnPacket.cs" />
<Compile Include="Packets\PSOPackets\11-ClientPacket\11-03-CharacterListPacket.cs" />
<Compile Include="Packets\PSOPackets\11-ClientPacket\11-07-CharacterCreateResponsePacket.cs" />
<Compile Include="Packets\PSOPackets\04-ObjectPacket\04-06-DespawnObjectPacket.cs" />

View File

@ -60,7 +60,7 @@ namespace PSO2SERVER.Zone
GenerationArgs = new GenParam();
Objects = ObjectManager.Instance.GetObjectsForZone(Name);
NPCs = ObjectManager.Instance.getNPCSForZone(Name);
NPCs = ObjectManager.Instance.GetNpcSForZone(Name);
}
public PSOLocation GetDefaultLocation()
@ -101,29 +101,38 @@ namespace PSO2SERVER.Zone
// Set area
if (questOveride != "") // TODO: This is a temporary hack, fix me!!
{
var setAreaPacket = File.ReadAllBytes("Resources/quests/" + questOveride + ".bin");
c.SendPacket(0x03, 0x24, 0x04, setAreaPacket);
//var setAreaPacket = File.ReadAllBytes("Resources\\quests\\" + questOveride + ".bin");
//c.SendPacket(0x03, 0x24, 0x04, setAreaPacket);
c.SendPacket(new LoadingLevelPacket(questOveride));
}
else
{
PacketWriter writer = new PacketWriter();
writer.WriteStruct(new ObjectHeader(3, EntityType.Map));
writer.WriteStruct(new ObjectHeader((uint)c.User.PlayerId, EntityType.Player));
writer.Write(0x1); // 8 Zeros
writer.Write(0); // 8 Zeros
writer.Write(~(uint)Type); // F4 FF FF FF
writer.Write(MapID); // Map ID maybe
writer.Write((uint)Flags);
writer.Write(GenerationArgs.seed); // 81 8F E6 19 (Maybe seed)
writer.Write(VariantID); // Randomgen enable / disable maybe
writer.Write(GenerationArgs.xsize); // X Size
writer.Write(GenerationArgs.ysize); // Y Size
writer.Write(1);
writer.Write(1);
writer.Write(~0); // FF FF FF FF FF FF FF FF
writer.Write(0x301);
//PacketWriter writer = new PacketWriter();
//writer.WriteStruct(new ObjectHeader(3, EntityType.Map));
//writer.WriteStruct(new ObjectHeader((uint)c.User.PlayerId, EntityType.Player));
//writer.Write(0x1); // 8 Zeros
//writer.Write(0); // 8 Zeros
//writer.Write(~(uint)Type); // F4 FF FF FF
//writer.Write(MapID); // Map ID maybe
//writer.Write((uint)Flags);
//writer.Write(GenerationArgs.seed); // 81 8F E6 19 (Maybe seed)
//writer.Write(VariantID); // Randomgen enable / disable maybe
//writer.Write(GenerationArgs.xsize); // X Size
//writer.Write(GenerationArgs.ysize); // Y Size
//writer.Write(1);
//writer.Write(1);
//writer.Write(~0); // FF FF FF FF FF FF FF FF
//writer.Write(0x301);
c.SendPacket(0x3, 0x0, 0x0, writer.ToArray());
//c.SendPacket(0x3, 0x0, 0x0, writer.ToArray());
var _map = new Map("", MapID, VariantID, Type, Flags);
_map.GenerationArgs.seed = GenerationArgs.seed;
_map.GenerationArgs.xsize = GenerationArgs.xsize;
_map.GenerationArgs.ysize = GenerationArgs.ysize;
c.SendPacket(new MapTransferPacket(_map, c.User.PlayerId));
}
if (c.CurrentZone != null)
@ -131,9 +140,10 @@ namespace PSO2SERVER.Zone
c.CurrentZone.RemoveClient(c);
}
var setPlayerId = new PacketWriter();
setPlayerId.WritePlayerHeader((uint)c.User.PlayerId);
c.SendPacket(0x06, 0x00, 0, setPlayerId.ToArray());
//var setPlayerId = new PacketWriter();
//setPlayerId.WritePlayerHeader((uint)c.User.PlayerId);
//c.SendPacket(0x06, 0x00, 0, setPlayerId.ToArray());
c.SendPacket(new SetPlayerIDPacket((uint)c.User.PlayerId));
// Spawn Character
c.SendPacket(new CharacterSpawnPacket(c.Character, location));
@ -143,13 +153,13 @@ namespace PSO2SERVER.Zone
// Objects
foreach (PSOObject obj in Objects)
{
c.SendPacket(0x08, 0x0B, 0x0, obj.GenerateSpawnBlob());
c.SendPacket(new ObjectSpawnPacket(obj));
}
// NPCs
foreach (PSONPC npc in NPCs)
{
c.SendPacket(0x08, 0xC, 0x4, npc.GenerateSpawnBlob());
c.SendPacket(new NPCSpawnPacket(npc));
}
// Spawn for others, Spawn others for me
@ -184,10 +194,11 @@ namespace PSO2SERVER.Zone
foreach (Client other in Clients)
{
PacketWriter writer = new PacketWriter();
writer.WriteStruct(new ObjectHeader((uint)other.User.PlayerId, EntityType.Player));
writer.WriteStruct(new ObjectHeader((uint)c.User.PlayerId, EntityType.Player));
other.SendPacket(0x4, 0x3B, 0x40, writer.ToArray());
//PacketWriter writer = new PacketWriter();
//writer.WriteStruct(new ObjectHeader((uint)other.User.PlayerId, EntityType.Player));
//writer.WriteStruct(new ObjectHeader((uint)c.User.PlayerId, EntityType.Player));
//other.SendPacket(0x4, 0x3B, 0x40, writer.ToArray());
other.SendPacket(new DespawnPlayerPacket(other.User.PlayerId, c.User.PlayerId));
}
if (InstanceName != null && ZoneManager.Instance.playerCounter.ContainsKey(InstanceName))