using PSO2SERVER.Database; using PSO2SERVER.Models; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.Remoting.Contexts; using System.Text; using static PSO2SERVER.Models.CharacterStruct; namespace PSO2SERVER.Protocol.Packets { public class CharacterListPacket : Packet { public uint Characters_count { get; set; } = 0; public uint unk1 { get; set; } = 0; // Available characters public List Characters { get; set; } = new List(); // Equipped items (List of 10 Items for each character) public List EquippedItems { get; set; } = new List(); // Character play times (30 times) public uint[] PlayTimes { get; set; } = new uint[30]; // Character deletion flags (flag, deletion timestamp) (30 pairs of (u32, u32)) public (uint flag, uint timestamp)[] DeletionFlags { get; set; } = new (uint, uint)[30]; // Character ship transfer flags (30 pairs of (u32, u32)) public (uint flag, uint timestamp)[] TransferFlags { get; set; } = new (uint, uint)[30]; // Account accessory flag (unknown) public ushort AccountAccessory { get; set; } // Login survey flag public uint LoginSurvey { get; set; } // Ad flag public uint Ad { get; set; } // 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 AccountId; public CharacterListPacket(int AccountId) { this.AccountId = AccountId; } #region implemented abstract members of Packet public override byte[] Build() { using (var db = new ServerEf()) { var chars = db.Characters .Where(w => w.AccountID == AccountId) .OrderBy(o => o.CharacterID) // TODO: 按照最后游玩的角色排序 .Select(s => s); foreach (var ch in chars) { Characters.Add(ch); //// 创建一个 Consumable 类型的物品 //PSO2ItemConsumable consumableItem = new PSO2ItemConsumable //{ // amount = 10, //}; //PSO2Items[] items = new PSO2Items[10]; //for (var i = 0; i < 10; i++) //{ // items[i] = new PSO2Items // { // uuid = (ulong)i, // id = new ItemId // { // ItemType = 3, // Id = 1, // Subid = 0, // }, // data = new Items { Consumable = consumableItem } // }; //} ch.EquipedItems = new PSO2Items[10]; EquippedItems.Add(ch.EquipedItems); } Characters_count = (uint)Characters.Count(); } var rest_count = 30 - Characters_count; for (var i = 0; i < rest_count; i++) { //Character character = Characters[0]; Characters.Add(Characters[0]); EquippedItems.Add(EquippedItems[0]); } var pkt = new PacketWriter(); pkt.Write(Characters_count); // 写入玩家数量 pkt.Write(unk1); foreach (var ch in Characters) { pkt.Write((uint)0); pkt.Write(ch.BuildCharacterByteArray());//4 } pkt.Write(File.ReadAllBytes("packets/charlist_rest.bin")); //pkt.Write((uint)EquippedItems.Count()); // 写入物品数量 //foreach (var itemsArray in EquippedItems) //{ // foreach (var item in itemsArray) // { // pkt.WriteStruct(item); // } //} //// Write PlayTimes //foreach (var playTime in PlayTimes) //{ // pkt.Write(playTime); //} //// Write DeletionFlags //foreach (var flag in DeletionFlags) //{ // pkt.Write(flag.flag); // pkt.Write(flag.timestamp); //} //// Write TransferFlags //foreach (var flag in TransferFlags) //{ // pkt.Write(flag.flag); // pkt.Write(flag.timestamp); //} //// Write AccountAccessory //pkt.Write(AccountAccessory); //// Write LoginSurvey //pkt.Write(LoginSurvey); //// Write Ad //pkt.Write(Ad); //pkt.WriteBytes(0, 2); return pkt.ToArray(); } public override PacketHeader GetHeader() { return new PacketHeader(0x11, 0x03, PacketFlags.None); } #endregion } }