修正LoadEquipedPacket

This commit is contained in:
Sancaros 2024-12-07 17:14:04 +08:00
parent 239440ec6c
commit 5e28e2791c
7 changed files with 166 additions and 73 deletions

View File

@ -238,7 +238,7 @@ namespace PSO2SERVER
public void CreateCommands()
{
// Help
var help = new ConsoleCommand(Help, "help") { Help = "显示服务端所有指令帮助" };
var help = new ConsoleCommand(Help, "help") { Help = "顯示服務端所有指令幫助" };
Commands.Add(help);
// Config
@ -391,7 +391,7 @@ namespace PSO2SERVER
Commands.Add(tellLoc);
// Exit
var exit = new ConsoleCommand(Exit, "exit", "quit") { Help = "关闭PSO2服务器" };
var exit = new ConsoleCommand(Exit, "exit", "quit") { Help = "關閉PSO2服務器" };
Commands.Add(exit);
}
@ -456,7 +456,7 @@ namespace PSO2SERVER
// Stop if the command line is blank
if (string.IsNullOrEmpty(_commandLine))
Logger.WriteWarning("[CMD] 未指定指令");
Logger.WriteWarning("[CMD] 空白指令");
else
{
// Iterate commands
@ -476,7 +476,7 @@ namespace PSO2SERVER
}
if (!valid)
Logger.WriteError("[CMD] {0} - 指令未找到", _commandLine.Split(' ')[0].Trim('\r'));
Logger.WriteError("[CMD] {0} - 指令不存在", _commandLine.Split(' ')[0].Trim('\r'));
// Add the command line to history and wipe it
_history.Add(_commandLine);
@ -499,7 +499,7 @@ namespace PSO2SERVER
// TODO: Use that fancy popup box when sending help to a client
private void Help(string[] args, int length, string full, Client client)
{
Logger.WriteCommand(client, "[CMD] 指令帮助菜单");
Logger.WriteCommand(client, "[CMD] 指令幫助菜單");
foreach (var command in Commands)
{
@ -566,7 +566,7 @@ namespace PSO2SERVER
c.SendPacket(messagePacket);
}
Logger.WriteCommand(client, "[CMD] 送公告至所有玩家");
Logger.WriteCommand(client, "[CMD] 送公告至所有玩家");
}
private void ClearLog(string[] args, int length, string full, Client client)
@ -590,29 +590,29 @@ namespace PSO2SERVER
break;
case "list":
Logger.WriteCommand(client, "[CMD] 设置选项");
Logger.WriteCommand(client, "[CMD] 設置選項");
foreach (var f in fields)
Logger.WriteCommand(client, "[CMD] {0} = {1}", f.Name, f.GetValue(ServerApp.Config));
break;
default: // Set a config option
if (args.Length < 3)
Logger.WriteCommand(client, "[CMD] Too few arguments");
Logger.WriteCommand(client, "[CMD] 指令參數不足");
else if (field != null)
{
var value = args[2].Contains('\"') ? full.Split('"')[1].Split('"')[0].Trim('\"') : args[2];
if (!ServerApp.Config.SetField(args[1], value))
Logger.WriteCommand(client, "[CMD] Config option {0} could not be changed to {1}", args[1],
Logger.WriteCommand(client, "[CMD] 設置選項 {0} 无法更改為 {1}", args[1],
value);
else
{
Logger.WriteCommand(client, "[CMD] Config option {0} changed to {1}", args[1], value);
Logger.WriteCommand(client, "[CMD] 設置選項 {0} 更改為 {1}", args[1], value);
ServerApp.Config.SettingsChanged();
}
}
else
Logger.WriteCommand(client, "[CMD] Config option {0} not found", args[1]);
Logger.WriteCommand(client, "[CMD] 設置選項 {0} 不存在", args[1]);
break;
}
}
@ -640,7 +640,7 @@ namespace PSO2SERVER
// Couldn't find the username
if (!foundPlayer)
{
Logger.WriteCommand(client, "[CMD] Could not find user " + name);
Logger.WriteCommand(client, "[CMD] 无法找到玩家 " + name);
return;
}
}
@ -680,7 +680,7 @@ namespace PSO2SERVER
// Couldn't find the username
if (!foundPlayer)
{
Logger.WriteError("[CMD] Could not find user " + name);
Logger.WriteError("[CMD] 无法找到玩家 " + name);
return;
}

