/// export {}; (function () { if (main.mode !== 'play' || main.replayChecking) return; /** * 发送请求 * @param {string} url * @param {string} type * @param {string} data * @returns {Promise} */ async function post(url, type, data) { const xhr = new XMLHttpRequest(); xhr.open(type, url); xhr.send(data); const res = await new Promise(res => { xhr.onload = () => { if (xhr.status !== 200) { console.error(`hot reload: http ${xhr.status}`); res('@error'); } else res('success'); }; xhr.onerror = () => { res('@error'); console.error(`hot reload: error on connection`); }; }); if (res === 'success') return xhr.response; else return '@error'; } /** * 热重载css * @param {string} data */ function reloadCss(data) { const css = document.getElementById('mota-css'); css.remove(); const link = document.createElement('link'); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = data; link.id = 'mota-css'; document.head.appendChild(link); console.log(`css hot reload: ${data}`); } /** * 热重载楼层 * @param {string} data */ async function reloadFloor(data) { // 如果被砍层了直接忽略 if ( core.status.maps[data].deleted || core.status.maps[data].forceDelete ) return; // 首先重新加载main.floors对应的楼层 await import(`/project/floors/${data}.js?v=${Date.now()}`); // 然后写入core.floors并解析 core.floors[data] = main.floors[data]; const floor = core.loadFloor(data); if (core.isPlaying()) { core.status.maps[data] = floor; delete core.status.mapBlockObjs[data]; core.extractBlocks(data); if (data === core.status.floorId) { core.drawMap(data); let weather = core.getFlag('__weather__', null); if (!weather && core.status.thisMap.weather) weather = core.status.thisMap.weather; if (weather) core.setWeather(weather[0], weather[1]); else core.setWeather(); } core.updateStatusBar(true, true); } console.log(`floor hot reload: ${data}`); } /** * 热重载脚本编辑 * @param {string} data */ async function reloadScript() { // 脚本编辑略微麻烦点 const before = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a; // 这里不能用动态导入,因为动态导入会变成模块,变量就不是全局的了 const script = document.createElement('script'); script.src = `/project/functions.js?v=${Date.now()}`; document.body.appendChild(script); await new Promise(res => { script.onload = () => res('success'); }); const after = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a; // 找到差异的函数 for (const mod in before) { const fns = before[mod]; for (const id in fns) { const fn = fns[id]; if (typeof fn !== 'function' || id === 'hasSpecial') continue; const now = after[mod][id]; if (fn.toString() !== now.toString()) { try { if (mod === 'events') { core.events.eventdata[id] = now; } else if (mod === 'enemys') { core.enemys.enemydata[id] = now; } else if (mod === 'actions') { core.actions.actionsdata[id] = now; } else if (mod === 'control') { core.control.controldata[id] = now; } else if (mod === 'ui') { core.ui.uidata[id] = now; } core.updateStatusBar(true, true); console.log(`function hot reload: ${mod}.${id}`); } catch (e) { console.error(e); } } } } } async function reloadPlugin(data) { // 直接import就完事了 await import(`/project/plugin/${data}.js?v=${Date.now()}`); console.log(`plugin hot reload: ${data}.js`); } /** * 属性热重载,包括全塔属性等 * @param {string} data */ async function reloadData(data) { const script = document.createElement('script'); script.src = `/project/${data}.js?v=${Date.now()}`; document.body.appendChild(script); await new Promise(res => { script.onload = () => res('success'); }); let after; if (data === 'data') after = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d; if (data === 'enemys') after = enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80; if (data === 'icons') after = icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1; if (data === 'items') after = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a; if (data === 'maps') after = maps_90f36752_8815_4be8_b32b_d7fad1d0542e; if (data === 'events') after = events_c12a15a8_c380_4b28_8144_256cba95f760; if (data === 'enemys') { core.enemys.enemys = after; for (var enemyId in after) { core.enemys.enemys[enemyId].id = enemyId; } core.material.enemys = core.getEnemys(); } else if (data === 'icons') { core.icons.icons = after; core.material.icons = core.getIcons(); } else if (data === 'items') { core.items.items = after; for (var itemId in after) { core.items.items[itemId].id = itemId; } core.material.items = core.getItems(); } else if (data === 'maps') { core.maps.blocksInfo = after; core.status.mapBlockObjs = {}; core.status.number2block = {}; Object.values(core.status.maps).forEach(v => delete v.blocks); core.extractBlocks(); core.setWeather( core.animateFrame.weather.type, core.animateFrame.weather.level ); core.drawMap(); } else if (data === 'events') { core.events.commonEvent = after.commonEvent; } else if (data === 'data') { location.reload(); } core.updateStatusBar(true, true); console.log(`data hot reload: ${data}`); } // 初始化 (async function () { const data = await post('/reload', 'POST', 'test'); if (data === '@error') { console.log(`未检测到node服务,热重载插件将无法使用`); } else { console.log(`热重载插件加载成功`); // reload setInterval(async () => { const res = await post('/reload', 'POST'); if (res === '@error') return; if (res === 'true') location.reload(); else return; }, 1000); // hot reload setInterval(async () => { const res = await post('/hotReload', 'POST'); const data = res.split('@@'); data.forEach(v => { if (v === '') return; const [type, file] = v.split(':'); if (type === 'css') reloadCss(file); if (type === 'data') reloadData(file); if (type === 'floor') reloadFloor(file); if (type === 'script') reloadScript(file); if (type === 'plugin') reloadPlugin(file); }); }, 1000); } })(); })();