暂存大量修改

This commit is contained in:
Longfeng Qin 2024-11-29 10:01:28 +08:00
parent eadf136dcb
commit 16bb43b1e9
18 changed files with 191 additions and 62 deletions

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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)]

View File

@ -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);

View File

@ -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));

View File

@ -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
{

View File

@ -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 需要补充完整
}

View File

@ -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));
}
}
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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?

View File

@ -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)]

View File

@ -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);

View File

@ -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" />

View File

@ -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));