未完成角色生成

This commit is contained in:
Sancaros 2024-12-02 20:43:28 +08:00
parent 235a4ee5fc
commit 75380c1a81
13 changed files with 148 additions and 120 deletions

View File

@ -4,8 +4,8 @@ using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.IO;
using MySql.Data.EntityFramework;
using PSO2SERVER.Models;
using static PSO2SERVER.Models.Character;
using PSO2SERVER.Protocol;
using static PSO2SERVER.Models.CharacterStruct;
namespace PSO2SERVER.Database
{
@ -99,6 +99,64 @@ namespace PSO2SERVER.Database
public float PosZ { get; set; }
}
public class Character
{
// Probably more info than this
[Key, Column(Order = 1)]
public int CharacterID { get; set; }
[Key, Column(Order = 2)]
public int AccountID { get; set; }
public int Unk1 { get; set; }
public int VoiceType { get; set; }
public short Unk2 { get; set; }
public short VoicePitch { get; set; }
public string Name { get; set; }
public LooksParam Looks { get; set; }
public byte[] LooksBinary
{
get
{
PacketWriter w = new PacketWriter();
w.WriteStruct(Looks);
return w.ToArray();
}
set
{
Looks = Helper.ByteArrayToStructure<LooksParam>(value);
}
}
public int Unk3 { get; set; }
public JobParam Jobs { get; set; }
public byte[] JobsBinary
{
get
{
PacketWriter w = new PacketWriter();
w.WriteStruct(Jobs);
return w.ToArray();
}
set
{
Jobs = Helper.ByteArrayToStructure<JobParam>(value);
}
}
public string Unk4 { get; set; }
public virtual Account Account { get; set; }
public byte[] fulldata { get; set; }
}
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class ServerEf : DbContext
{

View File

@ -7,7 +7,7 @@ using PSO2SERVER.Database;
namespace PSO2SERVER.Models
{
public class Character
public class CharacterStruct
{
public enum ShortLanguage : byte
{
@ -263,59 +263,6 @@ namespace PSO2SERVER.Models
public Entries entries; //TODO: Make this a fixed array 24 * 8
public fixed ushort unk_maxlevel[15];//30
}
// Probably more info than this
[Key, Column(Order = 1)]
public int CharacterID { get; set; }
[Key, Column(Order = 2)]
public int AccountID { get; set; }
public uint Unk1 { get; set; }
public uint VoiceType { get; set; }
public ushort Unk2 { get; set; }
public short VoicePitch { get; set; }
public string Name { get; set; }
public byte[] LooksBinary
{
get
{
PacketWriter w = new PacketWriter();
w.WriteStruct(Looks);
return w.ToArray();
}
set
{
Looks = Helper.ByteArrayToStructure<LooksParam>(value);
}
}
public LooksParam Looks { get; set; }
public uint Unk3 { get; set; }
public byte[] JobsBinary
{
get
{
PacketWriter w = new PacketWriter();
w.WriteStruct(Jobs);
return w.ToArray();
}
set
{
Jobs = Helper.ByteArrayToStructure<JobParam>(value);
}
}
public JobParam Jobs { get; set; }
public string NickName { get; set; }
public virtual Account Account { get; set; }
}

View File

@ -1,9 +1,8 @@
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using static PSO2SERVER.Models.Character;
using static PSO2SERVER.Models.CharacterStruct;
namespace PSO2SERVER.Models
{

View File

@ -1,4 +1,5 @@
using PSO2SERVER.Models;
using PSO2SERVER.Database;
using PSO2SERVER.Models;
using PSO2SERVER.Protocol.Packets;
using System;
using System.Collections.Generic;
@ -34,7 +35,7 @@ namespace PSO2SERVER.Party
{
if (members.Count < 1)
{
c.SendPacket(new PartyInitPacket(new Models.Character[1] { c.Character }));
c.SendPacket(new PartyInitPacket(new Character[1] { c.Character }));
}
else
{

View File

@ -93,8 +93,8 @@ namespace PSO2SERVER.Protocol.Handlers
ReadFromStream(reader);
var info = string.Format("[<--] 接收到的数据 (hex): {0}字节", data.Length);
Logger.WriteHex(info, data);
//var info = string.Format("[<--] 接收到的数据 (hex): {0}字节", data.Length);
//Logger.WriteHex(info, data);
//Logger.Write("用户名 {0} 密码 {1} - {2}", Username, Password, BCrypt.Net.BCrypt.HashPassword(Password));

View File

@ -4,7 +4,9 @@ using PSO2SERVER.Models;
using PSO2SERVER.Protocol.Packets;
using PSO2SERVER.Database;
using System.Linq;
using static PSO2SERVER.Models.Character;
using static PSO2SERVER.Models.CharacterStruct;
using System.Security.Cryptography.Pkcs;
using System.Runtime.InteropServices;
namespace PSO2SERVER.Protocol.Handlers
{
@ -12,19 +14,20 @@ namespace PSO2SERVER.Protocol.Handlers
public class CharacterCreate : PacketHandler
{
#region implemented abstract members of PacketHandler
public struct CharacterCreatePacket
{
public uint CharacterID;
public uint AccountID;
public uint Unk1;
public uint VoiceType;
public ushort Unk2;
public int CharacterID;
public int AccountID;
public int Unk1;
public int VoiceType;
public short Unk2;
public short VoicePitch;
public string Name;
public uint Unk3;
public int Unk3;
public LooksParam Looks;
public JobParam Jobs;
public string NickName;
public string unk4; // 148 字节的字节数组
}
private CharacterCreatePacket packet = new CharacterCreatePacket();
@ -38,18 +41,17 @@ namespace PSO2SERVER.Protocol.Handlers
var info = string.Format("[<--] 接收到的数据 (hex): {0} 字节", data.Length);
Logger.WriteHex(info, data);
packet.CharacterID = reader.ReadUInt32();
packet.AccountID = reader.ReadUInt32();
packet.Unk1 = reader.ReadUInt32();//Unk1
packet.VoiceType = reader.ReadUInt32(); // VoiceType
packet.Unk2 = reader.ReadUInt16(); // 5 unknown bytes
packet.CharacterID = reader.ReadInt32();
packet.AccountID = reader.ReadInt32();
packet.Unk1 = reader.ReadInt32();//Unk1
packet.VoiceType = reader.ReadInt32(); // VoiceType
packet.Unk2 = reader.ReadInt16(); // 5 unknown bytes
packet.VoicePitch = reader.ReadInt16(); // VoiceData
packet.Name = reader.ReadFixedLengthUtf16(16);
packet.Unk3 = reader.ReadUInt32();
packet.Looks = reader.ReadStruct<Character.LooksParam>();
packet.Jobs = reader.ReadStruct<Character.JobParam>();
packet.NickName = reader.ReadFixedLengthUtf16(16);
reader.BaseStream.Seek(0x56, SeekOrigin.Current); // Padding
packet.Unk3 = reader.ReadInt32();
packet.Looks = reader.ReadStruct<LooksParam>();
packet.Jobs = reader.ReadStruct<JobParam>();
packet.unk4 = reader.ReadFixedLengthUtf16(76);
var newCharacter = new Character
{
@ -63,8 +65,8 @@ namespace PSO2SERVER.Protocol.Handlers
Unk3 = packet.Unk3,
Jobs = packet.Jobs,
Looks = packet.Looks,
NickName = packet.NickName,
Account = context._account
Account = context._account,
fulldata = data
};
// Add to database

View File

@ -7,6 +7,7 @@ using PSO2SERVER.Protocol.Packets;
using PSO2SERVER.Object;
using PSO2SERVER.Database;
using PSO2SERVER.Zone;
using static PSO2SERVER.Models.CharacterStruct;
namespace PSO2SERVER.Protocol.Handlers
{
@ -29,8 +30,8 @@ namespace PSO2SERVER.Protocol.Handlers
Logger.WriteHex(info, data);
reader.BaseStream.Seek(0x38, SeekOrigin.Begin);
context.Character.Looks = reader.ReadStruct<Character.LooksParam>();
context.Character.Jobs = reader.ReadStruct<Character.JobParam>();
context.Character.Looks = reader.ReadStruct<LooksParam>();
context.Character.Jobs = reader.ReadStruct<JobParam>();
using(var db = new ServerEf())
db.ChangeTracker.DetectChanges();

View File

@ -1,5 +1,7 @@
using PSO2SERVER.Models;
using PSO2SERVER.Database;
using PSO2SERVER.Models;
using System.Runtime.InteropServices;
using static PSO2SERVER.Models.CharacterStruct;
using static PSO2SERVER.Protocol.Packets.CharacterSpawnPacket;
namespace PSO2SERVER.Protocol.Packets
@ -47,7 +49,7 @@ namespace PSO2SERVER.Protocol.Packets
// Spawn position
writer.WritePosition(Position);
writer.Write((ushort)0); // padding?
writer.Write((ushort)0);
writer.WriteFixedLengthASCII("Character", 32);
writer.Write((ushort)1); // 0x44
writer.Write((ushort)0); // 0x46
@ -69,23 +71,33 @@ namespace PSO2SERVER.Protocol.Packets
//writer.write((byte)0x01);
// Character data.
writer.Write((uint)_character.AccountID); // player ID copy
writer.Write((uint)_character.CharacterID); // "char array ugggghhhhh" according to PolarisLegacy
writer.Write(_character.Unk1);//4
writer.Write(_character.VoiceType);//4
writer.Write(_character.Unk2);//2
writer.Write((uint)_character.AccountID);
writer.Write((uint)_character.CharacterID);
writer.Write((uint)_character.Unk1);//4
writer.Write((uint)_character.VoiceType);//4
writer.Write((ushort)_character.Unk2);//2
writer.Write(_character.VoicePitch);//2
writer.WriteFixedLengthUtf16(_character.Name, 16);
writer.Write((uint)0); // 0x90
writer.Write((uint)_character.Unk3); // 0x90
writer.WriteStruct(_character.Looks);
writer.WriteStruct(_character.Jobs);
writer.WriteFixedLengthUtf16(_character.Account.Nickname, 16); // Nickname, maybe not 16 chars?
JobParam jobParam = _character.Jobs;
jobParam.mainClass = ClassType.Luster;
jobParam.subClass = ClassType.Phantom;
jobParam.entries.Luster.level = 100;
writer.WriteStruct(jobParam);
writer.WriteBytes(0, 148);
writer.Write((uint)0); // 0x204
writer.Write(IsGM); // gmflag?
for (var i = 0; i < 60; i++)
//writer.WriteFixedLengthUtf16(_character.Account.Nickname, 16);
for (var i = 0; i < 0x60; i++)
writer.Write((byte)0);
//for (var i = 0; i < 0x40; i++)
// writer.Write((byte)0);
return writer.ToArray();
}

View File

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSO2SERVER.Database;
using PSO2SERVER.Models;
using static PSO2SERVER.Models.Character;
using static PSO2SERVER.Models.CharacterStruct;
using static PSO2SERVER.Party.Party;
namespace PSO2SERVER.Protocol.Packets

View File

@ -6,6 +6,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Contexts;
using System.Text;
using static PSO2SERVER.Models.CharacterStruct;
namespace PSO2SERVER.Protocol.Packets
{
@ -47,30 +48,38 @@ namespace PSO2SERVER.Protocol.Packets
writer.Write((uint)chars.Count()); // 写入玩家数量
writer.Write((uint)AccountId);
writer.Write((uint)0);
foreach (var ch in chars)
{
writer.Write((uint)ch.AccountID);//4
writer.Write((uint)0);
writer.Write((uint)ch.CharacterID);//4
writer.Write(ch.Unk1);//4
writer.Write(ch.VoiceType);//4
writer.Write(ch.Unk2);//2
writer.Write((uint)ch.AccountID);//4
writer.Write((uint)ch.Unk1);//4
writer.Write((uint)ch.VoiceType);//4
writer.Write((ushort)ch.Unk2);//2
writer.Write(ch.VoicePitch);//2
writer.Write((uint)0);//4
writer.WriteFixedLengthUtf16(ch.Name, 16);
//Logger.WriteInternal("[CHR] 新增名为 {0} 的新角色.", ch.Name);
writer.Write((uint)0); // 修改这个值 可能会触发角色不可用或变为联动角色
writer.Write((uint)ch.Unk3);
writer.WriteStruct(ch.Looks);
writer.WriteStruct(ch.Jobs);
writer.WriteFixedLengthUtf16(ch.NickName, 16);
JobParam jobParam = ch.Jobs;
jobParam.mainClass = ClassType.Luster;
jobParam.subClass = ClassType.Phantom;
jobParam.entries.Luster.level = 100;
writer.WriteStruct(jobParam);
writer.WriteBytes(0, 148);
for (var i = 0; i < 116; i++)
writer.Write((byte)0);
}
//for (var i = 0; i < 640; i++)
// writer.Write((byte)1);
//for (var i = 0; i < 30; i++)
// writer.Write((uint)1);
//writer.Write(new byte[240]);
//writer.Write(new byte[240]);
}
return writer.ToArray();

View File

@ -1,4 +1,5 @@
using PSO2SERVER.Models;
using PSO2SERVER.Database;
using PSO2SERVER.Models;
namespace PSO2SERVER.Protocol.Packets
{

View File

@ -403,7 +403,7 @@
<Compile Include="Protocol\Handlers\PacketHandler.cs" />
<Compile Include="Protocol\Handlers\11-ClientHandler\11-0B-KeyExchange.cs" />
<Compile Include="Protocol\Handlers\11-ClientHandler\11-00-SegaIDLogin.cs" />
<Compile Include="Models\Character.cs" />
<Compile Include="Models\CharacterStruct.cs" />
<Compile Include="Protocol\Handlers\11-ClientHandler\11-54-CreateCharacterTwo.cs" />
<Compile Include="Protocol\PacketWriter.cs" />
<Compile Include="Models\FixedPackets.cs" />

View File

@ -9,6 +9,7 @@ using NUnit.Framework;
using PSO2SERVER.Models;
using PSO2SERVER.Protocol;
using PSO2SERVER.Protocol.Handlers;
using static PSO2SERVER.Models.CharacterStruct;
namespace ServerTest
{
@ -41,12 +42,12 @@ namespace ServerTest
[TestFixture]
public class UnsafeTests
{
private readonly Character.JobParam _jp = new Character.JobParam();
private readonly JobParam _jp = new JobParam();
[Test]
public void CheckJobParam()
{
var size = Marshal.SizeOf(typeof(Character.JobParam));
var size = Marshal.SizeOf(typeof(JobParam));
Assert.IsNotNull(_jp);
var jpArr = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
@ -77,8 +78,8 @@ namespace ServerTest
[Test]
public void TestStructureWrite()
{
var structureSize = Marshal.SizeOf(typeof(Character.JobParam));
var jp = new Character.JobParam();
var structureSize = Marshal.SizeOf(typeof(JobParam));
var jp = new JobParam();
jp.entries.hunter.level = 7;
_writer.WriteStruct(jp);
var structArray = _writer.ToArray();