HumanBreak/public/project/plugin/hotReload.js
2023-02-28 17:49:34 +08:00

246 lines
9.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
(function () {
if (main.mode !== 'play' || main.replayChecking) return;
/**
* 发送请求
* @param {string} url
* @param {string} type
* @param {string} data
* @returns {Promise<string>}
*/
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(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()) {
try {
core.plugin[id] = after[id];
core.plugin[id].call(core.plugin);
core.updateStatusBar(true, true);
console.log(`plugin hot reload: ${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);
}
}
}
}
}
}
/**
* 属性热重载,包括全塔属性等
* @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);
});
}, 1000);
}
})();
})();