View File

@ -317,6 +317,13 @@ namespace PSO2SERVER.Models
// ...
}
/// Player equiped item.
public struct EquipedItem
{
public PSO2Items item;
public uint unk;
}
}
public static class AffixUtils
{

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSO2SERVER.Models;
using PSO2SERVER.Party;
using PSO2SERVER.Protocol.Packets;
using PSO2SERVER.Zone;
namespace PSO2SERVER.Protocol.Handlers
{
[PacketHandlerAttr(0x04, 0x75)]
public class ActionEnd : PacketHandler
{
public ObjectHeader unk1 { get; set; } = new ObjectHeader();
/// Object that was performing an action.
public ObjectHeader performer { get; set; } = new ObjectHeader();
public uint unk2 { get; set; } = 0;
public ObjectHeader unk3 { get; set; } = new ObjectHeader();
public ObjectHeader unk4 { get; set; } = new ObjectHeader();
public byte[] unk5 { get; set; } = new byte[0x04];
public string action { get; set; } = string.Empty;//Ascii
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);
unk1 = reader.ReadStruct<ObjectHeader>();
performer = reader.ReadStruct<ObjectHeader>();
unk2 = reader.ReadUInt32();
unk3 = reader.ReadStruct<ObjectHeader>();
unk4 = reader.ReadStruct<ObjectHeader>();
unk5 = reader.ReadBytes(4);
action = reader.ReadAscii(0x83EF, 0x40);
// 打印各个字段的内容
Logger.Write("unk1: " + unk1); // 假设 ObjectHeader 重载了 ToString() 方法
Logger.Write("performer: " + performer); // 同上
Logger.Write("unk2: " + unk2);
Logger.Write("unk3: " + unk3);
Logger.Write("unk4: " + unk4);
Logger.Write("unk5: " + BitConverter.ToString(unk5)); // 打印 byte 数组
Logger.Write("action: " + action); // 打印 ASCII 字符串
foreach (Client cl in PartyManager.instance.GetCurrentPartyForClient(context).getMembers())
{
cl.SendPacket(new ActionEndPacket(unk1, performer, unk2, unk3, unk4, unk5, action));
}
}
}
}

View File

@ -0,0 +1,54 @@
using PSO2SERVER.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PSO2SERVER.Protocol.Packets
{
public class ActionEndPacket : Packet
{
public ObjectHeader unk1 { get; set; } = new ObjectHeader();
/// Object that was performing an action.
public ObjectHeader performer { get; set; } = new ObjectHeader();
public uint unk2 { get; set; } = 0;
public ObjectHeader unk3 { get; set; } = new ObjectHeader();
public ObjectHeader unk4 { get; set; } = new ObjectHeader();
public byte[] unk5 { get; set; } = new byte[0x04];
public string action { get; set; } = string.Empty;//Ascii
// 带参数的构造函数,用来初始化字段
public ActionEndPacket(ObjectHeader unk1, ObjectHeader performer, uint unk2, ObjectHeader unk3, ObjectHeader unk4, byte[] unk5, string action)
{
this.unk1 = unk1; // 如果传入的值为 null, 使用默认值
this.performer = performer;
this.unk2 = unk2;
this.unk3 = unk3;
this.unk4 = unk4;
this.unk5 = unk5 ?? new byte[0x04]; // 如果传入的值为 null, 使用默认字节数组
this.action = action ?? string.Empty; // 如果传入的值为 null, 使用空字符串
}
#region implemented abstract members of Packet
public override byte[] Build()
{
var pkt = new PacketWriter();
pkt.WriteStruct(unk1);
pkt.WriteStruct(performer);
pkt.Write(unk2);
pkt.WriteStruct(unk3);
pkt.WriteStruct(unk4);
pkt.WriteByteArray(unk5);
pkt.WriteAscii(action, 0x83EF, 0x40);
return pkt.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x04, 0x75, PacketFlags.PACKED_OBJECT_RELATED);
}
#endregion
}
}

