FormBotTest.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. 
  2. using DeepCore;
  3. using DeepCore.Reflection;
  4. using DeepCore.Xml;
  5. using DeepEditor.Common.G2D;
  6. using DeepMMO.Client.BotTest.Runner;
  7. using DeepMMO.Client.Win32.Battle;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.ComponentModel;
  11. using System.Drawing;
  12. using System.Text;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. using System.Windows.Forms;
  16. namespace DeepMMO.Client.BotTest
  17. {
  18. public partial class FormBotTest : Form
  19. {
  20. private static bool first_start = true;
  21. private int lastIndex = 0;
  22. private long last_update_time;
  23. private BotConfig config;
  24. private bool started = false;
  25. public FormBotTest(BotConfig cfg)
  26. {
  27. this.config = cfg;
  28. InitializeComponent();
  29. InitBotModules();
  30. }
  31. public BotListViewItem SelectedBotItem
  32. {
  33. get
  34. {
  35. if (list_Bots.SelectedItems.Count > 0)
  36. {
  37. return list_Bots.SelectedItems[0] as BotListViewItem;
  38. }
  39. return null;
  40. }
  41. }
  42. public BotListViewItem[] SelectedBotItems
  43. {
  44. get
  45. {
  46. return list_Bots.SelectedItems.ToArray<BotListViewItem>();
  47. }
  48. }
  49. private void FormBotTest_Load(object sender, EventArgs e)
  50. {
  51. if (config.NoBattleView)
  52. {
  53. splitContainer2.Panel1Collapsed = true;
  54. }
  55. }
  56. private void FormBotTest_Shown(object sender, EventArgs e)
  57. {
  58. if (BotLauncher.IsAuto && first_start)
  59. {
  60. first_start = false;
  61. StartBots(BotLauncher.DefaultBotPrefix, BotLauncher.DefaultBotCount);
  62. }
  63. }
  64. private void FormBotTest_FormClosing(object sender, FormClosingEventArgs e)
  65. {
  66. foreach (BotListViewItem item in list_Bots.Items)
  67. {
  68. try
  69. {
  70. item.Runner.Dispose();
  71. }
  72. catch (Exception err)
  73. {
  74. Console.WriteLine(err.Message);
  75. }
  76. }
  77. }
  78. private void btn_GC_Click(object sender, EventArgs e)
  79. {
  80. System.GC.Collect();
  81. }
  82. private void timer_30_Tick(object sender, EventArgs e)
  83. {
  84. //if (base.Visible)
  85. {
  86. long curTime = DeepCore.CUtils.CurrentTimeMS;
  87. if (last_update_time == 0)
  88. {
  89. last_update_time = curTime;
  90. }
  91. int intervalMS = (int)(curTime - last_update_time);
  92. last_update_time = curTime;
  93. intervalMS = Math.Min(intervalMS, timer_30.Interval * 2);
  94. foreach (BotListViewItem item in list_Bots.Items)
  95. {
  96. item.Update(intervalMS);
  97. }
  98. }
  99. var selected = SelectedBotItem;
  100. if (text_Events.Tag != selected)
  101. {
  102. text_Events.Tag = selected;
  103. text_Events.Clear();
  104. }
  105. if (selected != null)
  106. {
  107. if (text_Events.TextLength < selected.Events.Length)
  108. {
  109. char[] copyto = new char[selected.Events.Length - text_Events.TextLength];
  110. selected.Events.CopyTo(text_Events.TextLength, copyto, 0, copyto.Length);
  111. text_Events.AppendText(new string(copyto));
  112. }
  113. if (text_Events.TextLength > selected.Events.Length)
  114. {
  115. text_Events.Clear();
  116. }
  117. }
  118. }
  119. private void timer_3000_Tick(object sender, EventArgs e)
  120. {
  121. long totalRecvBytes = 0;
  122. long totalSentBytes = 0;
  123. foreach (var item in list_Bots.Items.ToArray<BotListViewItem>())
  124. {
  125. item.Refresh();
  126. totalRecvBytes += item.Client.GameClient.TotalRecvBytes;
  127. totalSentBytes += item.Client.GameClient.TotalSentBytes;
  128. if (config.KeepBotCount > 0)
  129. {
  130. if (item.Runner.IsDisposed)
  131. {
  132. try { list_Bots.Items.Remove(item); } catch { }
  133. }
  134. else if (item.Runner.Client.IsGameDisconnected)
  135. {
  136. try { item.Runner.Dispose(); } catch { }
  137. }
  138. }
  139. }
  140. if (started && config.KeepBotCount > 0 && list_Bots.Items.Count < config.KeepBotCount)
  141. {
  142. StartBots(BotLauncher.DefaultBotPrefix, config.KeepBotCount - list_Bots.Items.Count, true);
  143. }
  144. this.lbl_NetStatus.Text = string.Format("TotalRecv={0} TotalSent={1}",
  145. CUtils.ToBytesSizeString(totalRecvBytes),
  146. CUtils.ToBytesSizeString(totalSentBytes));
  147. this.Text = "BotTest : (" + list_Bots.Items.Count + ")";
  148. }
  149. private void btn_AddBots_Click(object sender, EventArgs e)
  150. {
  151. StartBots();
  152. }
  153. private void btn_StopAll_Click(object sender, EventArgs e)
  154. {
  155. foreach (BotListViewItem item in list_Bots.Items)
  156. {
  157. try
  158. {
  159. item.Runner.Stop();
  160. }
  161. catch (Exception err)
  162. {
  163. Console.WriteLine(err.Message);
  164. }
  165. }
  166. }
  167. private void btn_CleanBots_Click(object sender, EventArgs e)
  168. {
  169. for (int i = list_Bots.Items.Count - 1; i >= 0; --i)
  170. {
  171. try
  172. {
  173. BotListViewItem item = list_Bots.Items[i] as BotListViewItem;
  174. if (item.Client.IsGameDisconnected)
  175. {
  176. list_Bots.Items.RemoveAt(i);
  177. try { item.Runner.Dispose(); } catch { }
  178. }
  179. }
  180. catch (Exception err)
  181. {
  182. Console.WriteLine(err.Message);
  183. }
  184. }
  185. }
  186. private void btn_ClearConsole_Click(object sender, EventArgs e)
  187. {
  188. text_Events.Clear();
  189. var selected = SelectedBotItem;
  190. if (selected != null)
  191. {
  192. selected.Events.Clear();
  193. }
  194. }
  195. private void btn_ClearAllConsole_Click(object sender, EventArgs e)
  196. {
  197. text_Events.Clear();
  198. foreach (BotListViewItem item in list_Bots.Items)
  199. {
  200. item.Events.Clear();
  201. }
  202. }
  203. private void list_Bots_SelectedIndexChanged(object sender, EventArgs e)
  204. {
  205. splitContainer2.Panel1.Controls.Clear();
  206. var selected = SelectedBotItem;
  207. if (selected != null && selected.BattleView != null)
  208. {
  209. splitContainer2.Panel1.Controls.Add(selected.BattleView);
  210. }
  211. }
  212. private void moduleItem_CheckedChanged(object sender, EventArgs e)
  213. {
  214. var item = sender as ToolStripMenuItem;
  215. var mt = item.Tag as Type;
  216. BotModule.SetModuleEnable(mt, item.Checked);
  217. SaveBotModules();
  218. }
  219. private void group_Module_Click(object sender, EventArgs e)
  220. {
  221. }
  222. private void menu_BotItem_Opening(object sender, CancelEventArgs e)
  223. {
  224. var menu = sender as ContextMenuStrip;
  225. if (menu != null)
  226. {
  227. var mp = menu.PointToScreen(new Point(0, 0));
  228. var lp = list_Bots.PointToClient(mp);
  229. var item = list_Bots.GetItemAt(lp.X, lp.Y);
  230. if (item != null)
  231. {
  232. item.Selected = true;
  233. var selected = SelectedBotItem;
  234. if (selected == null)
  235. {
  236. e.Cancel = true;
  237. }
  238. }
  239. else
  240. {
  241. e.Cancel = true;
  242. }
  243. }
  244. }
  245. private void btn_BotReconnect_Click(object sender, EventArgs e)
  246. {
  247. foreach (var bot in SelectedBotItems)
  248. {
  249. bot.Runner.Reconnect();
  250. }
  251. }
  252. private void btn_BotStart_Click(object sender, EventArgs e)
  253. {
  254. foreach (var bot in SelectedBotItems)
  255. {
  256. bot.Runner.Start();
  257. }
  258. }
  259. private void btn_BotStop_Click(object sender, EventArgs e)
  260. {
  261. foreach (var bot in SelectedBotItems)
  262. {
  263. bot.Runner.Stop();
  264. }
  265. }
  266. private void btn_EmuDisconnect_Click(object sender, EventArgs e)
  267. {
  268. foreach (var bot in SelectedBotItems)
  269. {
  270. bot.Runner.Disconnect();
  271. }
  272. }
  273. //-------------------------------------------------------------------------------------------------------------
  274. #region OP
  275. private void StartBots(string name_prefix = null, int count = 1, bool keep = false)
  276. {
  277. var add = AddBotConfig.TryLoadAddConfig();
  278. if (name_prefix != null)
  279. {
  280. add.name_format = name_prefix;
  281. add.count = count;
  282. add.index = lastIndex;
  283. }
  284. else
  285. {
  286. var servers = RPGClientTemplateManager.Instance.GetAllServers();
  287. var servers_optionals = new DeepEditor.Common.G2D.DataGrid.OptionalList();
  288. servers_optionals.AddRange(servers);
  289. servers_optionals.Converter = new Func<System.Reflection.MemberInfo, object, object>((field, value) =>
  290. {
  291. if (value is Data.ServerInfo server)
  292. return server.id;
  293. return value;
  294. });
  295. add.index = lastIndex;
  296. if (keep == false)
  297. {
  298. var dialog = new G2DPropertyDialog<AddBotConfig>(add);
  299. {
  300. dialog.Text = "1";
  301. dialog.PropertyGrid.SelectedDescriptorObject.AppendOptionals(nameof(AddBotConfig.serverID), servers_optionals);
  302. var res = dialog.ShowDialog();
  303. if (res == System.Windows.Forms.DialogResult.OK)
  304. {
  305. add = dialog.SelectedObject;
  306. }
  307. else
  308. {
  309. return;
  310. }
  311. }
  312. }
  313. else
  314. {
  315. add.count = count;
  316. }
  317. // add = G2DPropertyDialog<AddBotConfig>.Show("1", add);
  318. }
  319. if (add != null)
  320. {
  321. try
  322. {
  323. if (add.name_format.Contains("{0}") && !string.IsNullOrEmpty(add.digit_format))
  324. {
  325. var starting = new List<BotListViewItem>();
  326. for (int i = 0; i < add.count; i++)
  327. {
  328. var id = add.index + i;
  329. var name = string.Format(add.name_format, id.ToString(add.digit_format));
  330. var item = new BotListViewItem(name, id, add, config);
  331. list_Bots.Items.Add(item);
  332. starting.Add(item);
  333. }
  334. Task.Run(async () =>
  335. {
  336. foreach (var e in starting)
  337. {
  338. if (config.AddBotIntervalMS > 0)
  339. {
  340. await Task.Delay(config.AddBotIntervalMS);
  341. }
  342. this.Invoke(new Action(()=>
  343. {
  344. e.Runner.Start();
  345. }));
  346. }
  347. }).ConfigureAwait(true);
  348. }
  349. else
  350. {
  351. var name = add.name_format;
  352. var item = new BotListViewItem(name, lastIndex, add, config);
  353. list_Bots.Items.Add(item);
  354. item.Runner.Start();
  355. }
  356. }
  357. catch (Exception err)
  358. {
  359. MessageBox.Show(err.Message);
  360. }
  361. this.started = true;
  362. this.lastIndex = add.index + add.count;
  363. if (keep == false)
  364. {
  365. AddBotConfig.TrySaveAddConfig(add);
  366. }
  367. }
  368. }
  369. private void InitBotModules()
  370. {
  371. try
  372. {
  373. var saved = XmlUtil.LoadXML(Application.StartupPath + "/bot_modules.save");
  374. if (saved != null)
  375. {
  376. var cfg = XmlUtil.XmlToObject<BotModulesConfig>(saved);
  377. foreach (var me in cfg.Modules)
  378. {
  379. var mt = ReflectionUtil.GetType(me.Key);
  380. if (mt != null)
  381. {
  382. BotModule.SetModuleEnable(mt, me.Value);
  383. }
  384. }
  385. }
  386. }
  387. catch (Exception err)
  388. {
  389. MessageBox.Show(err.Message);
  390. }
  391. foreach (var mt in BotFactory.Instance.GetModuleTypes())
  392. {
  393. var enable = BotModule.GetModuleEnable(mt);
  394. var item = new ToolStripMenuItem();
  395. item.CheckOnClick = true;
  396. item.Size = new System.Drawing.Size(152, 22);
  397. item.Text = "模块:" + mt.Name;
  398. item.Tag = mt;
  399. item.Checked = enable;
  400. item.CheckedChanged += moduleItem_CheckedChanged;
  401. group_Module.DropDownItems.Add(item);
  402. }
  403. }
  404. private void SaveBotModules()
  405. {
  406. BotModulesConfig cfg = new BotModulesConfig();
  407. foreach (var mt in BotFactory.Instance.GetModuleTypes())
  408. {
  409. cfg.Modules.Add(mt.FullName, BotModule.GetModuleEnable(mt));
  410. }
  411. var save = XmlUtil.ObjectToXml(cfg);
  412. XmlUtil.SaveXML(Application.StartupPath + "/bot_modules.save", save);
  413. }
  414. #endregion
  415. }
  416. public class BotGamePanelContainer : GamePanelContainer
  417. {
  418. private readonly BotRunner bot;
  419. public BotGamePanelContainer(BotRunner bot)
  420. {
  421. this.bot = bot;
  422. }
  423. protected override void Client_OnErrorResponse(Protocol.Response rsp, Exception err = null)
  424. {
  425. var prefix = (rsp != null) ? (rsp.GetType().Name + " : " + rsp + Environment.NewLine) : "";
  426. var suffix = (err != null) ? (err.Message + Environment.NewLine + err.StackTrace) : "";
  427. bot.LogEvents.Error(prefix + suffix);
  428. }
  429. protected override void Client_OnError(Exception err)
  430. {
  431. bot.LogEvents.Error(err.Message + Environment.NewLine + err.StackTrace);
  432. }
  433. }
  434. public class BotListViewItem : ListViewItem
  435. {
  436. public RPGClient Client { get; private set; }
  437. public BotRunner Runner { get; private set; }
  438. public StringBuilder Events { get; private set; }
  439. public GamePanelContainer BattleView { get; private set; }
  440. public BotListViewItem(string name, int index, AddBotConfig add, BotConfig cfg)
  441. : base(name)
  442. {
  443. lock (this)
  444. {
  445. var bot = BotFactory.Instance.CreateBotRunner(cfg, add, name);
  446. this.Client = bot.Client;
  447. this.Runner = bot;
  448. this.Events = new StringBuilder();
  449. this.Runner.Client.IsAutoUpdateBattle = true;
  450. if (cfg.NoBattleView == false)
  451. {
  452. this.BattleView = new BotGamePanelContainer(bot);
  453. this.BattleView.AutoUpdateBattleClient = false;
  454. this.BattleView.Init(this.Client);
  455. this.BattleView.Dock = DockStyle.Fill;
  456. }
  457. this.Tag = bot;
  458. var colums = bot.Columns;
  459. for (int i = 1; i < colums.Length; i++)
  460. {
  461. this.SubItems.Add(colums[i]);
  462. }
  463. }
  464. }
  465. public void Update(int intervalMS)
  466. {
  467. lock (this)
  468. {
  469. if (BattleView != null)
  470. {
  471. Runner.Update(intervalMS);
  472. BattleView.UpdateBattle(intervalMS);
  473. }
  474. else
  475. {
  476. Runner.Update(intervalMS);
  477. }
  478. }
  479. }
  480. public void Refresh()
  481. {
  482. lock (this)
  483. {
  484. if (Events.Length > 10000)
  485. {
  486. Events.Clear();
  487. }
  488. using (var list = CollectionObjectPool<string>.AllocList())
  489. {
  490. this.Runner.PopLogs(list);
  491. foreach (var e in list)
  492. {
  493. Events.AppendLine(e);
  494. }
  495. }
  496. var colums = Runner.Columns;
  497. for (int i = 1; i < colums.Length; i++)
  498. {
  499. if (this.SubItems[i].Text != colums[i])
  500. this.SubItems[i].Text = colums[i];
  501. }
  502. if (Client.GameClient.IsConnected == false)
  503. {
  504. this.ForeColor = Color.Gray;
  505. }
  506. else
  507. {
  508. this.ForeColor = Color.Black;
  509. }
  510. }
  511. }
  512. }
  513. }