webtools_old.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <html lang="zh">
  2. <head>
  3. <meta charset="utf-8">
  4. <title>Grasscutters 网页控制台</title>
  5. <meta name="viewport" content="width=device-width">
  6. <meta name="apple-mobile-web-app-capable" content="yes">
  7. <meta name="apple-mobile-web-app-status-bar-style" content="black">
  8. <meta name="viewport"
  9. content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=5,user-scalable=yes"/>
  10. <link rel="stylesheet" href="css/mui.min.css">
  11. <script src="js/mui.min.js"></script>
  12. <script type="text/javascript" src="js/cheat.js"></script>
  13. <script type="text/javascript" src="js/cheat/item_data.js"></script>
  14. <script type="text/javascript" src="js/cheat/data.js"></script>
  15. <script type="text/javascript" src="js/cheat/quickcommand.js"></script>
  16. <script type="text/javascript" src="js/cheat/weapon.js"></script>
  17. <script type="text/javascript" src="js/cheat/avatar.js"></script>
  18. <script type="text/javascript" src="js/cheat/reli.js"></script>
  19. <script type="text/javascript" src="js/cheat/item.js"></script>
  20. <script type="text/javascript" src="js/cheat/monster.js"></script>
  21. <script type="text/javascript" src="js/cheat/scene.js"></script>
  22. <script type="text/javascript" src="js/cheat/quest.js"></script>
  23. <script type="text/javascript" src="js/qrcode.min.js"></script>
  24. <style>
  25. .hidden {
  26. display: none;
  27. }
  28. </style>
  29. <header class="mui-bar mui-bar-nav">
  30. <h1 class="mui-title">Grasscutters 网页工具箱</h1>
  31. </header>
  32. </head>
  33. <body>
  34. <div class="mui-content">
  35. <div class="mui-card" style="margin-bottom: 35px;">
  36. <div class="mui-card-header">扫描二维码也可以打开这个页面</div>
  37. <div id="qrcode"></div>
  38. </div>
  39. <div class="mui-card" style="margin-bottom: 35px;">
  40. <div class="mui-card-header">在线玩家 <br>传送前请先刷新一下列表
  41. <button type="button" data-loading-text="请稍后" class="mui-btn mui-btn-primary mui-btn-outlined"
  42. onclick="updatePlayerList()">刷新
  43. </button>
  44. </div>
  45. <ul class="mui-table-view" id="id-player-list">
  46. </ul>
  47. </div>
  48. <div class="mui-card" style="margin-bottom: 35px;">
  49. <div class="mui-card-header">传送点列表
  50. <button type="button" data-loading-text="请稍后" class="mui-btn mui-btn-outlined" onclick="addTransfer()">添加
  51. </button>
  52. <button type="button" data-loading-text="请稍后" class="mui-btn mui-btn-primary mui-btn-outlined"
  53. onclick="updateTransferList()">刷新
  54. </button>
  55. <button type="button" data-loading-text="请稍后" class="mui-btn mui-btn-danger mui-btn-outlined"
  56. onclick="delAllTransfer()">全部删除
  57. </button>
  58. </div>
  59. <ul class="mui-table-view" id="id-Transfer-list">
  60. </ul>
  61. </div>
  62. <div class="container">
  63. <div class="toolset">
  64. <div class="mui-card">
  65. <form class="mui-input-group">
  66. <div class="mui-input-row mui-radio">
  67. <label for='tab-1'>常用指令</label>
  68. <input id='tab-1' type='radio' name='tabgroupB' checked>
  69. </div>
  70. <div class="mui-input-row mui-radio">
  71. <label for='tab-2'>角色</label>
  72. <input id='tab-2' type='radio' name='tabgroupB'>
  73. </div>
  74. <div class="mui-input-row mui-radio">
  75. <label for='tab-3'>武器</label>
  76. <input id='tab-3' type='radio' name='tabgroupB'>
  77. </div>
  78. <div class="mui-input-row mui-radio">
  79. <label for='tab-4'>圣遗物</label>
  80. <input id='tab-4' type='radio' name='tabgroupB'>
  81. </div>
  82. <div class="mui-input-row mui-radio">
  83. <label for='tab-5'>道具</label>
  84. <input id='tab-5' type='radio' name='tabgroupB'>
  85. </div>
  86. <div class="mui-input-row mui-radio">
  87. <label for='tab-6'>怪物</label>
  88. <input id='tab-6' type='radio' name='tabgroupB'>
  89. </div>
  90. <div class="mui-input-row mui-radio">
  91. <label for='tab-7'>场景</label>
  92. <input id='tab-7' type='radio' name='tabgroupB'>
  93. </div>
  94. <div class="mui-input-row mui-radio">
  95. <label for='tab-8'>任务</label>
  96. <input id='tab-8' type='radio' name='tabgroupB'>
  97. </div>
  98. </form>
  99. </div>
  100. </div>
  101. </div>
  102. <div id="panel" class="mui-card" style="margin-bottom: 35px;">
  103. </div>
  104. </div>
  105. <script>
  106. mui.init();
  107. function getQueryVariable(variable) {
  108. const query = window.location.search.substring(1);
  109. const vars = query.split("&");
  110. for (let i = 0; i < vars.length; i++) {
  111. const pair = vars[i].split("=");
  112. if (pair[0] === variable) {
  113. return pair[1];
  114. }
  115. }
  116. return false;
  117. }
  118. let ServerAddress = getQueryVariable("server");
  119. let ServerKey = getQueryVariable("key");
  120. if (ServerAddress !== false) {
  121. //URL解码
  122. ServerAddress = decodeURIComponent(ServerAddress);
  123. console.log(ServerAddress);
  124. }
  125. if (ServerAddress === false || ServerKey === false) {
  126. mui.prompt("请输入服务器连接地址", "服务器连接地址", "提示", ["连接"], function (e) {
  127. const server_address = e.value;
  128. if (server_address.indexOf("ws://") < 0 && server_address.indexOf("wss://") < 0) {
  129. mui.alert("服务器地址不正确", "连接失败", "刷新", function () {
  130. location.reload();
  131. });
  132. } else {
  133. ServerAddress = server_address;
  134. }
  135. mui.prompt("请输入连接码", "连接码", "提示", ["连接"], function (e) {
  136. const server_key = e.value;
  137. if (server_key.length !== 8) {
  138. mui.alert("连接码不正确", "连接失败", "刷新", function () {
  139. location.reload();
  140. });
  141. } else {
  142. ServerKey = server_key;
  143. ContentServer();
  144. }
  145. });
  146. });
  147. } else {
  148. ContentServer();
  149. }
  150. var ws;
  151. function updatePlayerList() {
  152. sendCommand("0", "Player");
  153. }
  154. function updateTransferList() {
  155. sendCommand("0", "TPMList");
  156. }
  157. function delAllTransfer() {
  158. //询问是否删除
  159. mui.confirm("确定删除所有传送点?", "删除传送点", ["确定", "取消"], function (e) {
  160. if (e.index === 0) {
  161. sendCommand("tpm delall yes");
  162. updateTransferList();
  163. }
  164. });
  165. }
  166. function addTransfer() {
  167. mui.prompt("请输入传送点名称", "添加传送点", "提示", ["取消", "确定"], function (e) {
  168. if (e.index === 1) {
  169. const name = e.value;
  170. if (name.length === 0) {
  171. mui.alert("传送点名称不能为空", "添加失败", "确定", function () {
  172. });
  173. } else {
  174. sendCommand("tpm add " + name);
  175. updateTransferList();
  176. }
  177. }
  178. });
  179. }
  180. //心跳检测防止与服务器断开连接
  181. var heartCheck = {
  182. timeout: 10000, //10秒发一次心跳
  183. timeoutObj: null,
  184. serverTimeoutObj: null,
  185. reset: function () {
  186. clearTimeout(this.timeoutObj);
  187. clearTimeout(this.serverTimeoutObj);
  188. return this;
  189. },
  190. start: function () {
  191. this.timeoutObj = setTimeout(function () {
  192. updatePlayerList();
  193. updateTransferList();
  194. }, this.timeout)
  195. }
  196. }
  197. function deal_onmessage(event) {
  198. heartCheck.reset().start();
  199. const server_msg = JSON.parse(event.data);
  200. switch (server_msg['eventName']) {
  201. case 'error':
  202. mui.alert(server_msg['data'], "错误", "确定", function () {
  203. });
  204. break;
  205. case "auth":
  206. if (server_msg['data'] !== "连接成功") {
  207. mui.alert(server_msg['data'], "连接失败", "刷新", function () {
  208. location.reload();
  209. });
  210. }
  211. break;
  212. case "success":
  213. mui.toast(server_msg['data']);
  214. break;
  215. case 'TPMList':
  216. var tpm_list = server_msg['data'];
  217. var tpm_list_html = "";
  218. for (let i = 0; i < tpm_list.length; i++) {
  219. var tpm_list_data = tpm_list[i];
  220. tpm_list_html += "<li class=\"mui-table-view-cell\">\n" +
  221. " <div class=\"mui-slider-cell\">\n" +
  222. " <div class=\"mui-slider-cell-right\">\n" +
  223. " <p class=\"mui-ellipsis\">传送点名称:" + tpm_list_data['Name'] + "</p>\n" +
  224. " <p class=\"mui-ellipsis\">坐标:" + tpm_list_data['pos'] + "</p>\n" +
  225. " <p class=\"mui-ellipsis\">场景:" + tpm_list_data['SceneId'] + "</p>\n" +
  226. " <p class=\"mui-ellipsis\">UID:" + tpm_list_data['uid'] + "</p>\n" +
  227. " <button type=\"button\" data-loading-text=\"请稍后\" class=\"mui-btn \" onclick=\"sendCommand('tpm go " + tpm_list_data['Name'] + "')\">传送</button>" +
  228. " <button type=\"button\" data-loading-text=\"请稍后\" class=\"mui-btn \" onclick=\"sendCommand('tpm del " + tpm_list_data['Name'] + "');updateTransferList();\">删除</button>" +
  229. " </div>\n" +
  230. " </div>\n" +
  231. " </li>";
  232. }
  233. document.getElementById("id-Transfer-list").innerHTML = tpm_list_html;
  234. break;
  235. case 'PlayerList':
  236. var player_list = server_msg['data'];
  237. //遍历玩家列表
  238. var player_list_html = "";
  239. for (let i = 0; i < player_list.length; i++) {
  240. var player_data = player_list[i];
  241. var tp_str = player_data['pos'];
  242. tp_str = tp_str.replace("(", "");
  243. tp_str = tp_str.replace(")", "");
  244. tp_str = tp_str.replace(",", "");
  245. tp_str = tp_str.replace(",", "");
  246. tp_str = "tp " + tp_str + " " + player_data['SceneId'];
  247. player_list_html += "<li class=\"mui-table-view-cell\">\n" +
  248. " <div class=\"mui-slider-cell\">\n" +
  249. " <div class=\"mui-slider-cell-right\">\n" +
  250. " <p class=\"mui-ellipsis\">UID:" + player_data['uid'] + "</p>\n" +
  251. " <p class=\"mui-ellipsis\">昵称:" + player_data['nickname'] + "</p>\n" +
  252. " <p class=\"mui-ellipsis\">签名:" + player_data['signature'] + "</p>\n" +
  253. " <p class=\"mui-ellipsis\">等级:" + player_data['Level'] + "级</p>\n" +
  254. " <p class=\"mui-ellipsis\">世界等级:" + player_data['worldLevel'] + "级</p>\n" +
  255. " <p class=\"mui-ellipsis\">等级:" + player_data['Level'] + "级</p>\n" +
  256. " <p class=\"mui-ellipsis\">坐标:" + player_data['pos'] + "</p>\n" +
  257. " <p class=\"mui-ellipsis\">场景:" + player_data['SceneId'] + "</p>\n" +
  258. " <button type=\"button\" data-loading-text=\"请稍后\" class=\"mui-btn \" onclick=\"sendCommand('" + tp_str + "')\">传送</button>" +
  259. " </div>\n" +
  260. " </div>\n" +
  261. " </li>";
  262. }
  263. document.getElementById("id-player-list").innerHTML = player_list_html;
  264. break;
  265. default:
  266. break;
  267. }
  268. }
  269. function ContentServer() {
  270. //判断server_address是否是一个有效的websocket地址
  271. try {
  272. ws = new WebSocket(ServerAddress + "?key=" + ServerKey)
  273. ws.onopen = function () {
  274. new QRCode(document.getElementById("qrcode"), {
  275. text: "https://liujiaqi7998.github.io/GrasscuttersWebDashboard/webtools.html?server=" + ServerAddress + "&key=" + ServerKey,
  276. width: 180,
  277. height: 180,
  278. //居中
  279. colorDark : "#000000",
  280. colorLight : "#ffffff",
  281. correctLevel : QRCode.CorrectLevel.H
  282. });
  283. console.log("连接成功");
  284. heartCheck.reset().start();
  285. updatePlayerList();
  286. updateTransferList();
  287. }
  288. ws.onclose = () => {
  289. mui.alert("连接已断开", "提示", "确定", function () {
  290. });
  291. };
  292. ws.onmessage = deal_onmessage;
  293. } catch (e) {
  294. mui.alert(e.message, "连接失败", "刷新", function () {
  295. location.reload();
  296. });
  297. }
  298. }
  299. function sendCommand(cmd, method = "CMD", background = false, persistent = "auto") {
  300. if (ws.readyState === WebSocket.OPEN) {
  301. try {
  302. console.log("执行命令:" + cmd);
  303. const send_msg = {
  304. "type": method,
  305. "data": cmd
  306. };
  307. const send_msg_str = JSON.stringify(send_msg);
  308. ws.send(send_msg_str);
  309. } catch (e) {
  310. console.log(e);
  311. mui.toast("发送命令失败:" + e.message);
  312. }
  313. } else {
  314. mui.toast("发送命令失败:服务器连接已断开");
  315. }
  316. }
  317. </script>
  318. </body>
  319. </html>