View File

@ -1,6 +1,7 @@
using PSO2SERVER.Database;
using PSO2SERVER.Models;
using PSO2SERVER.Zone;
using System.IO;
using System.Runtime.InteropServices;
using static PSO2SERVER.Models.CharacterStruct;
using static PSO2SERVER.Protocol.Packets.CharacterSpawnPacket;
@ -31,37 +32,40 @@ namespace PSO2SERVER.Protocol.Packets
public PSOLocation ObjPosition { get; set; } = new PSOLocation();
public ushort Unk1 { get; set; } = 0;
/// Always `Character`. (?)
public string ObjName { get; set; } = "Character";//0x20
public string ObjName { get; set; } = "Character";//Ascii 0x20
public ushort Unk3 { get; set; } = 1;
public ushort Unk4 { get; set; }
public uint Unk5 { get; set; }
public uint Unk6 { get; set; }
public uint Unk7 { get; set; }
public uint Unk8 { get; set; }
/// Character spawn type.
public CharacterSpawnType SpawnType { get; set; }
public byte Unk9 { get; set; }
public ushort Unk10 { get; set; }
/// Character data.
public Character Character { get; set; }
public uint Unk11 { get; set; }
/// Set to `1` if the player is a GM.
public uint GmFlag { get; set; }
public string Nickname { get; set; }
/// Player's nickname.
public string Nickname { get; set; }//0x10
//#[SeekAfter(0x60)]
public byte[] Unk12 { get; set; } = new byte[0x40];
public CharacterSpawnPacket(Character character, PSOLocation locatiion)
{
ObjHeader = new ObjectHeader((uint)character.Account.AccountId, ObjectType.Player);
Character = character;
ObjPosition = locatiion;
Character = character;
}
public CharacterSpawnPacket(Character character, PSOLocation locatiion, bool isme, bool isgm)
{
ObjHeader = new ObjectHeader((uint)character.Account.AccountId, ObjectType.Player);
ObjPosition = locatiion;
Character = character;
SpawnType = isme ? CharacterSpawnType.Myself : CharacterSpawnType.Other;
ObjPosition = locatiion;
GmFlag = isgm ? (uint)1 : 0;
}
@ -90,56 +94,8 @@ namespace PSO2SERVER.Protocol.Packets
pkt.Write(Unk11);
pkt.Write(GmFlag);
pkt.WriteFixedLengthUtf16(Character.Account.Nickname, 0x10);
//for (var i = 0; i < 0x60; i++)
// pkt.Write((byte)0);
//pkt.Write(unk12);
//pkt.Write((ushort)0); // 0x46
//pkt.Write((uint)602); // 0x48
//pkt.Write((uint)1); // 0x4C
//pkt.Write((uint)53); // 0x50
//pkt.Write((uint)0); // 0x54
//// Character spawn type.
//pkt.Write(IsItMe); // 0x58
//pkt.Write((byte)0x00);
//pkt.Write((ushort)0x00);
//////writer.write((ushort)0x022f); // 0x5c
////writer.write((byte)0x2f); // 0x5c
////writer.write((byte)0x02);
//////writer.write((ushort)0x0132); // 0x5e
////writer.write((byte)0x32);
////writer.write((byte)0x01);
////JobParam jobParam = _character.Jobs;
////jobParam.mainClass = ClassType.Luster;
////jobParam.subClass = ClassType.Phantom;
////jobParam.entries.Luster.level = 100;
//// Character data.
//pkt.Write((uint)_character.AccountID);
//pkt.Write((uint)_character.CharacterID);
//pkt.Write((uint)_character.Unk1);//4
//pkt.Write((uint)_character.VoiceType);//4
//pkt.Write((ushort)_character.Unk2);//2
//pkt.Write(_character.VoicePitch);//2
//pkt.WriteFixedLengthUtf16(_character.Name, 16);
//pkt.Write((uint)_character.Unk3); // 0x90
//pkt.WriteStruct(_character.Looks);
//pkt.WriteStruct(_character.Jobs);
//pkt.WriteFixedLengthUtf16(_character.Account.Nickname, 16);
//pkt.WriteBytes(0, 116);
//pkt.Write((uint)0); // 0x204
//pkt.Write(IsGM); // gmflag?
//for (var i = 0; i < 0x60; i++)
// pkt.Write((byte)0);
//for (var i = 0; i < 0x40; i++)
// writer.Write((byte)0);
pkt.BaseStream.Seek(0x60, SeekOrigin.Current);
pkt.Write(Unk12);
return pkt.ToArray();
}

