CharacterInfo.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. using System.Drawing;
  2. using Server.MirEnvir;
  3. using Server.MirNetwork;
  4. using Server.MirObjects;
  5. namespace Server.MirDatabase
  6. {
  7. public class CharacterInfo
  8. {
  9. protected static Envir Envir
  10. {
  11. get { return Envir.Main; }
  12. }
  13. public int Index;
  14. public string Name;
  15. public ushort Level;
  16. public MirClass Class;
  17. public MirGender Gender;
  18. public byte Hair;
  19. public int GuildIndex = -1;
  20. public string CreationIP;
  21. public DateTime CreationDate;
  22. public bool Banned;
  23. public string BanReason = string.Empty;
  24. public DateTime ExpiryDate;
  25. public bool ChatBanned;
  26. public DateTime ChatBanExpiryDate;
  27. public string LastIP = string.Empty;
  28. public DateTime LastLogoutDate;
  29. public DateTime LastLoginDate;
  30. public bool Deleted;
  31. public DateTime DeleteDate;
  32. //Marriage
  33. public int Married = 0;
  34. public DateTime MarriedDate;
  35. //Mentor
  36. public int Mentor = 0;
  37. public DateTime MentorDate;
  38. public bool IsMentor;
  39. public long MentorExp = 0;
  40. //Location
  41. public int CurrentMapIndex;
  42. public Point CurrentLocation;
  43. public MirDirection Direction;
  44. public int BindMapIndex;
  45. public Point BindLocation;
  46. public int HP, MP;
  47. public long Experience;
  48. public AttackMode AMode;
  49. public PetMode PMode;
  50. public bool AllowGroup;
  51. public bool AllowTrade;
  52. public bool AllowObserve;
  53. public int PKPoints;
  54. public bool NewDay;
  55. public bool Thrusting, HalfMoon, CrossHalfMoon;
  56. public bool DoubleSlash;
  57. public byte MentalState;
  58. public byte MentalStateLvl;
  59. public UserItem[] Inventory = new UserItem[46], Equipment = new UserItem[14], Trade = new UserItem[10], QuestInventory = new UserItem[40], Refine = new UserItem[16];
  60. public List<ItemRentalInformation> RentedItems = new List<ItemRentalInformation>();
  61. public List<ItemRentalInformation> RentedItemsToRemove = new List<ItemRentalInformation>();
  62. public bool HasRentedItem;
  63. public UserItem CurrentRefine = null;
  64. public long CollectTime = 0, RefineTimeRemaining = 0;
  65. public List<UserMagic> Magics = new List<UserMagic>();
  66. public List<PetInfo> Pets = new List<PetInfo>();
  67. public List<Buff> Buffs = new List<Buff>();
  68. public List<Poison> Poisons = new List<Poison>();
  69. public List<MailInfo> Mail = new List<MailInfo>();
  70. public List<FriendInfo> Friends = new List<FriendInfo>();
  71. public List<UserIntelligentCreature> IntelligentCreatures = new List<UserIntelligentCreature>();
  72. public int PearlCount;
  73. public List<QuestProgressInfo> CurrentQuests = new List<QuestProgressInfo>();
  74. public List<int> CompletedQuests = new List<int>();
  75. public bool[] Flags = new bool[Globals.FlagIndexCount];
  76. public AccountInfo AccountInfo;
  77. public PlayerObject Player;
  78. public MountInfo Mount;
  79. public Dictionary<int, int> GSpurchases = new Dictionary<int, int>();
  80. public int[] Rank = new int[2];//dont save this in db!(and dont send it to clients :p)
  81. public int MaximumHeroCount = 1;
  82. public HeroInfo[] Heroes;
  83. public int CurrentHeroIndex;
  84. public bool HeroSpawned;
  85. public HeroBehaviour HeroBehaviour;
  86. public CharacterInfo() { }
  87. public CharacterInfo(ClientPackets.NewCharacter p, MirConnection c)
  88. {
  89. Name = p.Name;
  90. Class = p.Class;
  91. Gender = p.Gender;
  92. Heroes = new HeroInfo[MaximumHeroCount];
  93. CreationIP = c.IPAddress;
  94. CreationDate = Envir.Now;
  95. }
  96. public CharacterInfo(BinaryReader reader, int version, int customVersion)
  97. {
  98. Load(reader, version, customVersion);
  99. }
  100. public virtual void Load(BinaryReader reader, int version, int customVersion)
  101. {
  102. Index = reader.ReadInt32();
  103. Name = reader.ReadString();
  104. if (version < 62)
  105. {
  106. Level = (ushort)reader.ReadByte();
  107. }
  108. else
  109. {
  110. Level = reader.ReadUInt16();
  111. }
  112. Class = (MirClass)reader.ReadByte();
  113. Gender = (MirGender)reader.ReadByte();
  114. Hair = reader.ReadByte();
  115. CreationIP = reader.ReadString();
  116. CreationDate = DateTime.FromBinary(reader.ReadInt64());
  117. Banned = reader.ReadBoolean();
  118. BanReason = reader.ReadString();
  119. ExpiryDate = DateTime.FromBinary(reader.ReadInt64());
  120. LastIP = reader.ReadString();
  121. LastLogoutDate = DateTime.FromBinary(reader.ReadInt64());
  122. if (version > 81)
  123. {
  124. LastLoginDate = DateTime.FromBinary(reader.ReadInt64());
  125. }
  126. Deleted = reader.ReadBoolean();
  127. DeleteDate = DateTime.FromBinary(reader.ReadInt64());
  128. CurrentMapIndex = reader.ReadInt32();
  129. CurrentLocation = new Point(reader.ReadInt32(), reader.ReadInt32());
  130. Direction = (MirDirection)reader.ReadByte();
  131. BindMapIndex = reader.ReadInt32();
  132. BindLocation = new Point(reader.ReadInt32(), reader.ReadInt32());
  133. if (version <= 84)
  134. {
  135. HP = reader.ReadUInt16();
  136. MP = reader.ReadUInt16();
  137. }
  138. else
  139. {
  140. HP = reader.ReadInt32();
  141. MP = reader.ReadInt32();
  142. }
  143. Experience = reader.ReadInt64();
  144. AMode = (AttackMode)reader.ReadByte();
  145. PMode = (PetMode)reader.ReadByte();
  146. if (version > 34)
  147. {
  148. PKPoints = reader.ReadInt32();
  149. }
  150. int count = reader.ReadInt32();
  151. Array.Resize(ref Inventory, count);
  152. for (int i = 0; i < count; i++)
  153. {
  154. if (!reader.ReadBoolean()) continue;
  155. UserItem item = new UserItem(reader, version, customVersion);
  156. if (Envir.BindItem(item) && i < Inventory.Length)
  157. {
  158. Inventory[i] = item;
  159. }
  160. }
  161. count = reader.ReadInt32();
  162. for (int i = 0; i < count; i++)
  163. {
  164. if (!reader.ReadBoolean()) continue;
  165. UserItem item = new UserItem(reader, version, customVersion);
  166. if (Envir.BindItem(item) && i < Equipment.Length)
  167. {
  168. Equipment[i] = item;
  169. }
  170. }
  171. count = reader.ReadInt32();
  172. for (int i = 0; i < count; i++)
  173. {
  174. if (!reader.ReadBoolean()) continue;
  175. UserItem item = new UserItem(reader, version, customVersion);
  176. if (Envir.BindItem(item) && i < QuestInventory.Length)
  177. {
  178. QuestInventory[i] = item;
  179. }
  180. }
  181. count = reader.ReadInt32();
  182. for (int i = 0; i < count; i++)
  183. {
  184. UserMagic magic = new UserMagic(reader, version, customVersion);
  185. if (magic.Info == null) continue;
  186. magic.CastTime = int.MinValue;
  187. Magics.Add(magic);
  188. }
  189. Thrusting = reader.ReadBoolean();
  190. HalfMoon = reader.ReadBoolean();
  191. CrossHalfMoon = reader.ReadBoolean();
  192. DoubleSlash = reader.ReadBoolean();
  193. MentalState = reader.ReadByte();
  194. count = reader.ReadInt32();
  195. for (int i = 0; i < count; i++)
  196. {
  197. Pets.Add(new PetInfo(reader, version, customVersion));
  198. }
  199. AllowGroup = reader.ReadBoolean();
  200. for (int i = 0; i < Globals.FlagIndexCount; i++)
  201. {
  202. Flags[i] = reader.ReadBoolean();
  203. }
  204. GuildIndex = reader.ReadInt32();
  205. AllowTrade = reader.ReadBoolean();
  206. if (version > 104)
  207. AllowObserve = reader.ReadBoolean();
  208. count = reader.ReadInt32();
  209. for (int i = 0; i < count; i++)
  210. {
  211. QuestProgressInfo quest = new QuestProgressInfo(reader, version, customVersion);
  212. if (quest == null || quest.Info == null || quest.IsOrphan)
  213. {
  214. Console.WriteLine($"[Load] Skipped orphan QuestProgress (Index={quest?.Index}) for character: {Name}");
  215. continue;
  216. }
  217. if (Envir.BindQuest(quest))
  218. {
  219. CurrentQuests.Add(quest);
  220. }
  221. }
  222. count = reader.ReadInt32();
  223. for (int i = 0; i < count; i++)
  224. {
  225. Buff buff = new Buff(reader, version, customVersion);
  226. Buffs.Add(buff);
  227. }
  228. count = reader.ReadInt32();
  229. for (int i = 0; i < count; i++)
  230. {
  231. Mail.Add(new MailInfo(reader, version, customVersion));
  232. }
  233. count = reader.ReadInt32();
  234. for (int i = 0; i < count; i++)
  235. {
  236. UserIntelligentCreature creature = new UserIntelligentCreature(reader, version, customVersion);
  237. if (creature.Info == null) continue;
  238. IntelligentCreatures.Add(creature);
  239. }
  240. if (version == 45)
  241. {
  242. var old1 = (IntelligentCreatureType)reader.ReadByte();
  243. var old2 = reader.ReadBoolean();
  244. }
  245. PearlCount = reader.ReadInt32();
  246. count = reader.ReadInt32();
  247. for (int i = 0; i < count; i++)
  248. {
  249. CompletedQuests.Add(reader.ReadInt32());
  250. }
  251. if (reader.ReadBoolean())
  252. {
  253. CurrentRefine = new UserItem(reader, version, customVersion);
  254. }
  255. if (CurrentRefine != null)
  256. {
  257. Envir.BindItem(CurrentRefine);
  258. }
  259. RefineTimeRemaining = reader.ReadInt64();
  260. CollectTime = Envir.Time + RefineTimeRemaining;
  261. count = reader.ReadInt32();
  262. for (int i = 0; i < count; i++)
  263. {
  264. Friends.Add(new FriendInfo(reader, version, customVersion));
  265. }
  266. if (version > 75)
  267. {
  268. count = reader.ReadInt32();
  269. for (var i = 0; i < count; i++)
  270. {
  271. RentedItems.Add(new ItemRentalInformation(reader, version, customVersion));
  272. }
  273. HasRentedItem = reader.ReadBoolean();
  274. }
  275. Married = reader.ReadInt32();
  276. MarriedDate = DateTime.FromBinary(reader.ReadInt64());
  277. Mentor = reader.ReadInt32();
  278. MentorDate = DateTime.FromBinary(reader.ReadInt64());
  279. IsMentor = reader.ReadBoolean();
  280. MentorExp = reader.ReadInt64();
  281. if (version >= 63)
  282. {
  283. int logCount = reader.ReadInt32();
  284. for (int i = 0; i < logCount; i++)
  285. {
  286. GSpurchases.Add(reader.ReadInt32(), reader.ReadInt32());
  287. }
  288. }
  289. if (version > 98)
  290. {
  291. MaximumHeroCount = reader.ReadInt32();
  292. Heroes = new HeroInfo[MaximumHeroCount];
  293. if (version > 102)
  294. {
  295. for (int i = 0; i < MaximumHeroCount; i++)
  296. {
  297. int heroIndex = reader.ReadInt32();
  298. if (heroIndex > 0)
  299. Heroes[i] = Envir.GetHeroInfo(heroIndex);
  300. }
  301. }
  302. else
  303. {
  304. for (int i = 0; i < MaximumHeroCount; i++)
  305. Heroes[i] = new HeroInfo(reader, version, customVersion);
  306. }
  307. if (version < 104) reader.ReadInt32();
  308. CurrentHeroIndex = reader.ReadInt32();
  309. HeroSpawned = reader.ReadBoolean();
  310. }
  311. else Heroes = new HeroInfo[MaximumHeroCount];
  312. if (version > 100)
  313. HeroBehaviour = (HeroBehaviour)reader.ReadByte();
  314. }
  315. public virtual void Save(BinaryWriter writer)
  316. {
  317. writer.Write(Index);
  318. writer.Write(Name);
  319. writer.Write(Level);
  320. writer.Write((byte) Class);
  321. writer.Write((byte) Gender);
  322. writer.Write(Hair);
  323. writer.Write(CreationIP);
  324. writer.Write(CreationDate.ToBinary());
  325. writer.Write(Banned);
  326. writer.Write(BanReason);
  327. writer.Write(ExpiryDate.ToBinary());
  328. writer.Write(LastIP);
  329. writer.Write(LastLogoutDate.ToBinary());
  330. writer.Write(LastLoginDate.ToBinary());
  331. writer.Write(Deleted);
  332. writer.Write(DeleteDate.ToBinary());
  333. writer.Write(CurrentMapIndex);
  334. writer.Write(CurrentLocation.X);
  335. writer.Write(CurrentLocation.Y);
  336. writer.Write((byte)Direction);
  337. writer.Write(BindMapIndex);
  338. writer.Write(BindLocation.X);
  339. writer.Write(BindLocation.Y);
  340. writer.Write(HP);
  341. writer.Write(MP);
  342. writer.Write(Experience);
  343. writer.Write((byte) AMode);
  344. writer.Write((byte) PMode);
  345. writer.Write(PKPoints);
  346. writer.Write(Inventory.Length);
  347. for (int i = 0; i < Inventory.Length; i++)
  348. {
  349. writer.Write(Inventory[i] != null);
  350. if (Inventory[i] == null) continue;
  351. Inventory[i].Save(writer);
  352. }
  353. writer.Write(Equipment.Length);
  354. for (int i = 0; i < Equipment.Length; i++)
  355. {
  356. writer.Write(Equipment[i] != null);
  357. if (Equipment[i] == null) continue;
  358. Equipment[i].Save(writer);
  359. }
  360. writer.Write(QuestInventory.Length);
  361. for (int i = 0; i < QuestInventory.Length; i++)
  362. {
  363. writer.Write(QuestInventory[i] != null);
  364. if (QuestInventory[i] == null) continue;
  365. QuestInventory[i].Save(writer);
  366. }
  367. writer.Write(Magics.Count);
  368. for (int i = 0; i < Magics.Count; i++)
  369. {
  370. Magics[i].Save(writer);
  371. }
  372. writer.Write(Thrusting);
  373. writer.Write(HalfMoon);
  374. writer.Write(CrossHalfMoon);
  375. writer.Write(DoubleSlash);
  376. writer.Write(MentalState);
  377. writer.Write(Pets.Count);
  378. for (int i = 0; i < Pets.Count; i++)
  379. {
  380. Pets[i].Save(writer);
  381. }
  382. writer.Write(AllowGroup);
  383. for (int i = 0; i < Flags.Length; i++)
  384. {
  385. writer.Write(Flags[i]);
  386. }
  387. writer.Write(GuildIndex);
  388. writer.Write(AllowTrade);
  389. writer.Write(AllowObserve);
  390. writer.Write(CurrentQuests.Count);
  391. for (int i = 0; i < CurrentQuests.Count; i++)
  392. {
  393. CurrentQuests[i].Save(writer);
  394. }
  395. writer.Write(Buffs.Count);
  396. for (int i = 0; i < Buffs.Count; i++)
  397. {
  398. Buffs[i].Save(writer);
  399. }
  400. writer.Write(Mail.Count);
  401. for (int i = 0; i < Mail.Count; i++)
  402. {
  403. Mail[i].Save(writer);
  404. }
  405. writer.Write(IntelligentCreatures.Count);
  406. for (int i = 0; i < IntelligentCreatures.Count; i++)
  407. {
  408. IntelligentCreatures[i].Save(writer);
  409. }
  410. writer.Write(PearlCount);
  411. writer.Write(CompletedQuests.Count);
  412. for (int i = 0; i < CompletedQuests.Count; i++)
  413. {
  414. writer.Write(CompletedQuests[i]);
  415. }
  416. writer.Write(CurrentRefine != null);
  417. if (CurrentRefine != null)
  418. {
  419. CurrentRefine.Save(writer);
  420. }
  421. RefineTimeRemaining = CollectTime - Envir.Time;
  422. if (RefineTimeRemaining < 0)
  423. RefineTimeRemaining = 0;
  424. writer.Write(RefineTimeRemaining);
  425. writer.Write(Friends.Count);
  426. for (int i = 0; i < Friends.Count; i++)
  427. {
  428. if (Friends[i].Info == null) continue;
  429. Friends[i].Save(writer);
  430. }
  431. writer.Write(RentedItems.Count);
  432. foreach (var rentedItemInformation in RentedItems)
  433. {
  434. rentedItemInformation.Save(writer);
  435. }
  436. writer.Write(HasRentedItem);
  437. writer.Write(Married);
  438. writer.Write(MarriedDate.ToBinary());
  439. writer.Write(Mentor);
  440. writer.Write(MentorDate.ToBinary());
  441. writer.Write(IsMentor);
  442. writer.Write(MentorExp);
  443. writer.Write(GSpurchases.Count);
  444. foreach (var item in GSpurchases)
  445. {
  446. writer.Write(item.Key);
  447. writer.Write(item.Value);
  448. }
  449. writer.Write(MaximumHeroCount);
  450. for (int i = 0; i < Heroes.Length; i++)
  451. writer.Write(Heroes[i] != null ? Heroes[i].Index : 0);
  452. writer.Write(CurrentHeroIndex);
  453. writer.Write(HeroSpawned);
  454. writer.Write((byte)HeroBehaviour);
  455. }
  456. public SelectInfo ToSelectInfo()
  457. {
  458. return new SelectInfo
  459. {
  460. Index = Index,
  461. Name = Name,
  462. Level = Level,
  463. Class = Class,
  464. Gender = Gender,
  465. LastAccess = LastLogoutDate
  466. };
  467. }
  468. public bool CheckHasIntelligentCreature(IntelligentCreatureType petType)
  469. {
  470. for (int i = 0; i < IntelligentCreatures.Count; i++)
  471. {
  472. if (IntelligentCreatures[i].PetType == petType) return true;
  473. }
  474. return false;
  475. }
  476. public virtual int ResizeInventory()
  477. {
  478. if (Inventory.Length >= 86) return Inventory.Length;
  479. if (Inventory.Length == 46)
  480. {
  481. Array.Resize(ref Inventory, Inventory.Length + 8);
  482. }
  483. else
  484. {
  485. Array.Resize(ref Inventory, Inventory.Length + 4);
  486. }
  487. return Inventory.Length;
  488. }
  489. }
  490. public class PetInfo
  491. {
  492. public int MonsterIndex;
  493. public int HP;
  494. public uint Experience;
  495. public byte Level, MaxPetLevel;
  496. public long TameTime;
  497. public PetInfo(MonsterObject ob)
  498. {
  499. MonsterIndex = ob.Info.Index;
  500. HP = ob.HP;
  501. Experience = ob.PetExperience;
  502. Level = ob.PetLevel;
  503. MaxPetLevel = ob.MaxPetLevel;
  504. }
  505. public PetInfo(BinaryReader reader, int version, int customVersion)
  506. {
  507. MonsterIndex = reader.ReadInt32();
  508. if (MonsterIndex == 271) MonsterIndex = 275;
  509. if (version <= 84)
  510. {
  511. HP = (int)reader.ReadUInt32();
  512. }
  513. else
  514. {
  515. HP = reader.ReadInt32();
  516. }
  517. Experience = reader.ReadUInt32();
  518. Level = reader.ReadByte();
  519. MaxPetLevel = reader.ReadByte();
  520. }
  521. public void Save(BinaryWriter writer)
  522. {
  523. writer.Write(MonsterIndex);
  524. writer.Write(HP);
  525. writer.Write(Experience);
  526. writer.Write(Level);
  527. writer.Write(MaxPetLevel);
  528. }
  529. }
  530. public class MountInfo
  531. {
  532. private HumanObject Player { get; set; }
  533. public short MountType = -1;
  534. private bool PlayerHasMap
  535. {
  536. get { return Player != null && Player.CurrentMap != null; }
  537. }
  538. public bool CanRide
  539. {
  540. get { return HasMount && Slots[(int)MountSlot.Saddle] != null; }
  541. }
  542. public bool CanMapRide
  543. {
  544. get { return HasMount && PlayerHasMap && !Player.CurrentMap.Info.NoMount; }
  545. }
  546. public bool CanDungeonRide
  547. {
  548. get { return HasMount && CanMapRide && (!Player.CurrentMap.Info.NeedBridle || Slots[(int)MountSlot.Reins] != null); }
  549. }
  550. public bool CanAttack
  551. {
  552. get { return HasMount && Slots[(int)MountSlot.Bells] != null || !RidingMount; }
  553. }
  554. public bool SlowLoyalty
  555. {
  556. get { return HasMount && Slots[(int)MountSlot.Ribbon] != null; }
  557. }
  558. public bool HasMount
  559. {
  560. get { return Player.Info.Equipment[(int)EquipmentSlot.Mount] != null; }
  561. }
  562. private bool RidingMount
  563. {
  564. get { return Player.RidingMount; }
  565. set { Player.RidingMount = value; }
  566. }
  567. public UserItem[] Slots
  568. {
  569. get { return Player.Info.Equipment[(int)EquipmentSlot.Mount].Slots; }
  570. }
  571. public MountInfo(HumanObject ob)
  572. {
  573. Player = ob;
  574. }
  575. }
  576. public class FriendInfo
  577. {
  578. protected static Envir Envir
  579. {
  580. get { return Envir.Main; }
  581. }
  582. public int Index;
  583. private CharacterInfo _Info;
  584. public CharacterInfo Info
  585. {
  586. get
  587. {
  588. if (_Info == null)
  589. {
  590. _Info = Envir.GetCharacterInfo(Index);
  591. }
  592. return _Info;
  593. }
  594. }
  595. public bool Blocked;
  596. public string Memo;
  597. public FriendInfo(CharacterInfo info, bool blocked)
  598. {
  599. Index = info.Index;
  600. Blocked = blocked;
  601. Memo = "";
  602. }
  603. public FriendInfo(BinaryReader reader, int version, int customVersion)
  604. {
  605. Index = reader.ReadInt32();
  606. Blocked = reader.ReadBoolean();
  607. Memo = reader.ReadString();
  608. }
  609. public void Save(BinaryWriter writer)
  610. {
  611. writer.Write(Index);
  612. writer.Write(Blocked);
  613. writer.Write(Memo);
  614. }
  615. public ClientFriend CreateClientFriend()
  616. {
  617. return new ClientFriend()
  618. {
  619. Index = Index,
  620. Name = Info.Name,
  621. Blocked = Blocked,
  622. Memo = Memo,
  623. Online = Info.Player != null && Info.Player.Node != null
  624. };
  625. }
  626. }
  627. }