ChestManager.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Xml;
  8. using Sfs2X.Entities.Data;
  9. using UnityEngine;
  10. using UnityEngine.UI;
  11. using Random = UnityEngine.Random;
  12. public class ChestData
  13. {
  14. #region Config
  15. public int Value;
  16. public int Round;
  17. public int RemainValue;
  18. public int RemainRound;
  19. public int DatabaseRoomID;
  20. public long ID;
  21. public long Owner;
  22. public DateTime ActivatedTime;
  23. public ChestType ChestType;
  24. public Vector3 Position;
  25. public static int SystemRoomDatabaseID = 1;
  26. private static bool Initialized;
  27. private static Vector3 DefaultPosition;
  28. //private static Vector3 ChestOffset = new Vector3(0, 0, 1.040916f);
  29. private static Vector3 ChestOffset = new Vector3(0, 0, 0.079915f);
  30. #endregion
  31. public ChestData(ISFSObject arg)
  32. {
  33. if (!Initialized)
  34. {
  35. Initialize();
  36. }
  37. ID = arg.GetLong(gd_chest.ID);
  38. Value = arg.GetInt(gd_chest.Value);
  39. Round = arg.GetInt(gd_chest.Round);
  40. RemainValue = arg.GetInt(gd_chest.RemainValue);
  41. RemainRound = arg.GetInt(gd_chest.RemainRound);
  42. DatabaseRoomID = arg.GetInt(gd_chest.DatabaseRoomID);
  43. Owner = arg.GetLong(gd_chest.Owner);
  44. ActivatedTime = DateUtil.GetTimeFromSeconds(arg.GetLong(gd_chest.ActivatedTime).ToString());
  45. ChestType = (ChestType) arg.GetInt(gd_chest.Type);
  46. Vector3 defaultPosition = DefaultPosition + ChestOffset;
  47. if (arg.ContainsKey(gd_chest.Position))
  48. {
  49. string vectorStr = arg.GetUtfString(gd_chest.Position);
  50. if (vectorStr == "null")
  51. {
  52. Position = defaultPosition;
  53. }
  54. else
  55. {
  56. Position = arg.GetUtfString(gd_chest.Position).ToVector() + ChestOffset;
  57. }
  58. }
  59. else
  60. {
  61. Position = defaultPosition;
  62. }
  63. }
  64. private static void Initialize()
  65. {
  66. Initialized = true;
  67. DefaultPosition = ResourceManager.Get(PlazaRoomLabel.PlazaRoomChestPos).position;
  68. }
  69. }
  70. public class ChestOperateData
  71. {
  72. public long ChestID;
  73. public bool Received;
  74. public int DatabaseRoomID;
  75. public int? RemainGuessAmt;
  76. public DateTime? LastActivatedTime; //只有系统宝箱才用
  77. public ChestOperateData(string str)
  78. {
  79. string[] strings = str.Split('|');
  80. ChestID = long.Parse(strings[0]);
  81. DatabaseRoomID = int.Parse(strings[1]);
  82. Received = int.Parse(strings[2]).ToBool();
  83. if (strings.Length > 3)
  84. {
  85. RemainGuessAmt = int.Parse(strings[3]);
  86. }
  87. if (strings.Length > 4)
  88. {
  89. LastActivatedTime = DateTime.Parse(strings[4]);
  90. }
  91. }
  92. public ChestOperateData(bool received, long chestID, int databaseRoomID)
  93. {
  94. Received = received;
  95. ChestID = chestID;
  96. DatabaseRoomID = databaseRoomID;
  97. }
  98. public override string ToString()
  99. {
  100. StringBuilder stringBuilder = new StringBuilder();
  101. stringBuilder.Append(ChestID);
  102. stringBuilder.Append("|" + DatabaseRoomID);
  103. stringBuilder.Append("|" + Received.ToInt());
  104. if (RemainGuessAmt != null)
  105. {
  106. stringBuilder.Append("|" + RemainGuessAmt);
  107. }
  108. if (LastActivatedTime != null)
  109. {
  110. stringBuilder.Append("|" + LastActivatedTime);
  111. }
  112. return stringBuilder.ToString();
  113. }
  114. }
  115. public class ChestManager : Regist
  116. {
  117. #region Config
  118. public static int PlayerMaxGuessAmt = 3;
  119. private static Text Create_DescriptionText;
  120. private static Text Create_ButtonText;
  121. private static Text Create_SliderValueText;
  122. private static Slider Create_RoundSlider;
  123. private static Button Create_Button;
  124. private static InputField Create_InputField;
  125. private static Button GuessButton;
  126. private static InputField GuessInputField;
  127. public static List<PlazaRoomChest> PlazaRoomChests = new List<PlazaRoomChest>();
  128. public static List<int> RefundRoomIDs = new List<int>();
  129. public static Dictionary<long, ChestOperateData> OperateDataDictionary = new Dictionary<long, ChestOperateData>();
  130. #endregion
  131. public override void FirstInit()
  132. {
  133. XmlNodeList RefundNodes = ConfigManager.ConfigRootNode.SelectNodes(PlayerConfigLabel.RefundNode);
  134. XmlNodeList ReceivedNodes = ConfigManager.ConfigRootNode.SelectNodes(PlayerConfigLabel.ReceivedNode);
  135. for (int i = 0; i < RefundNodes.Count; i++)
  136. {
  137. RefundRoomIDs.Add(int.Parse(RefundNodes[i].InnerText));
  138. }
  139. for (int i = 0; i < ReceivedNodes.Count; i++)
  140. {
  141. ChestOperateData chestOperateData = new ChestOperateData(ReceivedNodes[i].InnerText);
  142. OperateDataDictionary.Add(chestOperateData.ChestID, chestOperateData);
  143. }
  144. CheckRefund();
  145. GetChestExpireStatus();
  146. }
  147. public override void RegistReference()
  148. {
  149. Create_Button = ResourceManager.Get<Button>(CanvasLabel.Yb_Btn);
  150. GuessButton = ResourceManager.Get<Button>(CanvasLabel.Y_Btn);
  151. Create_DescriptionText = ResourceManager.Get<Text>(CanvasLabel.Yb_Desc);
  152. Create_RoundSlider = ResourceManager.Get<Slider>(CanvasLabel.Yb_Slider);
  153. Create_ButtonText = ResourceManager.Get<Text>(CanvasLabel.Yb_BtnLab);
  154. Create_InputField = ResourceManager.Get<InputField>(CanvasLabel.Yb_InputField);
  155. GuessInputField = ResourceManager.Get<InputField>(CanvasLabel.Y_InputField);
  156. Create_SliderValueText = ResourceManager.Get<Text>(CanvasLabel.Yb_SliderValueLab);
  157. GuessInputField.onValueChanged.AddListener(OnGuessInputValueChange);
  158. OnGuessInputValueChange(null);
  159. }
  160. public static void OnGuessInputValueChange(string value)
  161. {
  162. if (string.IsNullOrEmpty(value))
  163. {
  164. GuessButton.image.material = Lib.GrayMat;
  165. GuessButton.interactable = false;
  166. }
  167. else
  168. {
  169. GuessButton.image.material = null;
  170. GuessButton.interactable = true;
  171. }
  172. }
  173. public static void OpenCreateChestPanel()
  174. {
  175. ResourceManager.Get(CanvasLabel.Y_Chest).TweenForCG();
  176. ResourceManager.SetActive(CanvasLabel.Ya_GetAward, false);
  177. ResourceManager.SetActive(CanvasLabel.Y_Guess, false);
  178. ResourceManager.SetActive(CanvasLabel.Yb_CreateChest, true);
  179. OnSliderValueChange(Create_RoundSlider.value);
  180. OnInputValueChange(Create_InputField.text);
  181. Create_RoundSlider.value = 1;
  182. Create_RoundSlider.maxValue = SFSManager.GardenSmartFox.PlazaRoomController.CurrentRoomData.MaxPlayer;
  183. }
  184. public static void CloseCreateChestPanel()
  185. {
  186. ResourceManager.Get(CanvasLabel.Y_Chest).TweenBacCG();
  187. }
  188. public static void OnLuckyToggle(bool enable)
  189. {
  190. if (enable)
  191. {
  192. ChestType = ChestType.Lucky;
  193. LanguageManager.Add(Create_DescriptionText, new MulLanStr(LanguageLabel.UI__Yb_LuckyDesc));
  194. }
  195. }
  196. public static void OnColorToggle(bool enable)
  197. {
  198. if (enable)
  199. {
  200. ChestType = ChestType.GuessColor;
  201. LanguageManager.Add(Create_DescriptionText, new MulLanStr(LanguageLabel.UI__Yb_GuessColorDesc));
  202. }
  203. }
  204. public static void OnNumberToggle(bool enable)
  205. {
  206. if (enable)
  207. {
  208. ChestType = ChestType.GuessNumber;
  209. LanguageManager.Add(Create_DescriptionText, new MulLanStr(LanguageLabel.UI__Yb_GuessNumberDesc));
  210. }
  211. }
  212. public static void OnInputValueChange(string value)
  213. {
  214. if (string.IsNullOrEmpty(value) || int.Parse(value) < 20)
  215. {
  216. Create_Button.interactable = false;
  217. Create_Button.image.material = Lib.GrayMat;
  218. LanguageManager.Add(Create_ButtonText, new MulLanStr(LanguageLabel.UI__Yb_Minimum));
  219. return;
  220. }
  221. Cost = int.Parse(value);
  222. ResourceManager.SetText(CanvasLabel.Yb_CostLab, Language.GetStr(LanguageLabel.UI__AA_Cost) + TransferLabel.DiamondSprite + Cost);
  223. if (Manager.Diamond < Cost)
  224. {
  225. Create_Button.interactable = false;
  226. Create_Button.image.material = Lib.GrayMat;
  227. LanguageManager.Add(Create_ButtonText, new MulLanStr(LanguageLabel.Common__ShortDiamond));
  228. }
  229. else
  230. {
  231. Create_Button.interactable = true;
  232. Create_Button.image.material = null;
  233. LanguageManager.Add(Create_ButtonText, new MulLanStr(LanguageLabel.Common__Confirm));
  234. }
  235. }
  236. public static void OnSliderValueChange(float value)
  237. {
  238. Round = (int) value;
  239. Create_SliderValueText.text = Round + Language.GetStr(LanguageLabel.UI__Yb_SliderValueLab);
  240. }
  241. private static int Cost;
  242. private static int Round;
  243. private static float ChestXMinOffset = 1;
  244. private static float ChestXMaxOffset = 2;
  245. private static ChestType ChestType = ChestType.Lucky;
  246. public static void CreateChest()
  247. {
  248. LanguageManager.Add(ResourceManager.Get<Text>(CanvasLabel.Y_Tip), new MulLanStr(LanguageLabel.UI__AA_SendRequest));
  249. ResourceManager.Get(CanvasLabel.Y_Tip).TweenForCG();
  250. int databaseRoomID = SFSManager.GardenSmartFox.PlazaRoomController.CurrentRoomData.ID;
  251. long serialNumber = long.Parse(HttpManager.SerialNumber);
  252. Vector3 position = PlayerPosToChestPos(SFSManager.PlazaRoomController.SelfInstance.Player.transform.position);
  253. SFSManager.PlazaRoomEvent.CreateChest(Round, Cost, ChestType, databaseRoomID, serialNumber, position);
  254. ResourceManager.Get<CanvasGroup>(CanvasLabel.Y_Chest).interactable = false;
  255. }
  256. public static Vector3 PlayerPosToChestPos(Vector3 playerPos)
  257. {
  258. return playerPos + Mathf.Sign(Random.Range(-1f, 1f))*new Vector3(Random.Range(ChestXMinOffset, ChestXMaxOffset), 0, 0);
  259. }
  260. public static void OnCreateChestError()
  261. {
  262. LanguageManager.Add(ResourceManager.Get<Text>(CanvasLabel.Y_Tip), new MulLanStr(LanguageLabel.UI__AA_CreateError));
  263. ResourceManager.Get(CanvasLabel.Y_Tip).TweenBacCG();
  264. ResourceManager.Get<CanvasGroup>(CanvasLabel.Y_Chest).interactable = true;
  265. }
  266. public static void OnCreateChestSucceed()
  267. {
  268. Manager.CreateChestAmt++;
  269. if (ChestType == ChestType.Lucky)
  270. {
  271. Manager.CreateLuckyChestAmt++;
  272. }
  273. else if (ChestType == ChestType.GuessColor)
  274. {
  275. Manager.CreateGuessColorChestAmt++;
  276. }
  277. else if (ChestType == ChestType.GuessNumber)
  278. {
  279. Manager.CreateGuessNumberChestAmt++;
  280. }
  281. LanguageManager.Add(ResourceManager.Get<Text>(CanvasLabel.Y_Tip), new MulLanStr(LanguageLabel.UI__AA_CreateSucceed));
  282. ResourceManager.Get(CanvasLabel.Y_Tip).TweenBacCG();
  283. ResourceManager.Get<CanvasGroup>(CanvasLabel.Y_Chest).interactable = true;
  284. Manager.AddDiamond(-Cost, StaticsManager.ItemID.创建宝箱, StaticsManager.ConsumeModule.Charge);
  285. CloseCreateChestPanel();
  286. }
  287. public static void OnReceiveNewChest(ChestData chestData)
  288. {
  289. if (!SFSManager.PlazaRoomController.JoinedPlazaRoom)
  290. {
  291. return;
  292. }
  293. AudioManager.PlayClip(AudioLabel.Bubble);
  294. InstantiateChest(chestData);
  295. if (chestData.Owner == long.Parse(HttpManager.SerialNumber))
  296. {
  297. if (SFSManager.PlazaRoomController.CurrentRoomData.ID != ChestData.SystemRoomDatabaseID)
  298. {
  299. RefundRoomIDs.UniqueAdd(SFSManager.PlazaRoomController.CurrentRoomData.ID);
  300. }
  301. }
  302. }
  303. private static void CheckRefund()
  304. {
  305. if (RefundRoomIDs.Count == 0)
  306. {
  307. return;
  308. }
  309. else
  310. {
  311. SFSManager.PlazaRoomEvent.CheckChestRefund(RefundRoomIDs);
  312. }
  313. }
  314. private static void GetChestExpireStatus()
  315. {
  316. if (OperateDataDictionary.Keys.Count == 0)
  317. {
  318. return;
  319. }
  320. SFSManager.PlazaRoomEvent.GetChestExpireStatus(OperateDataDictionary.Keys.ToList());
  321. }
  322. public static void OnReceiveChestExpireStatus(List<long> chestIDs)
  323. {
  324. foreach (var chestID in chestIDs)
  325. {
  326. //Debug.LogWarning("expire " + chestID);
  327. OperateDataDictionary.Remove(chestID);
  328. }
  329. }
  330. public static void RetrieveAllChest()
  331. {
  332. foreach (var plazaRoomChest in PlazaRoomChests)
  333. {
  334. plazaRoomChest.RetriveChest();
  335. }
  336. PlazaRoomChests = new List<PlazaRoomChest>();
  337. }
  338. private static void InstantiateChest(ChestData chestData)
  339. {
  340. if (chestData.ChestType != ChestType.System)
  341. {
  342. if (chestData.RemainRound <= 0 || chestData.RemainValue <= 0)
  343. {
  344. return;
  345. }
  346. ChestOperateData chestOperateData;
  347. OperateDataDictionary.TryGetValue(chestData.ID, out chestOperateData);
  348. if (chestOperateData == null || chestOperateData.Received == false)
  349. {
  350. PlazaRoomChest chest = ResourceManager.GetPlazaRoomChest(chestData.Position);
  351. chest.Init(chestData);
  352. PlazaRoomChests.Add(chest);
  353. if (chestOperateData == null || chestOperateData.RemainGuessAmt == null || chestOperateData.RemainGuessAmt > 0)
  354. {
  355. chest.Active();
  356. chest.TurnNormalColor();
  357. }
  358. else
  359. {
  360. chest.Deactive();
  361. chest.TurnGray();
  362. }
  363. }
  364. }
  365. else
  366. {
  367. PlazaRoomChest chest = ResourceManager.GetPlazaRoomChest(chestData.Position);
  368. chest.SystemChestInit(chestData);
  369. PlazaRoomChests.Add(chest);
  370. }
  371. }
  372. private static int SystemChestActivateTimespan = 600;
  373. public static void ReceiveAllChestData(List<ChestData> chestDatas)
  374. {
  375. AudioManager.PlayClip(AudioLabel.Bubble);
  376. foreach (var chestData in chestDatas)
  377. {
  378. InstantiateChest(chestData);
  379. }
  380. }
  381. public static void ActivateSystemChest(DateTime activatedTime)
  382. {
  383. if (!SFSManager.GardenSmartFox.PlazaRoomController.JoinedPlazaRoom)
  384. {
  385. return;
  386. }
  387. if (PlazaRoomChest.SystemChest == null)
  388. {
  389. return;
  390. }
  391. if (OperateDataDictionary.Keys.Contains(PlazaRoomChest.SystemChest.ChestData.ID))
  392. {
  393. double timeSinceLastActivated = activatedTime.Subtract(OperateDataDictionary[PlazaRoomChest.SystemChest.ChestData.ID].LastActivatedTime.Value).TotalSeconds;
  394. if (timeSinceLastActivated >= SystemChestActivateTimespan)
  395. {
  396. ReactivateSystemChest(activatedTime);
  397. }
  398. return;
  399. }
  400. PlazaRoomChest.SystemChest.Active();
  401. PlazaRoomChest.SystemChest.TurnNormalColor();
  402. PlazaRoomChest.SystemChest.ChestTimerTransform.TweenBacCG();
  403. }
  404. public static void ReactivateSystemChest(DateTime activatedTime)
  405. {
  406. if (!SFSManager.GardenSmartFox.PlazaRoomController.JoinedPlazaRoom)
  407. {
  408. return;
  409. }
  410. if (PlazaRoomChest.SystemChest == null)
  411. {
  412. return;
  413. }
  414. OperateDataDictionary.Remove(PlazaRoomChest.SystemChest.ChestData.ID);
  415. PlazaRoomChest.SystemChest.Active();
  416. PlazaRoomChest.SystemChest.TurnNormalColor();
  417. PlazaRoomChest.SystemChest.ChestTimerTransform.TweenBacCG();
  418. PlazaRoomChest.SystemChest.LastActivatedTime = activatedTime;
  419. }
  420. public static void DeactivateSystemChest(long pasttime)
  421. {
  422. if (!SFSManager.GardenSmartFox.PlazaRoomController.JoinedPlazaRoom)
  423. {
  424. return;
  425. }
  426. if (PlazaRoomChest.SystemChest == null)
  427. {
  428. return;
  429. }
  430. PlazaRoomChest.SystemChest.Deactive();
  431. PlazaRoomChest.SystemChest.TurnGray();
  432. PlazaRoomChest.SystemChest.ChestRefreshTimer = PlazaRoomChest.SystemChest.ChestRefreshTime - pasttime + 1;
  433. }
  434. public static void ReceiveChestAward(int award, long chestID)
  435. {
  436. ChestOperateData chestOperateData;
  437. if (OperateDataDictionary.TryGetValue(chestID, out chestOperateData))
  438. {
  439. chestOperateData.Received = true;
  440. }
  441. else
  442. {
  443. chestOperateData = new ChestOperateData(true, PlazaRoomChest.SelectedChest.ChestData.ID, PlazaRoomChest.SelectedChest.ChestData.DatabaseRoomID);
  444. OperateDataDictionary.Add(chestOperateData.ChestID, chestOperateData);
  445. }
  446. ResourceManager.Get<CanvasGroup>(CanvasLabel.Y_Chest).interactable = true;
  447. if (award <= 0)
  448. {
  449. ResourceManager.Get(CanvasLabel.Y_Chest).TweenBacCG();
  450. Bubble.Show(null, Language.GetStr(LanguageLabel.UI__Y_SoldOut));
  451. }
  452. else
  453. {
  454. AudioManager.PlayClip(AudioLabel.GetCurrent);
  455. ResourceManager.Get(CanvasLabel.Y_Chest).TweenForCG();
  456. ResourceManager.SetActive(CanvasLabel.Ya_GetAward, true);
  457. ResourceManager.SetActive(CanvasLabel.Y_Guess, false);
  458. ResourceManager.SetActive(CanvasLabel.Yb_CreateChest, false);
  459. ResourceManager.SetText(CanvasLabel.Ya_Desc, $"x{award}");
  460. Manager.AddDiamond(award, StaticsManager.ItemID.获得钻石, StaticsManager.ConsumeModule.RoomChestAward);
  461. Manager.GetChestAwardAmt++;
  462. }
  463. for (int i = 0; i < PlazaRoomChests.Count; i++)
  464. {
  465. if (PlazaRoomChests[i].ChestData.ID == chestID)
  466. {
  467. if (PlazaRoomChests[i].ChestData.ChestType == ChestType.System)
  468. {
  469. PlazaRoomChests[i].ResetChestRefreshTimer();
  470. OperateDataDictionary[chestID].RemainGuessAmt = 0;
  471. OperateDataDictionary[chestID].LastActivatedTime = PlazaRoomChests[i].LastActivatedTime;
  472. }
  473. else
  474. {
  475. PlazaRoomChests[i].RetriveChest();
  476. PlazaRoomChests.RemoveAt(i--);
  477. }
  478. }
  479. }
  480. }
  481. public static void ReceiveChestRefund(int refund, List<int> databaseRoomIDs)
  482. {
  483. foreach (var databaseRoomID in databaseRoomIDs)
  484. {
  485. RefundRoomIDs.Remove(databaseRoomID);
  486. }
  487. if (refund > 0)
  488. {
  489. Manager.AddDiamond(refund, StaticsManager.ItemID.获得钻石, StaticsManager.ConsumeModule.RoomChestRefund);
  490. InfoBoxManager.GardenInfoBox.Display(Language.GetStr(LanguageLabel.UI__Y_Refund)+refund, 10, Color.white, ResourceManager.LoadSprite("Atlas", Folder.Atlas));
  491. }
  492. }
  493. public static void SaveToConfig()
  494. {
  495. ClearRefundAndOperateData(ConfigManager.ConfigRootNode);
  496. foreach (var id in RefundRoomIDs)
  497. {
  498. XmlNode node = ConfigManager.ConfigDocument.CreateNode(XmlNodeType.Element, PlayerConfigLabel.RefundNode, null);
  499. node.InnerText = id.ToString();
  500. ConfigManager.ConfigRootNode.AppendChild(node);
  501. }
  502. foreach (var kv in OperateDataDictionary)
  503. {
  504. XmlNode node = ConfigManager.ConfigDocument.CreateNode(XmlNodeType.Element, PlayerConfigLabel.ReceivedNode, null);
  505. node.InnerText = kv.Value.ToString();
  506. ConfigManager.ConfigRootNode.AppendChild(node);
  507. //Debug.LogWarning($"{kv.Key}|{kv.Value}");
  508. }
  509. }
  510. public static void ClearRefundAndOperateData(XmlNode playerConfigNode)
  511. {
  512. XmlNode node = playerConfigNode.SelectSingleNode(PlayerConfigLabel.RefundNode);
  513. while (node != null)
  514. {
  515. playerConfigNode.RemoveChild(node);
  516. node = playerConfigNode.SelectSingleNode(PlayerConfigLabel.RefundNode);
  517. }
  518. node = playerConfigNode.SelectSingleNode(PlayerConfigLabel.ReceivedNode);
  519. while (node != null)
  520. {
  521. playerConfigNode.RemoveChild(node);
  522. node = playerConfigNode.SelectSingleNode(PlayerConfigLabel.ReceivedNode);
  523. }
  524. }
  525. }