View File

@ -1,21 +1,43 @@
using System;
using System.Collections.Generic;
using PSO2SERVER.Models;
namespace PSO2SERVER.Protocol.Packets
{
public class LoadEquipedPacket : Packet
{
public Int64 NewAmount = 0;
/// Player whose equipment is loaded.
public ObjectHeader Player { get; set; } = new ObjectHeader();
/// Player's equiped items.
public List<EquipedItem> Items { get; set; } = new List<EquipedItem>();
// 0-back unit
// 1-arm unit
// 2-leg unit
// 3-outfit
// 9-weapon
public uint Unk1 { get; set; } = 0;
public byte[] Unk2 { get; set; } = new byte[0x28];
#region implemented abstract members of Packet
public LoadEquipedPacket(uint accountid, List<EquipedItem> items)
{
Player = new ObjectHeader(accountid, ObjectType.Player);
Items = items;
}
public override byte[] Build()
{
var writer = new PacketWriter();
writer.Write(NewAmount);
return writer.ToArray();
var pkt = new PacketWriter();
pkt.WriteStruct(Player);
pkt.WriteMagic((uint)Items.Count, 0xCF76, 0xB5);
foreach (var item in Items)
{
pkt.WriteStruct(item);
}
pkt.Write(Unk1);
pkt.Write(Unk2);
return pkt.ToArray();
}
public override PacketHeader GetHeader()

View File

@ -187,6 +187,7 @@
<Compile Include="Network\Ipv4Addr.cs" />
<Compile Include="Network\PortChecker.cs" />
<Compile Include="Object\ObjectManager.cs" />
<Compile Include="Protocol\Handlers\04-ObjectHandler\04-75-ActionEnd.cs" />
<Compile Include="Protocol\Handlers\06-PlayerStatusHandler\06-01-DealDamage.cs" />
<Compile Include="Protocol\Handlers\0B-QuestHandler\0B-20-AcceptQuest.cs" />
<Compile Include="Protocol\Handlers\11-ClientHandler\11-14-BlockLogin.cs" />
@ -258,6 +259,7 @@
<Compile Include="Protocol\Handlers\4A-ARKSMisionsHandler\4A-00-MissionListRequest.cs" />
<Compile Include="Protocol\Handlers\4D-ClassicMissionPassHandler\4D-02-MissionPassRequest.cs" />
<Compile Include="Protocol\Handlers\4D-ClassicMissionPassHandler\4D-00-MissionPassInfoRequest.cs" />
<Compile Include="Protocol\Packets\04-ObjectRelatedPacket\04-75-ActionEndPacket.cs" />
<Compile Include="Protocol\Packets\0B-QuestPacket\0B-1B-QuestCategoryStopperPacket.cs" />
<Compile Include="Protocol\Packets\19-LobbyPacket\19-08-SendSystemMessagePacket.cs" />
<Compile Include="Protocol\Packets\1E-UnkPacket\1E-0C-Unk1E0CPacket.cs" />