From 8ec41d634abf17bb60fb90205b5e06028b953513 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 28 Feb 2023 19:53:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E7=83=AD=E9=87=8D=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/project/plugin/hotReload.js | 100 +++++-------- public/server.cjs | 222 +++++------------------------ 2 files changed, 77 insertions(+), 245 deletions(-) diff --git a/public/project/plugin/hotReload.js b/public/project/plugin/hotReload.js index 51019ba..f46cb44 100644 --- a/public/project/plugin/hotReload.js +++ b/public/project/plugin/hotReload.js @@ -81,79 +81,56 @@ } /** - * 热重载脚本编辑及插件编写 + * 热重载脚本编辑 * @param {string} data */ - async function reloadScript(data) { - if (data === 'plugins') { - // 插件编写比较好办 - const before = plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1; - // 这里不能用动态导入,因为动态导入会变成模块,变量就不是全局的了 - const script = document.createElement('script'); - script.src = `/project/plugins.js?v=${Date.now()}`; - document.body.appendChild(script); - await new Promise(res => { - script.onload = () => res('success'); - }); - const after = plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1; - // 找到差异的函数 - for (const id in before) { - const fn = before[id]; - if (typeof fn !== 'function') continue; - if (fn.toString() !== after[id]?.toString()) { + 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 { - core.plugin[id] = after[id]; - core.plugin[id].call(core.plugin); + 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(`plugin hot reload: ${id}`); + console.log(`function hot reload: ${mod}.${id}`); } catch (e) { console.error(e); } } } - } else if (data === 'functions') { - // 脚本编辑略微麻烦点 - 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 @@ -239,6 +216,7 @@ if (type === 'data') reloadData(file); if (type === 'floor') reloadFloor(file); if (type === 'script') reloadScript(file); + if (type === 'plugin') reloadPlugin(file); }); }, 1000); } diff --git a/public/server.cjs b/public/server.cjs index b4dee5f..1f8dd35 100644 --- a/public/server.cjs +++ b/public/server.cjs @@ -44,6 +44,7 @@ next(); let repStart; const listenedFloors = []; +const listenedPlugins = []; // ----- GET file @@ -172,6 +173,7 @@ async function writeFile(req, res) { const value = /&value=[^]+/.exec(data)[0].slice(7); await fs.writeFile(dir, value, { encoding: type }); testWatchFloor(name); + testWatchPlugin(name); if (name.endsWith('project/events.js')) doDeclaration('events', value); if (name.endsWith('project/items.js')) doDeclaration('items', value); if (name.endsWith('project/maps.js')) doDeclaration('maps', value); @@ -332,7 +334,7 @@ async function watch() { watchOneFloor(v.slice(15)); }); - // 脚本编辑 及 插件 热重载 + // 脚本编辑 热重载 const scripts = await extract('project/functions.js', 'project/plugins.js'); scripts.forEach(v => { const dir = path.resolve(__dirname, v); @@ -343,6 +345,12 @@ async function watch() { }); }); + // 插件热重载 + const plugins = await extract('project/plugin/*.js'); + plugins.forEach(v => { + watchOnePlugin(v.slice(15)); + }); + // 数据热重载 const datas = (await extract('project/*.js')).filter( v => !v.endsWith('functions.js') && !v.endsWith('plugins.js') @@ -370,6 +378,19 @@ function testWatchFloor(url) { } } +/** + * 检测是否是楼层文件并进行监听 + * @param {string} url 要测试的路径 + */ +function testWatchPlugin(url) { + if (/project(\/|\\)plugin(\/|\\).*\.js/.test(url)) { + const f = url.slice(15); + if (!listenedFloors.includes(f.slice(0, -3))) { + watchOnePlugin(f); + } + } +} + /** * 监听一个楼层文件 * @param {string} file 要监听的文件 @@ -386,6 +407,22 @@ function watchOneFloor(file) { }); } +/** + * 监听一个楼层文件 + * @param {string} file 要监听的文件 + */ +function watchOnePlugin(file) { + if (!/.*\.js/.test(file)) return; + const f = file.slice(0, -3); + listenedFloors.push(file.slice(0, -3)); + fss.watchFile(`project/plugin/${file}`, { interval: 500 }, () => { + const plugin = f; + if (hotReloadData.includes(`@@plugin:${plugin}`)) return; + hotReloadData += `@@plugin:${plugin}`; + console.log(`plugin hot reload: ${plugin}`); + }); +} + /** * 修改部分文件后重新加载及热重载 * @param {http.IncomingMessage} req @@ -411,189 +448,6 @@ function reload(req, res, hot = false) { }); } -// ----- replay debugger - -/** - * 录像调试 - * @param {http.IncomingMessage} req - * @param {http.ServerResponse & {req: http.IncomingMessage;}} res - */ -function replay(req, res) { - req.on('data', async chunk => { - if (chunk.toString() === 'test' && !replayed) { - replayed = true; - try { - await fs.mkdir(path.resolve(__dirname, '_replay')); - await fs.mkdir(path.resolve(__dirname, '_replay/status')); - await fs.mkdir(path.resolve(__dirname, '_replay/save')); - } catch {} - - try { - await fs.readFile( - path.resolve(__dirname, '_replay/.info'), - 'utf-8' - ); - } catch { - await fs.writeFile( - path.resolve(__dirname, '_replay/.info'), - `{ - "cnt": 0 -}`, - 'utf-8' - ); - } - const data = fss.readFileSync( - path.resolve(__dirname, '_replay/.info'), - 'utf-8' - ); - repStart = Number(JSON.parse(data).cnt); - console.log(`服务器录像调试模块已开始服务`); - } - }); - - req.on('end', () => { - res.end(); - }); -} - -/** - * 获取未占用的状态栏位 - * @param {http.IncomingMessage} req - * @param {http.ServerResponse & {req: http.IncomingMessage;}} res - */ -async function replayCnt() { - const data = `{ - "cnt": ${++repStart} -}`; - fss.writeFileSync(path.resolve(__dirname, '_replay/.info'), data, 'utf-8'); - - return repStart; -} - -/** - * 写入 - * @param {http.IncomingMessage} req - * @param {http.ServerResponse & {req: http.IncomingMessage;}} res - */ -async function replayWrite(req, res) { - const data = await getPostData(req); - const n = await replayCnt(); - - if (isNaN(n)) res.end('@error'); - - await Promise.all([ - fs.writeFile( - path.resolve(__dirname, '_replay/.info'), - `{ - "cnt": ${n + 1} -}`, - 'utf-8' - ), - fs.writeFile( - path.resolve(__dirname, `_replay/status/${n}.rep`), - data, - 'utf-8' - ) - ]); - - res.end(n.toString()); -} - -/** - * 比对录像与本地数据 - * @param {http.IncomingMessage} req - * @param {http.ServerResponse & {req: http.IncomingMessage;}} res - */ -async function replayCheck(req, res) { - const ans = await getPostData(req); - const [n, data] = ans.split('@-|-@'); - - const local = ( - await fs.readFile( - path.resolve(__dirname, `_replay/status/${n}.rep`), - 'utf-8' - ) - ) - .split('@---@') - .map(v => JSON.parse(v)); - const rep = data.split('@---@').map(v => JSON.parse(v)); - - if (local.length !== rep.length) return res.end('false'); - - const check = (a, b) => { - if (a === b) return true; - if (typeof a !== typeof b) return false; - if (typeof a === 'object' && a !== null) { - for (const j in a) { - if (j === 'statistics' || j === 'timeout') continue; // 忽略统计信息 - const aa = a[j]; - const bb = b[j]; - if (!check(aa, bb)) { - return false; - } - } - return true; - } - if ( - typeof a === 'boolean' || - typeof a === 'number' || - typeof a === 'string' || - typeof a === 'symbol' || - typeof a === 'undefined' || - typeof a === 'bigint' || - a === null - ) { - return a === b; - } - return true; - }; - - for (let i = 0; i < local.length; i++) { - const a = local[i]; - const b = rep[i]; - if (!check(a, b)) return res.end('false'); - } - - res.end('true'); -} - -/** - * 获取本地属性 - * @param {http.IncomingMessage} req - * @param {http.ServerResponse & {req: http.IncomingMessage;}} res - */ -async function replayGet(req, res, dir) { - const ans = Number(await getPostData(req)); - - const data = await fs.readFile( - path.resolve(__dirname, `_replay/${dir}/${ans}.rep`) - ); - res.end(data); -} - -/** - * 录像回放存档 - * @param {http.IncomingMessage} req - * @param {http.ServerResponse & {req: http.IncomingMessage;}} res - */ -async function replaySave(req, res) { - const data = await getPostData(req); - const [cnt, save] = data.split('@-|-@'); - - if (isNaN(Number(cnt))) { - console.log('Invalid input of save cnt'); - res.end('@error: 不合法的录像存档信息'); - } - - await fs.writeFile( - path.resolve(__dirname, `_replay/save/${cnt}.rep`), - save, - 'utf-8' - ); - - res.end('success'); -} - // ----- declaration /**