暂存大量修改
This commit is contained in:
parent
eadf136dcb
commit
16bb43b1e9
@ -8,6 +8,9 @@ namespace PSO2SERVER
|
||||
{
|
||||
private byte[] data;
|
||||
|
||||
// 获取字符串的长度
|
||||
public int Length => data.Length;
|
||||
|
||||
// 从字符串初始化
|
||||
public AsciiString(string value)
|
||||
{
|
||||
@ -23,7 +26,7 @@ namespace PSO2SERVER
|
||||
// 从字节数组初始化
|
||||
public AsciiString(byte[] bytes)
|
||||
{
|
||||
data = bytes;
|
||||
data = bytes ?? throw new ArgumentNullException(nameof(bytes), "字节数组不能为 null");
|
||||
}
|
||||
|
||||
// 获取 ASCII 字符串,去除尾部的 null 字节
|
||||
@ -67,7 +70,59 @@ namespace PSO2SERVER
|
||||
return new AsciiString(value);
|
||||
}
|
||||
|
||||
// 获取字符串的长度
|
||||
public int Length => data.Length;
|
||||
// 写入固定长度 ASCII 字符串,超出部分截断,空余部分用零填充
|
||||
public void WriteFixedLengthASCII(string str, int charCount)
|
||||
{
|
||||
// 确保字符串长度不超过规定的 charCount
|
||||
var writeAmount = Math.Min(str.Length, charCount);
|
||||
var paddingAmount = charCount - writeAmount;
|
||||
|
||||
byte[] byteArray = Encoding.ASCII.GetBytes(str.Substring(0, writeAmount));
|
||||
|
||||
// 可能存在的填充
|
||||
byte[] resultArray = new byte[charCount];
|
||||
Array.Copy(byteArray, resultArray, byteArray.Length);
|
||||
|
||||
// 用零填充剩余部分
|
||||
if (paddingAmount > 0)
|
||||
{
|
||||
for (int i = byteArray.Length; i < charCount; i++)
|
||||
{
|
||||
resultArray[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
data = resultArray;
|
||||
}
|
||||
|
||||
// 写入固定长度的 UTF-16 字符串,超出部分截断,空余部分用零填充
|
||||
public void WriteFixedLengthUtf16(string str, int charCount)
|
||||
{
|
||||
var writeAmount = Math.Min(str.Length, charCount);
|
||||
var paddingAmount = charCount - writeAmount;
|
||||
|
||||
byte[] byteArray = Encoding.Unicode.GetBytes(str.Substring(0, writeAmount));
|
||||
|
||||
// 可能存在的填充
|
||||
byte[] resultArray = new byte[charCount * 2]; // UTF-16 每个字符占 2 个字节
|
||||
Array.Copy(byteArray, resultArray, byteArray.Length);
|
||||
|
||||
// 用零填充剩余部分
|
||||
if (paddingAmount > 0)
|
||||
{
|
||||
for (int i = byteArray.Length; i < charCount * 2; i++)
|
||||
{
|
||||
resultArray[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
data = resultArray;
|
||||
}
|
||||
|
||||
// 重写 ToString 方法,返回字符串表示
|
||||
public string GetStringRepresentation()
|
||||
{
|
||||
return Encoding.ASCII.GetString(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -712,9 +712,8 @@ namespace PSO2SERVER
|
||||
};
|
||||
|
||||
|
||||
var fakePacket = new CharacterSpawnPacket(fakeChar, new PSOLocation(0f, 1f, 0f, 0f, x, y, z))
|
||||
var fakePacket = new CharacterSpawnPacket(fakeChar, new PSOLocation(0f, 1f, 0f, 0f, x, y, z), false)
|
||||
{
|
||||
IsItMe = false
|
||||
};
|
||||
client.SendPacket(fakePacket);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using PSO2SERVER.Protocol.Packets;
|
||||
|
||||
namespace PSO2SERVER
|
||||
@ -226,5 +226,32 @@ namespace PSO2SERVER
|
||||
Writer.WriteLine("\t\t" + DateTime.Now);
|
||||
Writer.WriteLine("--------------------------------------------------");
|
||||
}
|
||||
|
||||
// 方法:打印结构体的二进制数据
|
||||
public static void WriteStructBinary(string text, object obj)
|
||||
{
|
||||
var byteArray = StructToByteArray(obj);
|
||||
WriteHex(text, byteArray);
|
||||
}
|
||||
|
||||
// 将结构体转换为字节数组
|
||||
public static byte[] StructToByteArray(object obj)
|
||||
{
|
||||
int size = Marshal.SizeOf(obj);
|
||||
byte[] byteArray = new byte[size];
|
||||
IntPtr ptr = Marshal.AllocHGlobal(size);
|
||||
|
||||
try
|
||||
{
|
||||
Marshal.StructureToPtr(obj, ptr, false);
|
||||
Marshal.Copy(ptr, byteArray, 0, size);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
|
||||
return byteArray;
|
||||
}
|
||||
}
|
||||
}
|
@ -68,8 +68,6 @@ namespace PSO2SERVER.Models
|
||||
[Flags]
|
||||
public enum ClassTypeField : ushort
|
||||
{
|
||||
Unknown = 0xFF,
|
||||
None = 0,
|
||||
Hunter = 1 << 0,
|
||||
Ranger = 1 << 1,
|
||||
Force = 1 << 2,
|
||||
@ -129,13 +127,13 @@ namespace PSO2SERVER.Models
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct JobParam
|
||||
{
|
||||
public ClassType mainClass;
|
||||
public ClassType subClass;
|
||||
public ushort unk2;
|
||||
public ClassTypeField enabledClasses;
|
||||
public ushort unk3;
|
||||
public Entries entries; //TODO: Make this a fixed array
|
||||
public fixed ushort unk_maxlevel[15];
|
||||
public ClassType mainClass;//1
|
||||
public ClassType subClass;//1
|
||||
public ushort unk2;//2
|
||||
public ClassTypeField enabledClasses;//2
|
||||
public ushort unk3;//2
|
||||
public Entries entries; //TODO: Make this a fixed array 24 * 8
|
||||
public fixed ushort unk_maxlevel[15];//30
|
||||
}
|
||||
|
||||
public enum RunAnimation : ushort
|
||||
|
@ -7,7 +7,7 @@ using static PSO2SERVER.Models.Character;
|
||||
|
||||
namespace PSO2SERVER.Models
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct ShortItemId
|
||||
{
|
||||
byte ItemType;
|
||||
@ -15,7 +15,7 @@ namespace PSO2SERVER.Models
|
||||
ushort Subid;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct ItemId
|
||||
{
|
||||
ushort ItemType;
|
||||
@ -51,12 +51,12 @@ namespace PSO2SERVER.Models
|
||||
//public PSO2ItemNone None;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct PSO2ItemNone
|
||||
{
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct PSO2ItemWeapon
|
||||
{
|
||||
byte flags;
|
||||
@ -75,7 +75,7 @@ namespace PSO2SERVER.Models
|
||||
uint unknown6;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct PSO2ItemClothing
|
||||
{
|
||||
ushort flags;
|
||||
@ -85,7 +85,7 @@ namespace PSO2SERVER.Models
|
||||
ushort Unk3;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct PSO2ItemConsumable
|
||||
{
|
||||
ushort flags;
|
||||
@ -93,7 +93,7 @@ namespace PSO2SERVER.Models
|
||||
ushort amount;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct PSO2ItemCamo
|
||||
{
|
||||
byte unk1;
|
||||
@ -103,7 +103,7 @@ namespace PSO2SERVER.Models
|
||||
byte unk5;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct PSO2ItemUnit
|
||||
{
|
||||
byte flags;
|
||||
|
@ -117,7 +117,7 @@ namespace PSO2SERVER.Models
|
||||
NotSet = 0x0000000800000000,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public unsafe struct QuestDefiniton
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32 - 8)]
|
||||
|
@ -35,7 +35,7 @@ namespace PSO2SERVER.Protocol.Handlers
|
||||
//var setPlayerId = new PacketWriter();
|
||||
//setPlayerId.WriteAccountHeader((uint)context._account.AccountId);
|
||||
//context.SendPacket(0x06, 0x00, 0, setPlayerId.ToArray());
|
||||
context.SendPacket(new SetPlayerIDPacket(context._account.AccountId));
|
||||
context.SendPacket(new SetAccountIDPacket(context._account.AccountId));
|
||||
|
||||
// Spawn Account
|
||||
new CharacterSpawn().HandlePacket(context, flags, data, position, size);
|
||||
|
@ -112,11 +112,18 @@ namespace PSO2SERVER.Protocol.Handlers
|
||||
if (!users.Any())
|
||||
{
|
||||
// Check if there is an empty field
|
||||
if (string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(Password))
|
||||
if (string.IsNullOrWhiteSpace(Username))
|
||||
{
|
||||
error = "用户名或密码为空.";
|
||||
error = "Username Empty.";
|
||||
user = null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Password))
|
||||
{
|
||||
error = "Password Empty #1.";
|
||||
user = null;
|
||||
}
|
||||
|
||||
// Check for special characters
|
||||
else if (!Regex.IsMatch(Username, "^[a-zA-Z0-9 ]*$", RegexOptions.IgnoreCase))
|
||||
{
|
||||
@ -145,20 +152,21 @@ namespace PSO2SERVER.Protocol.Handlers
|
||||
{
|
||||
user = users.First();
|
||||
|
||||
if (Password != user.Password)
|
||||
{
|
||||
if (Password == "")
|
||||
{
|
||||
error = "密码为空.";
|
||||
user = null;
|
||||
}
|
||||
else
|
||||
if (!BCrypt.Net.BCrypt.Verify(Password, user.Password))
|
||||
{
|
||||
error = "密码错误.";
|
||||
user = null;
|
||||
}
|
||||
}
|
||||
//TODO 方便GM测试
|
||||
//if (Password != user.Password)
|
||||
//{
|
||||
// if (Password == "")
|
||||
// {
|
||||
// error = "Password Empty #2.";
|
||||
// user = null;
|
||||
// }
|
||||
// else
|
||||
// if (!BCrypt.Net.BCrypt.Verify(Password, user.Password))
|
||||
// {
|
||||
// error = "Wrong Password.";
|
||||
// user = null;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
context.SendPacket(new LoginDataPacket("Server AuthList 1", error, (user == null) ? (uint)0 : (uint)user.AccountId));
|
||||
|
@ -35,6 +35,8 @@ namespace PSO2SERVER.Protocol.Handlers
|
||||
var looks = reader.ReadStruct<Character.LooksParam>();
|
||||
var jobs = reader.ReadStruct<Character.JobParam>();
|
||||
|
||||
Logger.WriteStructBinary(info, jobs);
|
||||
|
||||
Logger.WriteInternal("[CHR] {0} 创建了名为 {1} 的新角色.", context._account.Username, name);
|
||||
var newCharacter = new Character
|
||||
{
|
||||
|
@ -8,14 +8,20 @@ namespace PSO2SERVER.Protocol.Handlers
|
||||
[PacketHandlerAttr(0x11, 0xBC)]
|
||||
class CharacterShipTransferCanceldRequest : PacketHandler
|
||||
{
|
||||
public uint player_id { get; set; }
|
||||
public struct CharacterShipTransferCanceldRequestPacket
|
||||
{
|
||||
public uint player_id { get; set; }
|
||||
}
|
||||
|
||||
CharacterShipTransferCanceldRequestPacket pkt = new CharacterShipTransferCanceldRequestPacket();
|
||||
|
||||
public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size)
|
||||
{
|
||||
var info = string.Format("[<--] 接收到的数据 (hex): {0} 字节", data.Length);
|
||||
Logger.WriteHex(info, data);
|
||||
|
||||
var reader = new PacketReader(data, position, size);
|
||||
player_id = reader.ReadUInt32();
|
||||
pkt = reader.ReadStruct<CharacterShipTransferCanceldRequestPacket>();
|
||||
|
||||
context.SendPacket(new CharacterShipTransferCancelPacket(MoveStatus.Success));// TODO 需要补充完整
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using PSO2SERVER.Models;
|
||||
using PSO2SERVER.Protocol.Packets;
|
||||
using static PSO2SERVER.Protocol.Handlers.CharacterNewNameRequest;
|
||||
|
||||
namespace PSO2SERVER.Protocol.Handlers
|
||||
{
|
||||
[PacketHandlerAttr(0x11, 0xDC)]
|
||||
class CharacterSurvey : PacketHandler
|
||||
{
|
||||
public struct CharacterSurveyPacket
|
||||
{
|
||||
public uint choice { get; set; }
|
||||
}
|
||||
|
||||
public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size)
|
||||
{
|
||||
var info = string.Format("[<--] 接收到的数据 (hex): {0} 字节", data.Length);
|
||||
Logger.WriteHex(info, data);
|
||||
|
||||
// 创建一个结构体实例
|
||||
var packet = new CharacterSurveyPacket();
|
||||
|
||||
// 读取数据并填充到结构体中
|
||||
var reader = new PacketReader(data, position, size);
|
||||
packet.choice = reader.ReadUInt32();
|
||||
|
||||
context.SendPacket(new NoPayloadPacket(0x11, 0xDD));
|
||||
}
|
||||
}
|
||||
}
|
@ -150,9 +150,9 @@ namespace PSO2SERVER.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteAccountHeader(uint id)
|
||||
public void WriteAccountHeader(uint AccountId)
|
||||
{
|
||||
Write(id);
|
||||
Write(AccountId);
|
||||
Write((uint) 0);
|
||||
Write((ushort)ObjectType.Player);
|
||||
Write((ushort) 0);
|
||||
|
@ -6,13 +6,13 @@ using System.Text;
|
||||
|
||||
namespace PSO2SERVER.Protocol.Packets
|
||||
{
|
||||
public class SetPlayerIDPacket : Packet
|
||||
public class SetAccountIDPacket : Packet
|
||||
{
|
||||
private readonly int _PlayerId;
|
||||
private readonly int AccountId;
|
||||
|
||||
public SetPlayerIDPacket(int PlayerId)
|
||||
public SetAccountIDPacket(int AccountId)
|
||||
{
|
||||
_PlayerId = PlayerId;
|
||||
this.AccountId = AccountId;
|
||||
}
|
||||
|
||||
#region implemented abstract members of Packet
|
||||
@ -20,7 +20,7 @@ namespace PSO2SERVER.Protocol.Packets
|
||||
public override byte[] Build()
|
||||
{
|
||||
var pkt = new PacketWriter();
|
||||
pkt.WriteAccountHeader((uint)_PlayerId);
|
||||
pkt.WriteAccountHeader((uint)AccountId);
|
||||
return pkt.ToArray();
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
using PSO2SERVER.Models;
|
||||
using System.Runtime.InteropServices;
|
||||
using static PSO2SERVER.Protocol.Packets.CharacterSpawnPacket;
|
||||
|
||||
namespace PSO2SERVER.Protocol.Packets
|
||||
{
|
||||
@ -50,19 +52,23 @@ namespace PSO2SERVER.Protocol.Packets
|
||||
writer.Write((uint)602); // 0x48
|
||||
writer.Write((uint)1); // 0x4C
|
||||
writer.Write((uint)53); // 0x50
|
||||
writer.Write((uint)0); // 0x54
|
||||
writer.Write((uint)(IsItMe ? 47 : 39)); // 0x58
|
||||
writer.Write((uint)100); // 0x54
|
||||
writer.Write((uint)(IsItMe ? CharacterSpawnType.Myself : CharacterSpawnType.Other)); // 0x58
|
||||
writer.Write((ushort)559); // 0x5C
|
||||
writer.Write((ushort)306); // 0x5E
|
||||
writer.Write((uint)_character.Account.AccountId); // player ID copy
|
||||
writer.Write((uint)0); // "char array ugggghhhhh" according to PolarisLegacy
|
||||
|
||||
// Character
|
||||
writer.Write((uint)_character.AccountID); // player ID copy
|
||||
writer.Write((uint)_character.CharacterID); // "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.WriteStruct(_character.Looks);
|
||||
writer.WriteStruct(_character.Jobs);
|
||||
|
||||
writer.WriteFixedLengthUtf16("", 32); // title?
|
||||
|
||||
writer.Write((uint)0); // 0x204
|
||||
writer.Write((uint)0); // gmflag?
|
||||
writer.WriteFixedLengthUtf16(_character.Account.Nickname, 16); // Nickname, maybe not 16 chars?
|
||||
|
@ -63,7 +63,7 @@ namespace PSO2SERVER.Protocol.Packets
|
||||
}
|
||||
|
||||
//Size: 308 bytes, confirmed in unpacker
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public unsafe struct QuestDifficulty
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
|
||||
|
@ -54,8 +54,6 @@ namespace PSO2SERVER.Protocol.Packets
|
||||
writer.Write((uint)ch.AccountID);
|
||||
writer.Write((uint)ch.CharacterID);
|
||||
|
||||
//for (var i = 0; i < 0x10; i++)
|
||||
// writer.Write((byte)0);
|
||||
writer.Write(ch.Unk1);
|
||||
writer.Write(ch.VoiceType);
|
||||
writer.Write(ch.Unk2);
|
||||
|
@ -176,6 +176,7 @@
|
||||
<Compile Include="Object\ObjectManager.cs" />
|
||||
<Compile Include="Protocol\Handlers\0B-QuestHandler\0B-20-AcceptQuest.cs" />
|
||||
<Compile Include="Protocol\Handlers\11-ClientHandler\11-90-CharacterUndeletionRequest.cs" />
|
||||
<Compile Include="Protocol\Handlers\11-ClientHandler\11-DC-CharacterSurvey.cs" />
|
||||
<Compile Include="Protocol\Handlers\11-ClientHandler\11-EB-NicknameCheckRequest - 复制.cs" />
|
||||
<Compile Include="Protocol\Handlers\11-ClientHandler\11-52-CreateCharacterInviteNickname.cs" />
|
||||
<Compile Include="Protocol\Handlers\11-ClientHandler\11-C7-CharacterShipInfoRequest.cs" />
|
||||
@ -273,7 +274,7 @@
|
||||
<Compile Include="Protocol\Packets\04-ObjectRelatedPacket\04-81-ActionUpdateServerPacket.cs" />
|
||||
<Compile Include="Protocol\Packets\04-ObjectRelatedPacket\04-3B-DespawnPlayerPacket.cs" />
|
||||
<Compile Include="Protocol\Packets\06-PlayerStatusPacket\06-05-GainedEXPPacket.cs" />
|
||||
<Compile Include="Protocol\Packets\06-PlayerStatusPacket\06-00-SetPlayerIDPacket.cs" />
|
||||
<Compile Include="Protocol\Packets\06-PlayerStatusPacket\06-00-SetAccountIDPacket.cs" />
|
||||
<Compile Include="Protocol\Packets\08-SpawnPacket\08-09-EventSpawnPacket.cs" />
|
||||
<Compile Include="Protocol\Packets\08-SpawnPacket\08-0D-EnemySpawnPacket.cs" />
|
||||
<Compile Include="Protocol\Packets\08-SpawnPacket\08-05-TransporterSpawnPacket.cs" />
|
||||
|
@ -140,10 +140,8 @@ namespace PSO2SERVER.Zone
|
||||
c.CurrentZone.RemoveClient(c);
|
||||
}
|
||||
|
||||
//var setPlayerId = new PacketWriter();
|
||||
//setPlayerId.WriteAccountHeader((uint)c._account.AccountId);
|
||||
//c.SendPacket(0x06, 0x00, 0, setPlayerId.ToArray());
|
||||
c.SendPacket(new SetPlayerIDPacket(c._account.AccountId));
|
||||
// 设置客户端的账户ID
|
||||
c.SendPacket(new SetAccountIDPacket(c._account.AccountId));
|
||||
|
||||
// Spawn Character
|
||||
c.SendPacket(new CharacterSpawnPacket(c.Character, location));
|
||||
|
Loading…
Reference in New Issue
Block a user