继续修正
This commit is contained in:
parent
554a46206c
commit
86cbf43914
@ -239,11 +239,12 @@ namespace PSO2SERVER
|
||||
if (!Directory.Exists(packetPath))
|
||||
Directory.CreateDirectory(packetPath);
|
||||
|
||||
var filename = string.Format("{0}/0x{1:X2}-0x{2:X2}-{3}.bin"
|
||||
var filename = string.Format("{0}/0x{1:X2}-0x{2:X2}-{3}-{4}.bin"
|
||||
, packetPath
|
||||
, typeA, typeB
|
||||
//, _packetId++
|
||||
, fromClient ? "C" : "S"
|
||||
, _server.StartTime.ToShortTimeString().Replace('/', '-').Replace(':', '-')
|
||||
);
|
||||
|
||||
using (var stream = File.OpenWrite(filename))
|
||||
@ -269,11 +270,12 @@ namespace PSO2SERVER
|
||||
if (!Directory.Exists(packetPath))
|
||||
Directory.CreateDirectory(packetPath);
|
||||
|
||||
var filename = string.Format("{0}/0x{1:X2}-0x{2:X2}-{3}.bin"
|
||||
var filename = string.Format("{0}/0x{1:X2}-0x{2:X2}-{3}-{4}.bin"
|
||||
, packetPath
|
||||
, typeA, typeB
|
||||
//, _packetId++
|
||||
, "C-unk"
|
||||
, _server.StartTime.ToShortTimeString().Replace('/', '-').Replace(':', '-')
|
||||
);
|
||||
|
||||
using (var stream = File.OpenWrite(filename))
|
||||
|
@ -9,43 +9,179 @@ namespace PSO2SERVER.Models
|
||||
{
|
||||
public class Character
|
||||
{
|
||||
public enum ClassType : byte
|
||||
{
|
||||
Unknown = 0xFF,
|
||||
Hunter = 0,
|
||||
Ranger,
|
||||
Force,
|
||||
Fighter,
|
||||
Gunner,
|
||||
Techer,
|
||||
Braver,
|
||||
Bouncer,
|
||||
Challenger,
|
||||
Summoner,
|
||||
BattleWarrior,
|
||||
Hero,
|
||||
Phantom,
|
||||
Etole,
|
||||
Luster,
|
||||
}
|
||||
|
||||
// 每个枚举成员的值是通过位移操作计算的:
|
||||
|
||||
//Hunter:1 << 0,即 1(0x0001)
|
||||
//Ranger:1 << 1,即 2(0x0002)
|
||||
//Force:1 << 2,即 4(0x0004)
|
||||
//Fighter:1 << 3,即 8(0x0008)
|
||||
//Gunner:1 << 4,即 16(0x0010)
|
||||
//Techer:1 << 5,即 32(0x0020)
|
||||
//Braver:1 << 6,即 64(0x0040)
|
||||
//Bouncer:1 << 7,即 128(0x0080)
|
||||
//Challenger:1 << 8,即 256(0x0100)
|
||||
//Summoner:1 << 9,即 512(0x0200)
|
||||
//BattleWarrior:1 << 10,即 1024(0x0400)
|
||||
//Hero:1 << 11,即 2048(0x0800)
|
||||
//Phantom:1 << 12,即 4096(0x1000)
|
||||
//Etole:1 << 13,即 8192(0x2000)
|
||||
//Luster:1 << 14,即 16384(0x4000)
|
||||
|
||||
[Flags]
|
||||
public enum ClassTypeField : ushort
|
||||
{
|
||||
Unknown = 0xFF,
|
||||
None = 0,
|
||||
Hunter = 1 << 0,
|
||||
Ranger = 1 << 1,
|
||||
Force = 1 << 2,
|
||||
Fighter = 1 << 3,
|
||||
Gunner = 1 << 4,
|
||||
Techer = 1 << 5,
|
||||
Braver = 1 << 6,
|
||||
Bouncer = 1 << 7,
|
||||
Challenger = 1 << 8,
|
||||
Summoner = 1 << 9,
|
||||
BattleWarrior = 1 << 10,
|
||||
Hero = 1 << 11,
|
||||
Phantom = 1 << 12,
|
||||
Etole = 1 << 13,
|
||||
Luster = 1 << 14
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct CharParam
|
||||
{
|
||||
public uint character_id;
|
||||
public uint player_id;
|
||||
public uint unk1;
|
||||
public uint voice_type;
|
||||
public ushort unk2;
|
||||
public short voice_pitch;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct JobEntry
|
||||
{
|
||||
public ushort level;
|
||||
public ushort level2; // Usually the same as the above, what is this used for?
|
||||
public uint exp;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Entries
|
||||
{
|
||||
public JobEntry
|
||||
hunter
|
||||
, ranger
|
||||
, force
|
||||
, fighter
|
||||
, gunner
|
||||
, techer
|
||||
, braver
|
||||
, bouncer
|
||||
, Challenger
|
||||
, Summoner
|
||||
, BattleWarrior
|
||||
, Hero
|
||||
, Phantom
|
||||
, Etole
|
||||
, Luster
|
||||
, unk16
|
||||
, unk17
|
||||
, unk18
|
||||
, unk19
|
||||
, unk20
|
||||
, unk21
|
||||
, unk22
|
||||
, unk23
|
||||
, unk24
|
||||
;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct JobParam
|
||||
{
|
||||
//public fixed byte unknown_0[4];
|
||||
public ClassType mainClass;
|
||||
public ClassType subClass;
|
||||
public fixed byte uknown_6[2];
|
||||
public ClassTypeField enabledClasses;
|
||||
public fixed byte uknown_8[2];
|
||||
//public byte padding0;
|
||||
|
||||
public Entries entries; //TODO: Make this a fixed array
|
||||
|
||||
public fixed ushort unk_maxlevel[15];
|
||||
|
||||
//public ushort unknown_48, unknown_4A;
|
||||
//public uint unknown_4C;
|
||||
//public ushort unknown_50, unknown_52;
|
||||
//public uint unknown_54;
|
||||
//public ushort unknown_58, unknown_5A;
|
||||
//public uint unknown_5C;
|
||||
//public ushort unknown_60, unknown_62;
|
||||
//public uint unknown_64;
|
||||
//public uint unknown_68;
|
||||
//public ushort unknown_6C, unknown_6E;
|
||||
//public fixed int unknown_70[4];
|
||||
}
|
||||
|
||||
public enum RunAnimation : ushort
|
||||
{
|
||||
Walking = 9,
|
||||
Hovering = 11
|
||||
}
|
||||
|
||||
public enum Race : ushort
|
||||
{
|
||||
Unknown = 0xFFFF,
|
||||
Human = 0,
|
||||
Newman,
|
||||
Cast,
|
||||
Dewman
|
||||
Dewman,
|
||||
}
|
||||
|
||||
public enum Gender : ushort
|
||||
{
|
||||
Unknown = 0xFFFF,
|
||||
Male = 0,
|
||||
Female
|
||||
Female,
|
||||
}
|
||||
|
||||
public enum ClassType : byte
|
||||
public struct AccessoryData
|
||||
{
|
||||
Hunter = 0,
|
||||
Fighter,
|
||||
Ranger,
|
||||
Gunner,
|
||||
Force,
|
||||
Techer,
|
||||
Braver,
|
||||
Bouncer,
|
||||
public sbyte Value1;
|
||||
public sbyte Value2;
|
||||
public sbyte Value3;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ClassTypeField : byte
|
||||
public enum SkinColor
|
||||
{
|
||||
Hunter = 1,
|
||||
Fighter = 2,
|
||||
Ranger = 4,
|
||||
Gunner = 8,
|
||||
Force = 16,
|
||||
Techer = 32,
|
||||
Braver = 64,
|
||||
Bouncer = 128
|
||||
RaceDefined,
|
||||
Human,
|
||||
Deuman,
|
||||
Cast
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@ -60,83 +196,117 @@ namespace PSO2SERVER.Models
|
||||
public ushort x, y, z; // Great naming, SEGA
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct JobEntry
|
||||
{
|
||||
public ushort level;
|
||||
public ushort level2; // Usually the same as the above, what is this used for?
|
||||
public uint exp;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Entries
|
||||
{
|
||||
public JobEntry hunter, fighter, ranger, gunner, force, techer, braver, bouncer;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct JobParam
|
||||
{
|
||||
public fixed byte unknown_0[4];
|
||||
public ClassType mainClass;
|
||||
public ClassType subClass;
|
||||
public fixed byte uknown_6[2];
|
||||
public ClassTypeField enabledClasses;
|
||||
public fixed byte uknown_8[2];
|
||||
public byte padding0;
|
||||
|
||||
public Entries entries; //TODO: Make this a fixed array
|
||||
|
||||
public ushort unknown_48, unknown_4A;
|
||||
public uint unknown_4C;
|
||||
public ushort unknown_50, unknown_52;
|
||||
public uint unknown_54;
|
||||
public ushort unknown_58, unknown_5A;
|
||||
public uint unknown_5C;
|
||||
public ushort unknown_60, unknown_62;
|
||||
public uint unknown_64;
|
||||
public uint unknown_68;
|
||||
public ushort unknown_6C, unknown_6E;
|
||||
public fixed int unknown_70[4];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct LooksParam
|
||||
{
|
||||
public fixed byte padding[4];
|
||||
public ushort height;
|
||||
public fixed byte charData[80]; // Figure Data, needs more work
|
||||
public ushort accessoryData1;
|
||||
public ushort accessoryData2;
|
||||
public ushort accessoryData3;
|
||||
public ushort accessoryData4;
|
||||
public HSVColor costumeColor;
|
||||
public HSVColor mainColor;
|
||||
public HSVColor sub1Color;
|
||||
public HSVColor sub2Color;
|
||||
public HSVColor sub3Color;
|
||||
public HSVColor eyeColor;
|
||||
public HSVColor hairColor;
|
||||
public int modelID;
|
||||
public ushort mainParts;
|
||||
public ushort bodyPaint;
|
||||
public ushort emblem;
|
||||
public ushort eyePattern;
|
||||
public ushort eyelashes;
|
||||
public ushort eyebrows;
|
||||
public ushort face;
|
||||
public ushort facePaint1;
|
||||
public ushort hairstyle;
|
||||
public ushort accessory1;
|
||||
public ushort accessory2;
|
||||
public ushort accessory3;
|
||||
public ushort facePaint2;
|
||||
public ushort arms;
|
||||
public ushort legs;
|
||||
public ushort accessory4;
|
||||
public ushort costume;
|
||||
public RunAnimation running_animation;
|
||||
public Race race;
|
||||
public Gender gender;
|
||||
//public fixed byte padding[4];
|
||||
public ushort Muscule;
|
||||
public Figure Body;
|
||||
public Figure Arms;
|
||||
public Figure Legs;
|
||||
public Figure Chest;
|
||||
public Figure FaceShape;
|
||||
public Figure FaceParts;
|
||||
public Figure Eyes;
|
||||
public Figure NoseSize;
|
||||
public Figure NoseHeight;
|
||||
public Figure Mouth;
|
||||
public Figure Ears;
|
||||
public Figure Neck;
|
||||
public Figure Waist;
|
||||
public Figure Body2;
|
||||
public Figure Arms2;
|
||||
public Figure Legs2;
|
||||
public Figure Chest2;
|
||||
public Figure Neck2;
|
||||
public Figure Waist2;
|
||||
public fixed byte Unk1[0x20];
|
||||
public fixed byte Unk2[0x0A];
|
||||
public AccessoryData Acc1Location;
|
||||
public AccessoryData Acc2Location;
|
||||
public AccessoryData Acc3Location;
|
||||
public AccessoryData Acc4Location;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//public ushort height;
|
||||
//public fixed byte charData[80]; // Figure Data, needs more work
|
||||
//public ushort accessoryData1;
|
||||
//public ushort accessoryData2;
|
||||
//public ushort accessoryData3;
|
||||
//public ushort accessoryData4;
|
||||
public HSVColor UnkColor;
|
||||
public HSVColor CostumeColor;
|
||||
public HSVColor MainColor;
|
||||
public HSVColor Sub1Color;
|
||||
public HSVColor Sub2Color;
|
||||
public HSVColor Sub3Color;
|
||||
public HSVColor EyeColor;
|
||||
public HSVColor HairColor;
|
||||
public fixed byte Unk3[0x20];
|
||||
public fixed byte Unk4[0x10];
|
||||
public ushort CostumeId;
|
||||
public ushort BodyPaint1;
|
||||
public ushort StickerId;
|
||||
public ushort RightEyeId;
|
||||
public ushort EyebrowId;
|
||||
public ushort EyelashId;
|
||||
public ushort FaceId1;
|
||||
public ushort FaceId2;
|
||||
public ushort Facemakeup1Id;
|
||||
public ushort HairstyleId;
|
||||
public ushort Acc1Id;
|
||||
public ushort Acc2Id;
|
||||
public ushort Acc3Id;
|
||||
public ushort Facemakeup2Id;
|
||||
public ushort LegId;
|
||||
public ushort ArmId;
|
||||
public ushort Acc4Id;
|
||||
public fixed byte Unk5[0x04];
|
||||
public ushort BodyPaint2;
|
||||
public ushort LeftEyeId;
|
||||
public fixed byte Unk6[0x12];
|
||||
public AccessoryData Acc1Size;
|
||||
public AccessoryData Acc2Size;
|
||||
public AccessoryData Acc3Size;
|
||||
public AccessoryData Acc4Size;
|
||||
public AccessoryData Acc1Rotation;
|
||||
public AccessoryData Acc2Rotation;
|
||||
public AccessoryData Acc3Rotation;
|
||||
public AccessoryData Acc4Rotation;
|
||||
public ushort Unk7;
|
||||
public fixed byte Unk8[0x08];
|
||||
public SkinColor SkinColorType;
|
||||
public sbyte EyebrowThickness;
|
||||
|
||||
//public int modelID;
|
||||
//public ushort mainParts;
|
||||
//public ushort bodyPaint;
|
||||
//public ushort emblem;
|
||||
//public ushort eyePattern;
|
||||
//public ushort eyelashes;
|
||||
//public ushort eyebrows;
|
||||
//public ushort face;
|
||||
//public ushort facePaint1;
|
||||
//public ushort hairstyle;
|
||||
//public ushort accessory1;
|
||||
//public ushort accessory2;
|
||||
//public ushort accessory3;
|
||||
//public ushort facePaint2;
|
||||
//public ushort arms;
|
||||
//public ushort legs;
|
||||
//public ushort accessory4;
|
||||
//public ushort costume;
|
||||
//public Race race;
|
||||
//public Gender gender;
|
||||
}
|
||||
|
||||
// Probably more info than this
|
||||
@ -146,6 +316,24 @@ namespace PSO2SERVER.Models
|
||||
public int CharacterId { get; set; }
|
||||
|
||||
public virtual Player Player { get; set; }
|
||||
public byte[] CharSetBinary
|
||||
{
|
||||
get
|
||||
{
|
||||
PacketWriter w = new PacketWriter();
|
||||
w.WriteStruct(CharSet);
|
||||
return w.ToArray();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
CharSet = Helper.ByteArrayToStructure<CharParam>(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public CharParam CharSet { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public byte[] LooksBinary
|
||||
@ -164,6 +352,8 @@ namespace PSO2SERVER.Models
|
||||
|
||||
}
|
||||
|
||||
public LooksParam Looks { get; set; }
|
||||
|
||||
public byte[] JobsBinary
|
||||
{
|
||||
get
|
||||
@ -180,7 +370,6 @@ namespace PSO2SERVER.Models
|
||||
|
||||
}
|
||||
|
||||
public LooksParam Looks { get; set; }
|
||||
public JobParam Jobs { get; set; }
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using PSO2SERVER.Database;
|
||||
using PSO2SERVER.Packets.PSOPackets;
|
||||
using System.Linq;
|
||||
|
||||
namespace PSO2SERVER.Packets.Handlers
|
||||
@ -13,53 +14,7 @@ namespace PSO2SERVER.Packets.Handlers
|
||||
if (context.User == null)
|
||||
return;
|
||||
|
||||
var writer = new PacketWriter();
|
||||
|
||||
using (var db = new ServerEf())
|
||||
{
|
||||
var chars = db.Characters
|
||||
.Where(w => w.Player.PlayerId == context.User.PlayerId)
|
||||
.OrderBy(o => o.CharacterId) // TODO: Order by last played
|
||||
.Select(s => s);
|
||||
|
||||
writer.Write((uint)chars.Count()); // Number of characters
|
||||
|
||||
for (var i = 0; i < 0x4; i++) // Whatever this is
|
||||
writer.Write((byte)0);
|
||||
|
||||
foreach (var ch in chars)
|
||||
{
|
||||
writer.Write((uint)ch.CharacterId);
|
||||
writer.Write((uint)context.User.PlayerId);
|
||||
|
||||
for (var i = 0; i < 0x10; i++)
|
||||
writer.Write((byte)0);
|
||||
|
||||
writer.WriteFixedLengthUtf16(ch.Name, 16);
|
||||
writer.Write((uint)0);
|
||||
|
||||
writer.WriteStruct(ch.Looks); // Note: Pre-Episode 4 created looks doesn't seem to work anymore
|
||||
writer.WriteStruct(ch.Jobs);
|
||||
|
||||
for (var i = 0; i < 0xFC; i++)
|
||||
writer.Write((byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
// Ninji note: This packet may be followed by extra data,
|
||||
// after a fixed-length array of character data structures.
|
||||
// Needs more investigation at some point.
|
||||
// ---
|
||||
// CK note: Extra data is likely current equipment, playtime, etc.
|
||||
// All of that data is currently unaccounted for at the moment.
|
||||
//忍者注意:这个包后面可能有额外的数据,
|
||||
//在固定长度的字符数据结构数组之后。
|
||||
//需要更多的调查。
|
||||
// ---
|
||||
// CK注:额外的数据可能是当前设备,游戏时间等。
|
||||
//所有这些数据目前都是未知的。
|
||||
|
||||
context.SendPacket(0x11, 0x03, 0, writer.ToArray());
|
||||
context.SendPacket(new CharacterListPacket(context.User.PlayerId));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -5,6 +5,7 @@ using PSO2SERVER.Packets.PSOPackets;
|
||||
using PSO2SERVER.Database;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PSO2SERVER.Packets.Handlers
|
||||
{
|
||||
@ -21,20 +22,22 @@ namespace PSO2SERVER.Packets.Handlers
|
||||
var reader = new PacketReader(data, position, size);
|
||||
//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
|
||||
|
||||
reader.ReadBytes(12); // 12 unknown bytes
|
||||
reader.ReadByte(); // VoiceType
|
||||
reader.ReadBytes(5); // 5 unknown bytes
|
||||
reader.ReadUInt16(); // VoiceData
|
||||
var name = reader.ReadFixedLengthUtf16(16);//玩家名称 宽字符
|
||||
|
||||
reader.BaseStream.Seek(0x4, SeekOrigin.Current); // Padding
|
||||
//reader.BaseStream.Seek(0x04, SeekOrigin.Current); // Padding
|
||||
var looks = reader.ReadStruct<Character.LooksParam>();
|
||||
var jobs = reader.ReadStruct<Character.JobParam>();
|
||||
|
||||
//Logger.WriteInternal("[CHR] {0} 创建了名为 {1} 的新角色.", context.User.Username, name);
|
||||
var newCharacter = new Character
|
||||
{
|
||||
CharSet = setting,
|
||||
Name = name,
|
||||
Jobs = jobs,
|
||||
Looks = looks,
|
||||
@ -68,10 +71,11 @@ 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());
|
||||
//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
|
||||
context.SendPacket(new NoPayloadPacket(0x11, 0x3E));
|
||||
|
@ -33,6 +33,7 @@ namespace PSO2SERVER.Packets.Handlers
|
||||
db.ChangeTracker.DetectChanges();
|
||||
}
|
||||
|
||||
// 将客户端发送至默认大厅
|
||||
Map lobbyMap = ZoneManager.Instance.MapFromInstance("lobby", "lobby");
|
||||
lobbyMap.SpawnClient(context, lobbyMap.GetDefaultLocation(), "lobby");
|
||||
|
||||
@ -41,7 +42,7 @@ namespace PSO2SERVER.Packets.Handlers
|
||||
|
||||
//context.SendPacket(File.ReadAllBytes("testbed/237.23-7.210.189.208.30.bin"));
|
||||
|
||||
// Give a blank palette
|
||||
// 先给一个空的 Palette
|
||||
context.SendPacket(new PalettePacket());
|
||||
|
||||
// memset packet - Enables menus
|
||||
|
@ -8,29 +8,22 @@ namespace PSO2SERVER.Packets.PSOPackets
|
||||
{
|
||||
public class UnkPacket : Packet
|
||||
{
|
||||
private readonly byte _subtype;
|
||||
private readonly byte _type;
|
||||
|
||||
public UnkPacket()
|
||||
{
|
||||
_type = 0x00;
|
||||
_subtype = 0x00;
|
||||
}
|
||||
|
||||
#region implemented abstract members of Packet
|
||||
|
||||
public override byte[] Build()
|
||||
{
|
||||
return new byte[0];
|
||||
var pkt = new PacketWriter();
|
||||
return pkt.ToArray();
|
||||
}
|
||||
|
||||
public override PacketHeader GetHeader()
|
||||
{
|
||||
return new PacketHeader
|
||||
{
|
||||
Type = _type,
|
||||
Subtype = _subtype
|
||||
};
|
||||
return new PacketHeader(0x00, 0x00, PacketFlags.None);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -25,7 +25,7 @@ namespace PSO2SERVER.Packets.PSOPackets
|
||||
|
||||
public override PacketHeader GetHeader()
|
||||
{
|
||||
return new PacketHeader(0x0B, 0x18, 0x04);
|
||||
return new PacketHeader(0x0B, 0x18, PacketFlags.PACKED);
|
||||
}
|
||||
|
||||
// Hoo boy, this is 468 bytes!
|
||||
|
@ -0,0 +1,80 @@
|
||||
using PSO2SERVER.Database;
|
||||
using PSO2SERVER.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting.Contexts;
|
||||
using System.Text;
|
||||
|
||||
namespace PSO2SERVER.Packets.PSOPackets
|
||||
{
|
||||
public class CharacterListPacket : Packet
|
||||
{
|
||||
|
||||
// Ninji note: This packet may be followed by extra data,
|
||||
// after a fixed-length array of character data structures.
|
||||
// Needs more investigation at some point.
|
||||
// ---
|
||||
// CK note: Extra data is likely current equipment, playtime, etc.
|
||||
// All of that data is currently unaccounted for at the moment.
|
||||
//忍者注意:这个包后面可能有额外的数据,
|
||||
//在固定长度的字符数据结构数组之后。
|
||||
//需要更多的调查。
|
||||
// ---
|
||||
// CK注:额外的数据可能是当前设备,游戏时间等。
|
||||
//所有这些数据目前都是未知的。
|
||||
|
||||
private int _PlayerId;
|
||||
public CharacterListPacket(int PlayerId)
|
||||
{
|
||||
_PlayerId = PlayerId;
|
||||
}
|
||||
|
||||
#region implemented abstract members of Packet
|
||||
|
||||
public override byte[] Build()
|
||||
{
|
||||
var writer = new PacketWriter();
|
||||
|
||||
using (var db = new ServerEf())
|
||||
{
|
||||
var chars = db.Characters
|
||||
.Where(w => w.Player.PlayerId == _PlayerId)
|
||||
.OrderBy(o => o.CharacterId) // TODO: Order by last played
|
||||
.Select(s => s);
|
||||
|
||||
writer.Write((uint)chars.Count()); // Number of characters
|
||||
|
||||
for (var i = 0; i < 0x4; i++) // Whatever this is
|
||||
writer.Write((byte)0);
|
||||
|
||||
foreach (var ch in chars)
|
||||
{
|
||||
writer.Write((uint)ch.CharacterId);
|
||||
writer.Write((uint)_PlayerId);
|
||||
|
||||
for (var i = 0; i < 0x10; i++)
|
||||
writer.Write((byte)0);
|
||||
|
||||
writer.WriteFixedLengthUtf16(ch.Name, 16);
|
||||
writer.Write((uint)0);
|
||||
|
||||
writer.WriteStruct(ch.Looks); // Note: 第4集之前创造的外观似乎不再有效了
|
||||
writer.WriteStruct(ch.Jobs);
|
||||
|
||||
for (var i = 0; i < 0xFC; i++)
|
||||
writer.Write((byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
return writer.ToArray();
|
||||
}
|
||||
|
||||
public override PacketHeader GetHeader()
|
||||
{
|
||||
return new PacketHeader(0x11, 0x03, PacketFlags.None);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
using Mysqlx;
|
||||
using PSO2SERVER.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting.Contexts;
|
||||
using System.Text;
|
||||
|
||||
namespace PSO2SERVER.Packets.PSOPackets
|
||||
{
|
||||
public class CharacterCreateResponsePacket : Packet
|
||||
{
|
||||
public enum CharacterCreationStatus
|
||||
{
|
||||
/// 角色创建成功.
|
||||
Success,
|
||||
/// 显示数据空白错误信息.
|
||||
EmptyError,
|
||||
/// 角色数量上限错误.
|
||||
LimitReached,
|
||||
/// AC不足无法创建角色.
|
||||
NoAC,
|
||||
/// 常规系统报错.
|
||||
SystemError,
|
||||
}
|
||||
|
||||
private CharacterCreationStatus status;
|
||||
private uint userid;
|
||||
|
||||
public CharacterCreateResponsePacket(CharacterCreationStatus status, uint userid)
|
||||
{
|
||||
this.status = status;
|
||||
this.userid = userid;
|
||||
}
|
||||
|
||||
#region implemented abstract members of Packet
|
||||
|
||||
public override byte[] Build()
|
||||
{
|
||||
var pkt = new PacketWriter();
|
||||
pkt.Write((int)status);
|
||||
pkt.Write(userid);
|
||||
return pkt.ToArray();
|
||||
}
|
||||
|
||||
public override PacketHeader GetHeader()
|
||||
{
|
||||
return new PacketHeader(0x11, 0x07, PacketFlags.None);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -203,6 +203,8 @@
|
||||
<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\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" />
|
||||
<Compile Include="Packets\PSOPackets\00-00-UnkPacket.cs" />
|
||||
<Compile Include="Packets\PSOPackets\03-ServerPacket\03-2B-UnlockControlsPacket.cs" />
|
||||
|
0
数据对比/角色/3-魔人类-法师.bin
Normal file
0
数据对比/角色/3-魔人类-法师.bin
Normal file
BIN
数据对比/角色/charset-1-机器人-猎人.bin
Normal file
BIN
数据对比/角色/charset-1-机器人-猎人.bin
Normal file
Binary file not shown.
BIN
数据对比/角色/charset-2-d-猎人.bin
Normal file
BIN
数据对比/角色/charset-2-d-猎人.bin
Normal file
Binary file not shown.
BIN
数据对比/角色/job-1-人类-猎人.bin
Normal file
BIN
数据对比/角色/job-1-人类-猎人.bin
Normal file
Binary file not shown.
BIN
数据对比/角色/job-1-机器人-猎人.bin
Normal file
BIN
数据对比/角色/job-1-机器人-猎人.bin
Normal file
Binary file not shown.
BIN
数据对比/角色/job-3-魔人类-法师.bin
Normal file
BIN
数据对比/角色/job-3-魔人类-法师.bin
Normal file
Binary file not shown.
BIN
数据对比/角色/job-4-人类-武士.bin
Normal file
BIN
数据对比/角色/job-4-人类-武士.bin
Normal file
Binary file not shown.
BIN
数据对比/角色/job-5-人类-武士.bin
Normal file
BIN
数据对比/角色/job-5-人类-武士.bin
Normal file
Binary file not shown.
BIN
数据对比/角色/look-1-人类-猎人.bin
Normal file
BIN
数据对比/角色/look-1-人类-猎人.bin
Normal file
Binary file not shown.
BIN
数据对比/角色/look-5-人类-武士.bin
Normal file
BIN
数据对比/角色/look-5-人类-武士.bin
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user