Merge branch 'noAnimate' into hasAnimate

This commit is contained in:
爱的天使Erdnase 2023-03-15 20:59:38 +08:00
commit b547c096a5
27 changed files with 1682 additions and 592 deletions

View File

@ -1,5 +0,0 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
IDList=
URL=https://www.bilibili.com/video/BV1SB4y1p7bg?spm_id_from=333.999.0.0

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
_server/css/FiraCode.ttf Normal file

Binary file not shown.

View File

@ -699,3 +699,12 @@ div.checkboxSet {
.etableInputDiv textarea:hover { .etableInputDiv textarea:hover {
margin: -5px; margin: -5px;
} }
@font-face {
font-family: code;
src: url(./FiraCode.ttf);
}
.main .CodeMirror {
font-family: code, 微软雅黑, 黑体, 新宋体, Verdana;
}

View File

@ -710,3 +710,11 @@ div.checkboxSet {
margin: -5px; margin: -5px;
} }
@font-face {
font-family: Fira;
src: url(./FiraCode.ttf);
}
.main .CodeMirror {
font-family: Fira, Menlo, Consolas, 'Courier New', Courier, monospace;
}

View File

@ -7,11 +7,11 @@ editor_multi = function () {
var extraKeys = { var extraKeys = {
"Ctrl-/": function (cm) { cm.toggleComment(); }, "Ctrl-/": function (cm) { cm.toggleComment(); },
"Ctrl-B": function (cm) { ternServer.jumpToDef(cm); }, "Ctrl-B": function (cm) { ternServer.jumpToDef(cm); },
"Ctrl-Q": function(cm) { ternServer.rename(cm); }, "Ctrl-Q": function (cm) { ternServer.rename(cm); },
"Cmd-F": CodeMirror.commands.findPersistent, "Cmd-F": CodeMirror.commands.findPersistent,
"Ctrl-F": CodeMirror.commands.findPersistent, "Ctrl-F": CodeMirror.commands.findPersistent,
"Ctrl-R": CodeMirror.commands.replaceAll, "Ctrl-R": CodeMirror.commands.replaceAll,
"Ctrl-D": function(cm){ cm.foldCode(cm.getCursor()); }, "Ctrl-D": function (cm) { cm.foldCode(cm.getCursor()); },
"Ctrl-O": function () { editor_multi.openUrl('/_docs/#/api'); }, "Ctrl-O": function () { editor_multi.openUrl('/_docs/#/api'); },
"Ctrl-P": function () { editor_multi.openUrl('https://h5mota.com/plugins/'); } "Ctrl-P": function () { editor_multi.openUrl('https://h5mota.com/plugins/'); }
}; };
@ -48,14 +48,14 @@ editor_multi = function () {
'Ctrl-P': '打开在线插件列表Ctrl+P' 'Ctrl-P': '打开在线插件列表Ctrl+P'
}; };
document.getElementById('codemirrorCommands').innerHTML = document.getElementById('codemirrorCommands').innerHTML =
"<option value='' selected>执行操作...</option>" + "<option value='' selected>执行操作...</option>" +
Object.keys(commandsName).map(function (name) { Object.keys(commandsName).map(function (name) {
return "<option value='" + name + "'>" + commandsName[name] + "</option>" return "<option value='" + name + "'>" + commandsName[name] + "</option>"
}).join(''); }).join('');
var coredef = terndefs_f6783a0a_522d_417e_8407_94c67b692e50[2]; var coredef = terndefs_f6783a0a_522d_417e_8407_94c67b692e50[2];
Object.keys(core.material.enemys).forEach(function (name){ Object.keys(core.material.enemys).forEach(function (name) {
coredef.core.material.enemys[name] = { coredef.core.material.enemys[name] = {
"!type": "enemy", "!type": "enemy",
"!doc": core.material.enemys[name].name || "怪物" "!doc": core.material.enemys[name].name || "怪物"
@ -236,7 +236,15 @@ editor_multi = function () {
document.getElementById('left7').style = 'z-index:-1;opacity: 0;'; document.getElementById('left7').style = 'z-index:-1;opacity: 0;';
} }
editor_multi.setLint = function () { editor_multi.setLint = function () {
codeEditor.setOption("lint", editor_multi.lintAutocomplete); if (editor_multi.lintAutocomplete) {
codeEditor.setOption("lint", {
options: {
esversion: 2021
}
});
} else {
codeEditor.setOption("lint", false);
}
codeEditor.setOption("autocomplete", editor_multi.lintAutocomplete); codeEditor.setOption("autocomplete", editor_multi.lintAutocomplete);
document.getElementById("lintCheckbox").checked = editor_multi.lintAutocomplete; document.getElementById("lintCheckbox").checked = editor_multi.lintAutocomplete;
} }
@ -253,7 +261,7 @@ editor_multi = function () {
var _format = function () { var _format = function () {
if (!editor_multi.lintAutocomplete) return; if (!editor_multi.lintAutocomplete) return;
var offset = (codeEditor.getScrollInfo() || {}).top || 0; var offset = (codeEditor.getScrollInfo() || {}).top || 0;
_setValue(js_beautify(codeEditor.getValue(), { _setValue(beautifier.js(codeEditor.getValue(), {
brace_style: "collapse-preserve-inline", brace_style: "collapse-preserve-inline",
indent_with_tabs: true, indent_with_tabs: true,
jslint_happy: true jslint_happy: true
@ -486,6 +494,22 @@ editor_multi = function () {
editor_multi.importFile(dict[mod]) editor_multi.importFile(dict[mod])
} }
// 字体大小
{
const CONFIG_KEY = "editor_multi.fontSize";
let fontsize = editor.config.get(CONFIG_KEY, 14);
const input = document.getElementById("editor_multi_fontsize");
const check = document.getElementById("editor_multi_fontweight")
input.value = fontsize;
editor_multi.setFontSize = function () {
const value = Number(input.value);
editor.config.set(CONFIG_KEY, value);
const ele = codeEditor.getWrapperElement()
ele.style.fontSize = `${value}px`;
ele.style.fontWeight = `${check.checked ? 'bold' : 'normal'}`
}
}
return editor_multi; return editor_multi;
} }
//editor_multi=editor_multi(); //editor_multi=editor_multi();

View File

@ -555,14 +555,20 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"autoScale": { "autoScale": {
"_leaf": true, "_leaf": true,
"_type": "checkbox", "_type": "checkbox",
"_docs": "自动缩放最大化", "_docs": "自动缩放",
"_data": "是否自动缩放最大化,关闭后不再最大化" "_data": "是否自动缩放至合适值"
}, },
"extendToolbar": { "extendToolbar": {
"_leaf": true, "_leaf": true,
"_type": "checkbox", "_type": "checkbox",
"_docs": "横屏隐藏状态栏", "_docs": "画面下方道具栏",
"_data": "在横屏状态下是否隐藏左侧状态栏从而获得仿RM的沉浸式体验" "_data": "开启后道具栏会被挪动至游戏画面的下方"
},
"hideLeftStatusBar": {
"_leaf": true,
"_type": "checkbox",
"_docs": "隐藏左侧状态栏",
"_data": "是否隐藏左侧状态栏,开启后强制开启画面下方道具栏"
}, },
"flyNearStair": { "flyNearStair": {
"_leaf": true, "_leaf": true,

View File

@ -242,15 +242,21 @@
<button onclick="confirmColor()">确定</button> <button onclick="confirmColor()">确定</button>
</div> </div>
<div id="left7" style="z-index:-1;opacity: 0;"><!-- 多行文本编辑器 --> <div id="left7" style="z-index:-1;opacity: 0;"><!-- 多行文本编辑器 -->
<button onclick="editor_multi.confirm()">确认</button> <div>
<button onclick="editor_multi.cancel()">取消</button> <button onclick="editor_multi.confirm()">确认</button>
<button onclick="editor_multi.confirm(true)">应用</button> <button onclick="editor_multi.cancel()">取消</button>
<button onclick="editor_multi.format()">格式化</button> <button onclick="editor_multi.confirm(true)">应用</button>
<button id="editor_multi_preview" style="display: none;">预览</button> <button onclick="editor_multi.format()">格式化</button>
<input type="checkbox" onclick="editor_multi.toggerLint()" id="lintCheckbox" <button id="editor_multi_preview" style="display: none;">预览</button>
style="vertical-align: middle;margin-left:6px"/> <input type="checkbox" onclick="editor_multi.toggerLint()" id="lintCheckbox"
<span style="vertical-align: middle; margin-left: -3px">语法检查</span> style="vertical-align: middle;margin-left:6px"/>
<select id="codemirrorCommands" onchange="editor_multi.doCommand(this)" style="vertical-align: middle; margin-left: 6px;"></select> <span style="vertical-align: middle; margin-left: -3px">语法检查</span>
<select id="codemirrorCommands" onchange="editor_multi.doCommand(this)" style="vertical-align: middle; margin-left: 6px;"></select>
<span>字体大小</span>
<input style="width: 40px" type="number" onchange="editor_multi.setFontSize()" id="editor_multi_fontsize" />
<span>字体加粗</span>
<input style="width: 40px" type="checkbox" onchange="editor_multi.setFontSize()" id="editor_multi_fontweight" />
</div>
<textarea id="multiLineCode" name="multiLineCode"></textarea> <textarea id="multiLineCode" name="multiLineCode"></textarea>
</div> </div>
<div id="left8" class='leftTab' style="z-index:-1;opacity: 0;"><!-- functions --> <div id="left8" class='leftTab' style="z-index:-1;opacity: 0;"><!-- functions -->

View File

@ -238,15 +238,21 @@
<button onclick="confirmColor()">确定</button> <button onclick="confirmColor()">确定</button>
</div> </div>
<div id="left7" style="z-index:-1;opacity: 0;"><!-- 多行文本编辑器 --> <div id="left7" style="z-index:-1;opacity: 0;"><!-- 多行文本编辑器 -->
<button onclick="editor_multi.confirm()">确认</button> <div>
<button onclick="editor_multi.cancel()">取消</button> <button onclick="editor_multi.confirm()">确认</button>
<button onclick="editor_multi.confirm(true)">应用</button> <button onclick="editor_multi.cancel()">取消</button>
<button onclick="editor_multi.format()">格式化</button> <button onclick="editor_multi.confirm(true)">应用</button>
<button id="editor_multi_preview" style="display: none;">预览</button> <button onclick="editor_multi.format()">格式化</button>
<input type="checkbox" onclick="editor_multi.toggerLint()" id="lintCheckbox" <button id="editor_multi_preview" style="display: none;">预览</button>
style="vertical-align: middle;margin-left:6px"/> <input type="checkbox" onclick="editor_multi.toggerLint()" id="lintCheckbox"
<span style="vertical-align: middle; margin-left: -3px">语法检查</span> style="vertical-align: middle;margin-left:6px"/>
<select id="codemirrorCommands" onchange="editor_multi.doCommand(this)" style="vertical-align: middle; margin-left: 6px;"></select> <span style="vertical-align: middle; margin-left: -3px">语法检查</span>
<select id="codemirrorCommands" onchange="editor_multi.doCommand(this)" style="vertical-align: middle; margin-left: 6px;"></select>
<span>字体大小</span>
<input style="width: 40px" type="number" onchange="editor_multi.setFontSize()" id="editor_multi_fontsize" />
<span>字体加粗</span>
<input style="width: 40px" type="checkbox" onchange="editor_multi.setFontSize()" id="editor_multi_fontweight" />
</div>
<textarea id="multiLineCode" name="multiLineCode"></textarea> <textarea id="multiLineCode" name="multiLineCode"></textarea>
</div> </div>
<div id="left8" class='leftTab' style="z-index:-1;opacity: 0;"><!-- functions --> <div id="left8" class='leftTab' style="z-index:-1;opacity: 0;"><!-- functions -->

View File

@ -1,12 +1,14 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta http-equiv='content-type' content='text/html' charset='utf-8'> <meta http-equiv='content-type' content='text/html' charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=Edge, chrome=1'> <meta http-equiv='X-UA-Compatible' content='IE=Edge, chrome=1'>
<meta name='author' content='ckcz123'> <meta name='author' content='ckcz123'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=yes'> <meta name='viewport'
content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=yes'>
<title>HTML5魔塔</title> <title>HTML5魔塔</title>
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="screen-orientation" content="portrait"> <meta name="screen-orientation" content="portrait">
<meta name="full-screen" content="yes"> <meta name="full-screen" content="yes">
<meta name="browsermode" content="application"> <meta name="browsermode" content="application">
@ -20,130 +22,130 @@
<div id='startImageDiv'></div> <div id='startImageDiv'></div>
<img id='startImageLogo' /> <img id='startImageLogo' />
</div> </div>
<script> <script>
(function () { (function () {
var startImageBackgroundDiv = document.getElementById('startImageBackgroundDiv'); var startImageBackgroundDiv = document.getElementById('startImageBackgroundDiv');
var startImageLogo = document.getElementById('startImageLogo'); var startImageLogo = document.getElementById('startImageLogo');
var startImageDiv = document.getElementById('startImageDiv'); var startImageDiv = document.getElementById('startImageDiv');
startImageLogo.onload = function () { startImageLogo.onload = function () {
startImageBackgroundDiv.style.display = 'block'; startImageBackgroundDiv.style.display = 'block';
var onAnimationEnd = function () { var onAnimationEnd = function () {
startImageBackgroundDiv.style.display = 'none'; startImageBackgroundDiv.style.display = 'none';
startImageLogo.classList.remove("startImageAnimation"); startImageLogo.classList.remove("startImageAnimation");
startImageDiv.classList.remove("startImageDivAnimation"); startImageDiv.classList.remove("startImageDivAnimation");
}
startImageDiv.addEventListener("webkitAnimationEnd", onAnimationEnd);
startImageDiv.addEventListener("animationend", onAnimationEnd);
startImageLogo.classList.add("startImageAnimation");
startImageDiv.classList.add("startImageDivAnimation");
// 注释下面这句话以禁止单击立刻跳过开场动画
startImageBackgroundDiv.onclick = onAnimationEnd;
} }
startImageDiv.addEventListener("webkitAnimationEnd", onAnimationEnd); startImageLogo.onerror = function () { }
startImageDiv.addEventListener("animationend", onAnimationEnd); startImageLogo.src = "logo.png";
startImageLogo.classList.add("startImageAnimation"); })();
startImageDiv.classList.add("startImageDivAnimation"); </script>
// 注释下面这句话以禁止单击立刻跳过开场动画 <!-- injection -->
startImageBackgroundDiv.onclick = onAnimationEnd; <div id='gameGroup'>
} <canvas id="whole" style="position: absolute; left: 0; top: 0; z-index: 68;"></canvas>
startImageLogo.onerror = function () {} <p id='mainTips'>请稍候...</p>
startImageLogo.src = "logo.png"; <img id='musicBtn'>
})(); <div id='startPanel'>
</script> <div id='startTop'>
<!-- injection --> <div id='startTopProgressBar'>
<div id='gameGroup'> <div id='startTopProgress'></div>
<canvas id="whole" style="position: absolute; left: 0; top: 0; z-index: 68;"></canvas> </div>
<p id='mainTips'>请稍候...</p> <p id='startTopLoadTips'>资源即将开始加载</p>
<img id='musicBtn'> <p id='startTopHint'>HTML5魔塔游戏平台享受更多魔塔游戏<br />https://h5mota.com/</p>
<div id='startPanel'>
<div id='startTop'>
<div id='startTopProgressBar'>
<div id='startTopProgress'></div>
</div> </div>
<p id='startTopLoadTips'>资源即将开始加载</p> <img id='startBackground'>
<p id='startTopHint'>HTML5魔塔游戏平台享受更多魔塔游戏<br/>https://h5mota.com/</p> <p id='startLogo'></p>
</div> <div id='startButtonGroup'>
<img id='startBackground'> <div id='startButtons'>
<p id='startLogo'></p> <span class='startButton' id='playGame'>开始游戏</span>
<div id='startButtonGroup'> <span class='startButton' id='loadGame'>继续游戏</span>
<div id='startButtons'> <span class='startButton' id='replayGame'>录像回放</span>
<span class='startButton' id='playGame'>开始游戏</span> </div>
<span class='startButton' id='loadGame'>继续游戏</span> <div id='levelChooseButtons'></div>
<span class='startButton' id='replayGame'>录像回放</span>
</div> </div>
<div id='levelChooseButtons'></div>
</div> </div>
</div> <div id='floorMsgGroup'>
<div id='floorMsgGroup'> <p id='logoLabel'></p>
<p id='logoLabel'></p> <p id='versionLabel'></p>
<p id='versionLabel'></p> <p id='floorNameLabel'></p>
<p id='floorNameLabel'></p>
</div>
<div id='statusBar' class="clearfix">
<div class="status" id="floorCol">
<img id="img-floor">
<p class='statusLabel statusText' id='floor'></p>
</div>
<div class="status" id="nameCol">
<img id="img-name">
<p class='statusLabel statusText' id='name'></p>
</div>
<div class="status" id="lvCol">
<img id="img-lv">
<p class='statusLabel statusText' id='lv'></p>
</div>
<div class="status" id='hpmaxCol'>
<img id="img-hpmax">
<p class='statusLabel statusText' id='hpmax'></p>
</div>
<div class="status" id='hpCol'>
<img id="img-hp">
<p class='statusLabel statusText' id='hp'></p>
</div>
<div class="status" id='manaCol'>
<img id="img-mana">
<p class='statusLabel statusText' id='mana'></p>
</div>
<div class="status" id='atkCol'>
<img id="img-atk">
<p class='statusLabel statusText' id='atk'></p>
</div>
<div class="status" id='defCol'>
<img id="img-def">
<p class='statusLabel statusText' id='def'></p>
</div>
<div class="status" id="mdefCol">
<img id="img-mdef">
<p class='statusLabel statusText' id='mdef'></p>
</div>
<div class="status" id="moneyCol">
<img id="img-money">
<p class='statusLabel statusText' id='money'></p>
</div>
<div class="status" id="expCol">
<img id="img-exp">
<p class='statusLabel statusText' id='exp'></p>
</div>
<div class="status" id="upCol">
<img id="img-up">
<p class='statusLabel statusText' id='up'></p>
</div>
<div class="status" id="skillCol">
<img id="img-skill">
<p class='statusLabel statusText' id='skill' style='font-style: normal'></p>
</div>
<div class="status" id='keyCol'>
<span class='statusLabel' id='yellowKey' style="color:#FFCCAA"></span>
<span class='statusLabel' id='blueKey' style="color:#AAAADD"></span>
<span class='statusLabel' id='redKey' style="color:#FF8888"></span>
<span class='statusLabel' id='greenKey' style="color:#88FF88"></span>
</div>
<div class="status" id='pzfCol'>
<span class='statusLabel' id='pickaxe' style="color: #BC6E27"></span>
<span class='statusLabel' id='bomb' style="color: #FA14B9"></span>
<span class='statusLabel' id='fly' style="color: #8DB600"></span>
</div>
<div class="status" id="debuffCol">
<span class='statusLabel' id='poison' style="color: #AFFCA8;"></span>
<span class='statusLabel' id='weak' style="color: #FECCD0;"></span>
<span class='statusLabel' id='curse' style="color: #C2F4E7;"></span>
</div> </div>
<div id='statusBar' class="clearfix">
<div class="status" id="floorCol">
<img id="img-floor">
<p class='statusLabel statusText' id='floor'></p>
</div>
<div class="status" id="nameCol">
<img id="img-name">
<p class='statusLabel statusText' id='name'></p>
</div>
<div class="status" id="lvCol">
<img id="img-lv">
<p class='statusLabel statusText' id='lv'></p>
</div>
<div class="status" id='hpmaxCol'>
<img id="img-hpmax">
<p class='statusLabel statusText' id='hpmax'></p>
</div>
<div class="status" id='hpCol'>
<img id="img-hp">
<p class='statusLabel statusText' id='hp'></p>
</div>
<div class="status" id='manaCol'>
<img id="img-mana">
<p class='statusLabel statusText' id='mana'></p>
</div>
<div class="status" id='atkCol'>
<img id="img-atk">
<p class='statusLabel statusText' id='atk'></p>
</div>
<div class="status" id='defCol'>
<img id="img-def">
<p class='statusLabel statusText' id='def'></p>
</div>
<div class="status" id="mdefCol">
<img id="img-mdef">
<p class='statusLabel statusText' id='mdef'></p>
</div>
<div class="status" id="moneyCol">
<img id="img-money">
<p class='statusLabel statusText' id='money'></p>
</div>
<div class="status" id="expCol">
<img id="img-exp">
<p class='statusLabel statusText' id='exp'></p>
</div>
<div class="status" id="upCol">
<img id="img-up">
<p class='statusLabel statusText' id='up'></p>
</div>
<div class="status" id="skillCol">
<img id="img-skill">
<p class='statusLabel statusText' id='skill' style='font-style: normal'></p>
</div>
<div class="status" id='keyCol'>
<span class='statusLabel' id='yellowKey' style="color:#FFCCAA"></span>
<span class='statusLabel' id='blueKey' style="color:#AAAADD"></span>
<span class='statusLabel' id='redKey' style="color:#FF8888"></span>
<span class='statusLabel' id='greenKey' style="color:#88FF88"></span>
</div>
<div class="status" id='pzfCol'>
<span class='statusLabel' id='pickaxe' style="color: #BC6E27"></span>
<span class='statusLabel' id='bomb' style="color: #FA14B9"></span>
<span class='statusLabel' id='fly' style="color: #8DB600"></span>
</div>
<div class="status" id="debuffCol">
<span class='statusLabel' id='poison' style="color: #AFFCA8;"></span>
<span class='statusLabel' id='weak' style="color: #FECCD0;"></span>
<span class='statusLabel' id='curse' style="color: #C2F4E7;"></span>
</div>
<!-- 状态栏canvas化 --> <!-- 状态栏canvas化 -->
<canvas id="statusCanvas" style="position: absolute; left: 0; top: 0; z-index: 50;"></canvas> <canvas id="statusCanvas" style="position: absolute; left: 0; top: 0;"></canvas>
<canvas id="caidan1" style="position: absolute; left: 0; top: 0;"></canvas> <canvas id="caidan1" style="position: absolute; left: 0; top: 0;"></canvas>
</div> </div>
<div id="toolBar" class="clearfix"> <div id="toolBar" class="clearfix">
@ -168,11 +170,11 @@
<div id="gameDraw"> <div id="gameDraw">
<div id="gif"></div> <div id="gif"></div>
<div id="gif2"></div> <div id="gif2"></div>
<canvas class='gameCanvas' id='bg'></canvas> <canvas class='gameCanvas anti-aliasing' id='bg'></canvas>
<canvas class='gameCanvas' id='event'></canvas> <canvas class='gameCanvas anti-aliasing' id='event'></canvas>
<canvas class='gameCanvas' id='hero'></canvas> <canvas class='gameCanvas anti-aliasing' id='hero'></canvas>
<canvas class='gameCanvas' id='event2'></canvas> <canvas class='gameCanvas anti-aliasing' id='event2'></canvas>
<canvas class='gameCanvas' id='fg'></canvas> <canvas class='gameCanvas anti-aliasing' id='fg'></canvas>
<canvas class='gameCanvas' id='caidan'></canvas> <canvas class='gameCanvas' id='caidan'></canvas>
<canvas class='gameCanvas' id='damage'></canvas> <canvas class='gameCanvas' id='damage'></canvas>
<canvas class='gameCanvas' id='animate'></canvas> <canvas class='gameCanvas' id='animate'></canvas>
@ -200,4 +202,5 @@
<script>main.init('play');main.listen();</script> <script>main.init('play');main.listen();</script>
</body> </body>
</html> </html>

View File

@ -1225,7 +1225,7 @@ actions.prototype._clickBook = function (x, y) {
var data = core.status.event.data; var data = core.status.event.data;
if (data != null && y < core._HEIGHT_-1) { if (data != null && y < core._HEIGHT_-1) {
var per_page = pageinfo.per_page, page = parseInt(data / per_page); var per_page = pageinfo.per_page, page = parseInt(data / per_page);
var u = this.LAST / per_page; var u = (core._HEIGHT_ - 1) / per_page;
for (var i = 0; i < per_page; ++i) { for (var i = 0; i < per_page; ++i) {
if (y >= u * i && y < u * (i + 1)) { if (y >= u * i && y < u * (i + 1)) {
var index = per_page * page + i; var index = per_page * page + i;

View File

@ -18,6 +18,7 @@ control.prototype._init = function () {
this.weathers = {}; this.weathers = {};
this.resizes = []; this.resizes = [];
this.noAutoEvents = true; this.noAutoEvents = true;
this.updateNextFrame = false;
// --- 注册系统的animationFrame // --- 注册系统的animationFrame
this.registerAnimationFrame("totalTime", false, this._animationFrame_totalTime); this.registerAnimationFrame("totalTime", false, this._animationFrame_totalTime);
this.registerAnimationFrame("autoSave", true, this._animationFrame_autoSave); this.registerAnimationFrame("autoSave", true, this._animationFrame_autoSave);
@ -3046,22 +3047,27 @@ control.prototype.clearStatusBar = function () {
////// 更新状态栏 ////// ////// 更新状态栏 //////
control.prototype.updateStatusBar = function (doNotCheckAutoEvents, immediate) { control.prototype.updateStatusBar = function (doNotCheckAutoEvents, immediate) {
if (!core.isPlaying()) return;
if (immediate) { if (immediate) {
return this.updateStatusBar_update(); return this.updateStatusBar_update();
} }
if (!doNotCheckAutoEvents) this.noAutoEvents = false; if (!doNotCheckAutoEvents) this.noAutoEvents = false;
if (core.isReplaying()) return this.updateStatusBar_update(); if (core.isReplaying()) return this.updateStatusBar_update();
requestAnimationFrame(this.updateStatusBar_update) if (!core.control.updateNextFrame) {
} core.control.updateNextFrame = true;
requestAnimationFrame(this.updateStatusBar_update);
}
};
control.prototype.updateStatusBar_update = function () { control.prototype.updateStatusBar_update = function () {
core.control.updateNextFrame = false;
if (!core.isPlaying() || core.hasFlag('__statistics__')) return; if (!core.isPlaying() || core.hasFlag('__statistics__')) return;
core.control.controldata.updateStatusBar(); core.control.controldata.updateStatusBar();
if (!core.control.noAutoEvents) core.checkAutoEvents(); if (!core.control.noAutoEvents) core.checkAutoEvents();
core.control._updateStatusBar_setToolboxIcon(); core.control._updateStatusBar_setToolboxIcon();
core.clearRouteFolding(); core.clearRouteFolding();
core.control.noAutoEvents = true; core.control.noAutoEvents = true;
} };
control.prototype._updateStatusBar_setToolboxIcon = function () { control.prototype._updateStatusBar_setToolboxIcon = function () {
if (core.isReplaying()) { if (core.isReplaying()) {
@ -3265,9 +3271,10 @@ control.prototype.resize = function () {
var clientWidth = main.dom.body.clientWidth, clientHeight = main.dom.body.clientHeight; var clientWidth = main.dom.body.clientWidth, clientHeight = main.dom.body.clientHeight;
var BORDER = 3; var BORDER = 3;
var extendToolbar = core.flags.extendToolbar; var extendToolbar = core.flags.extendToolbar;
var BAR_WIDTH = extendToolbar ? 0 : Math.round(core._PY_ * 0.3); let hideLeftStatusBar = core.flags.hideLeftStatusBar;
var BAR_WIDTH = hideLeftStatusBar ? 0 : Math.round(core._PY_ * 0.31);
var horizontalMaxRatio = (clientHeight - 2 * BORDER - (extendToolbar ? BORDER : 0)) / (core._PY_ + (extendToolbar ? 38 : 0)); var horizontalMaxRatio = (clientHeight - 2 * BORDER - (hideLeftStatusBar ? BORDER : 0)) / (core._PY_ + (hideLeftStatusBar ? 38 : 0));
if (clientWidth - 3 * BORDER >= core._PX_ + BAR_WIDTH || (clientWidth > clientHeight && horizontalMaxRatio < 1)) { if (clientWidth - 3 * BORDER >= core._PX_ + BAR_WIDTH || (clientWidth > clientHeight && horizontalMaxRatio < 1)) {
// 横屏 // 横屏
@ -3289,6 +3296,7 @@ control.prototype.resize = function () {
core.domStyle.scale = Math.min((clientWidth - 2 * BORDER) / core._PX_); core.domStyle.scale = Math.min((clientWidth - 2 * BORDER) / core._PX_);
core.domStyle.availableScale = []; core.domStyle.availableScale = [];
extendToolbar = false; extendToolbar = false;
hideLeftStatusBar = false;
BAR_WIDTH = Math.round(core._PX_ * 0.3); BAR_WIDTH = Math.round(core._PX_ * 0.3);
} }
@ -3317,7 +3325,8 @@ control.prototype.resize = function () {
statusBarHeightInVertical: core.domStyle.isVertical ? (32 * col + 6) * core.domStyle.scale + 2 * BORDER : 0, statusBarHeightInVertical: core.domStyle.isVertical ? (32 * col + 6) * core.domStyle.scale + 2 * BORDER : 0,
toolbarHeightInVertical: core.domStyle.isVertical ? 38 * core.domStyle.scale + 2 * BORDER : 0, toolbarHeightInVertical: core.domStyle.isVertical ? 38 * core.domStyle.scale + 2 * BORDER : 0,
extendToolbar: extendToolbar, extendToolbar: extendToolbar,
is15x15: false is15x15: false,
hideLeftStatusBar
}; };
this._doResize(obj); this._doResize(obj);
@ -3339,7 +3348,7 @@ control.prototype._resize_gameGroup = function (obj) {
totalHeight = obj.outerHeight + obj.statusBarHeightInVertical + obj.toolbarHeightInVertical totalHeight = obj.outerHeight + obj.statusBarHeightInVertical + obj.toolbarHeightInVertical
} }
else { else {
totalWidth = obj.outerWidth + obj.BAR_WIDTH * core.domStyle.scale + (obj.extendToolbar ? 0 : obj.BORDER); totalWidth = obj.outerWidth + obj.BAR_WIDTH * core.domStyle.scale + (obj.hideLeftStatusBar ? 0 : obj.BORDER);
totalHeight = obj.outerHeight + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0); totalHeight = obj.outerHeight + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0);
} }
gameGroup.style.width = totalWidth + "px"; gameGroup.style.width = totalWidth + "px";
@ -3409,9 +3418,7 @@ control.prototype._resize_canvas = function (obj) {
} else { } else {
for (var name in core.dymCanvas) { for (var name in core.dymCanvas) {
var ctx = core.dymCanvas[name], canvas = ctx.canvas; var ctx = core.dymCanvas[name], canvas = ctx.canvas;
var ratio = canvas.hasAttribute('isHD') ? core.domStyle.ratio : 1; core.resizeCanvas(ctx, parseFloat(canvas.getAttribute("_width")), parseFloat(canvas.getAttribute("_height")))
canvas.style.width = canvas.width / ratio * core.domStyle.scale + "px";
canvas.style.height = canvas.height / ratio * core.domStyle.scale + "px";
canvas.style.left = parseFloat(canvas.getAttribute("_left")) * core.domStyle.scale + "px"; canvas.style.left = parseFloat(canvas.getAttribute("_left")) * core.domStyle.scale + "px";
canvas.style.top = parseFloat(canvas.getAttribute("_top")) * core.domStyle.scale + "px"; canvas.style.top = parseFloat(canvas.getAttribute("_top")) * core.domStyle.scale + "px";
} }
@ -3435,13 +3442,13 @@ control.prototype._resize_statusBar = function (obj) {
statusBar.style.height = obj.outerHeight + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px"; statusBar.style.height = obj.outerHeight + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px";
statusBar.style.background = obj.globalAttribute.statusLeftBackground; statusBar.style.background = obj.globalAttribute.statusLeftBackground;
// --- 计算文字大小 // --- 计算文字大小
if (obj.extendToolbar) { if (obj.hideLeftStatusBar) {
statusBar.style.fontSize = 16 * core.domStyle.scale + "px"; statusBar.style.fontSize = 16 * core.domStyle.scale + "px";
} else { } else {
statusBar.style.fontSize = 16 * Math.min(1, (core._HEIGHT_ - 4) / obj.count) * core.domStyle.scale + "px"; statusBar.style.fontSize = 16 * Math.min(1, (core._HEIGHT_ - 4) / obj.count) * core.domStyle.scale + "px";
} }
} }
statusBar.style.display = obj.extendToolbar ? 'none' : 'block'; statusBar.style.display = obj.hideLeftStatusBar ? 'none' : 'block';
statusBar.style.borderTop = statusBar.style.borderLeft = obj.border; statusBar.style.borderTop = statusBar.style.borderLeft = obj.border;
statusBar.style.borderRight = core.domStyle.isVertical ? obj.border : ''; statusBar.style.borderRight = core.domStyle.isVertical ? obj.border : '';
statusBar.style.borderBottom = core.domStyle.isVertical ? '' : obj.border; statusBar.style.borderBottom = core.domStyle.isVertical ? '' : obj.border;
@ -3456,7 +3463,7 @@ control.prototype._resize_statusBar = function (obj) {
core.dom.statusCanvas.style.height = obj.outerHeight - 2 * obj.BORDER + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px"; core.dom.statusCanvas.style.height = obj.outerHeight - 2 * obj.BORDER + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px";
core.maps._setHDCanvasSize(core.dom.statusCanvasCtx, obj.BAR_WIDTH, core._PY_ + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT + obj.BORDER : 0)); core.maps._setHDCanvasSize(core.dom.statusCanvasCtx, obj.BAR_WIDTH, core._PY_ + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT + obj.BORDER : 0));
} }
core.dom.statusCanvas.style.display = core.flags.statusCanvas && !obj.extendToolbar ? "block" : "none"; core.dom.statusCanvas.style.display = core.flags.statusCanvas && !obj.hideLeftStatusBar ? "block" : "none";
} }
control.prototype._resize_status = function (obj) { control.prototype._resize_status = function (obj) {
@ -3464,7 +3471,7 @@ control.prototype._resize_status = function (obj) {
if (core.domStyle.isVertical) { if (core.domStyle.isVertical) {
statusHeight = 32 * core.domStyle.scale * 0.8; statusHeight = 32 * core.domStyle.scale * 0.8;
} else { } else {
statusHeight = (obj.extendToolbar ? core._HEIGHT_ : core._HEIGHT_ - 4) / obj.count * 32 * core.domStyle.scale * 0.8; statusHeight = (obj.hideLeftStatusBar ? core._HEIGHT_ : core._HEIGHT_ - 4) / obj.count * 32 * core.domStyle.scale * 0.8;
} }
// status // status
for (var i = 0; i < core.dom.status.length; ++i) { for (var i = 0; i < core.dom.status.length; ++i) {
@ -3507,7 +3514,7 @@ control.prototype._resize_toolBar = function (obj) {
toolBar.style.background = obj.globalAttribute.toolsBackground; toolBar.style.background = obj.globalAttribute.toolsBackground;
} }
else { else {
if (obj.extendToolbar) { if (obj.extendToolbar || obj.hideLeftStatusBar) {
toolBar.style.left = ""; toolBar.style.left = "";
toolBar.style.right = 0; toolBar.style.right = 0;
toolBar.style.width = obj.outerWidth + "px"; toolBar.style.width = obj.outerWidth + "px";

View File

@ -34,11 +34,10 @@ maps.prototype._resetFloorImages = function () {
} }
} }
maps.prototype._setHDCanvasSize = function (ctx, width, height, isTempCanvas) { maps.prototype._setHDCanvasSize = function (ctx, width, height) {
ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.setTransform(1, 0, 0, 1, 0, 0);
var ratio = core.domStyle.ratio; var ratio = core.domStyle.scale;
if (ctx === core.bigmap.tempCanvas) ratio = core.domStyle.scale; ratio *= devicePixelRatio;
if (isTempCanvas) ratio = core.domStyle.ratio;
if (width != null) ctx.canvas.width = width * ratio; if (width != null) ctx.canvas.width = width * ratio;
if (height != null) ctx.canvas.height = height * ratio; if (height != null) ctx.canvas.height = height * ratio;
ctx.scale(ratio, ratio); ctx.scale(ratio, ratio);
@ -1728,18 +1727,20 @@ maps.prototype._drawThumbnail_drawTempCanvas = function (floorId, blocks, option
// 如果是大地图模式? // 如果是大地图模式?
if (options.all) { if (options.all) {
// 计算比例 // 计算比例
var scale = Math.max(core._WIDTH_ / width, core._HEIGHT_ / height);
if (options.noHD) { if (options.noHD) {
tempCanvas.canvas.width = width * 32 * scale; tempCanvas.canvas.width = width * 32;
tempCanvas.canvas.height = height * 32 * scale; tempCanvas.canvas.height = height * 32;
} else core.resizeCanvas(tempCanvas, width * 32 * scale, height * 32 * scale, false, true); tempCanvas.canvas.removeAttribute('isHD');
tempCanvas.scale(scale, scale); } else {
core.maps._setHDCanvasSize(tempCanvas, width * 32, height * 32);
}
} else if (width * height > core.bigmap.threshold) { } else if (width * height > core.bigmap.threshold) {
options.v2 = true; options.v2 = true;
if (options.noHD) { if (options.noHD) {
tempCanvas.canvas.width = core._PX_; tempCanvas.canvas.width = core._PX_;
tempCanvas.canvas.height = core._PY_; tempCanvas.canvas.height = core._PY_;
} else core.resizeCanvas(tempCanvas, core._PX_, core._PY_); tempCanvas.canvas.removeAttribute('isHD');
} else core.maps._setHDCanvasSize(tempCanvas, width * 32, height * 32);
var centerX = options.centerX, centerY = options.centerY; var centerX = options.centerX, centerY = options.centerY;
if (centerX == null) centerX = Math.floor(width / 2); if (centerX == null) centerX = Math.floor(width / 2);
if (centerY == null) centerY = Math.floor(height / 2); if (centerY == null) centerY = Math.floor(height / 2);
@ -1751,7 +1752,8 @@ maps.prototype._drawThumbnail_drawTempCanvas = function (floorId, blocks, option
if (options.noHD) { if (options.noHD) {
tempCanvas.canvas.width = width * 32; tempCanvas.canvas.width = width * 32;
tempCanvas.canvas.height = height * 32; tempCanvas.canvas.height = height * 32;
} else core.resizeCanvas(tempCanvas, width * 32, height * 32, false, true); tempCanvas.canvas.removeAttribute('isHD');
} else core.maps._setHDCanvasSize(tempCanvas, width * 32, height * 32);
} }
options.ctx = tempCanvas; options.ctx = tempCanvas;
@ -1813,6 +1815,7 @@ maps.prototype._drawThumbnail_drawToTarget = function (floorId, options) {
if (centerY == null) centerY = Math.floor(height / 2); if (centerY == null) centerY = Math.floor(height / 2);
var tempCanvas = core.bigmap.tempCanvas; var tempCanvas = core.bigmap.tempCanvas;
const scale = core.domStyle.scale * devicePixelRatio;
if (options.all) { if (options.all) {
var tempWidth = tempCanvas.canvas.width, tempHeight = tempCanvas.canvas.height; var tempWidth = tempCanvas.canvas.width, tempHeight = tempCanvas.canvas.height;
// 绘制全景图 // 绘制全景图
@ -1833,20 +1836,28 @@ maps.prototype._drawThumbnail_drawToTarget = function (floorId, options) {
} }
else { else {
// 只绘制可见窗口 // 只绘制可见窗口
var pw = core._PX_, ph = core._PY_, hw = core._HALF_WIDTH_, hh = core._HALF_HEIGHT_, W = core._WIDTH_, H = core._HEIGHT_; var pw = core._PX_,
var ratio = core.domStyle.isVertical ? core.domStyle.ratio : core.domStyle.scale; ph = core._PY_,
if (main.mode == 'editor') { pw = ph = core.__PIXELS__; hw = hh = core.__HALF_SIZE__; W = H = core.__SIZE__; } hw = core._HALF_WIDTH_,
hh = core._HALF_HEIGHT_,
W = core._WIDTH_,
H = core._HEIGHT_;
if (main.mode == 'editor') {
pw = ph = core.__PIXELS__;
hw = hh = core.__HALF_SIZE__;
W = H = core.__SIZE__;
}
if (options.v2) { if (options.v2) {
core.drawImage(ctx, tempCanvas.canvas, 0, 0, pw * ratio, ph * ratio, x, y, w, h); if (options.noHD) core.drawImage(ctx, tempCanvas.canvas, 0, 0, pw, ph, x, y, w, h);
else core.drawImage(ctx, tempCanvas.canvas, 0, 0, pw * scale, ph * scale, x, y, w, h);
} else { } else {
var offsetX = core.clamp(centerX - hw, 0, width - W), var offsetX = core.clamp(centerX - hw, 0, width - W),
offsetY = core.clamp(centerY - hh, 0, height - H), offsetY = core.clamp(centerY - hh, 0, height - H);
c = options.noHD ? 1 : core.domStyle.scale;
if (options.noHD) { if (options.noHD) {
core.drawImage(ctx, tempCanvas.canvas, offsetX * 32, offsetY * 32, pw, ph, x, y, w, h); core.drawImage(ctx, tempCanvas.canvas, offsetX * 32, offsetY * 32, pw, ph, x, y, w, h);
return; } else {
core.drawImage(ctx, tempCanvas.canvas, offsetX * 32 * scale, offsetY * 32 * scale, pw * scale, ph * scale, x, y, w, h);
} }
core.drawImage(ctx, tempCanvas.canvas, offsetX * 32 * ratio, offsetY * 32 * ratio, pw * ratio, ph * ratio, x, y, w, h);
} }
} }
} }

View File

@ -57,7 +57,13 @@ ui.prototype.clearMap = function (name, x, y, width, height) {
if (x != null && y != null && width != null && height != null) { if (x != null && y != null && width != null && height != null) {
ctx.clearRect(x, y, width, height); ctx.clearRect(x, y, width, height);
} else { } else {
ctx.clearRect(-32, -32, ctx.canvas.width + 32, ctx.canvas.height + 32); if (ctx.canvas.getAttribute('isHD')) {
const width = ctx.canvas.width / core.domStyle.scale / devicePixelRatio;
const height = ctx.canvas.height / core.domStyle.scale / devicePixelRatio;
ctx.clearRect(0, 0, width, height);
} else {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
} }
} }
} }
@ -1108,12 +1114,16 @@ ui.prototype.drawTextContent = function (ctx, content, config) {
config.offsetY = 0; config.offsetY = 0;
config.line = 0; config.line = 0;
config.blocks = []; config.blocks = [];
config.isHD = ctx != null && ctx.canvas.hasAttribute('isHD'); config.isHD = ctx == null || ctx.canvas.hasAttribute('isHD');
// 创建一个新的临时画布 // 创建一个新的临时画布
var tempCtx = document.createElement('canvas').getContext('2d'); var tempCtx = document.createElement('canvas').getContext('2d');
if (config.isHD) { if (config.isHD && ctx) {
core.maps._setHDCanvasSize(tempCtx, ctx.canvas.width, ctx.canvas.height); core.maps._setHDCanvasSize(
tempCtx,
ctx.canvas.width,
ctx.canvas.height
);
} else { } else {
tempCtx.canvas.width = ctx == null ? 1 : ctx.canvas.width; tempCtx.canvas.width = ctx == null ? 1 : ctx.canvas.width;
tempCtx.canvas.height = ctx == null ? 1 : ctx.canvas.height; tempCtx.canvas.height = ctx == null ? 1 : ctx.canvas.height;
@ -1148,10 +1158,20 @@ ui.prototype._drawTextContent_draw = function (ctx, tempCtx, content, config) {
if (config.index >= config.blocks.length) return false; if (config.index >= config.blocks.length) return false;
var block = config.blocks[config.index++]; var block = config.blocks[config.index++];
if (block != null) { if (block != null) {
var ratio = config.isHD ? core.domStyle.ratio : 1; // It works, why?
core.drawImage(ctx, tempCtx.canvas, block.left * ratio, block.top * ratio, block.width * ratio, block.height * ratio, const scale = config.isHD ? devicePixelRatio * core.domStyle.scale : 1;
config.left + block.left + block.marginLeft, config.top + block.top + block.marginTop, core.drawImage(
block.width, block.height); ctx,
tempCtx.canvas,
block.left * scale,
block.top * scale,
block.width * scale,
block.height * scale,
config.left + block.left + block.marginLeft,
config.top + block.top + block.marginTop,
block.width,
block.height
);
} }
return true; return true;
} }
@ -2512,23 +2532,24 @@ ui.prototype.drawFly = function (page) {
core.setTextAlign('ui', 'center'); core.setTextAlign('ui', 'center');
var middle = core._PY_ / 2 + 39; var middle = core._PY_ / 2 + 39;
const lastWidth = 0.25 * core._PX_ - 16;
// 换行 // 换行
var lines = core.splitLines('ui', title, 120, this._buildFont(19, true)); var lines = core.splitLines('ui', title, lastWidth, this._buildFont(19, true));
var start_y = middle - (lines.length - 1) * 11; var start_y = middle - (lines.length - 1) * 11;
for (var i in lines) { for (var i in lines) {
core.fillText('ui', lines[i], core._PX_ - 60, start_y, '#FFFFFF'); core.fillText('ui', lines[i], core._PX_ - lastWidth * 0.5, start_y, '#FFFFFF');
start_y += 22; start_y += 22;
} }
if (core.actions._getNextFlyFloor(1) != page) { if (core.actions._getNextFlyFloor(1) != page) {
core.fillText('ui', '▲', core._PX_ - 60, middle - 64, null, this._buildFont(17, false)); core.fillText('ui', '▲', core._PX_ - lastWidth * 0.5, middle - 64, null, this._buildFont(17, false));
core.fillText('ui', '▲', core._PX_ - 60, middle - 96); core.fillText('ui', '▲', core._PX_ - lastWidth * 0.5, middle - 96);
core.fillText('ui', '▲', core._PX_ - 60, middle - 96 - 7); core.fillText('ui', '▲', core._PX_ - lastWidth * 0.5, middle - 96 - 7);
} }
if (core.actions._getNextFlyFloor(-1) != page) { if (core.actions._getNextFlyFloor(-1) != page) {
core.fillText('ui', '▼', core._PX_ - 60, middle + 64, null, this._buildFont(17, false)); core.fillText('ui', '▼', core._PX_ - lastWidth * 0.5, middle + 64, null, this._buildFont(17, false));
core.fillText('ui', '▼', core._PX_ - 60, middle + 96); core.fillText('ui', '▼', core._PX_ - lastWidth * 0.5, middle + 96);
core.fillText('ui', '▼', core._PX_ - 60, middle + 96 + 7); core.fillText('ui', '▼', core._PX_ - lastWidth * 0.5, middle + 96 + 7);
} }
var size = 0.75; var size = 0.75;
core.strokeRect('ui', 16, 64, size * core._PX_, size * core._PY_, '#FFFFFF', 2); core.strokeRect('ui', 16, 64, size * core._PX_, size * core._PY_, '#FFFFFF', 2);
@ -3381,6 +3402,8 @@ ui.prototype.createCanvas = function (name, x, y, width, height, z) {
newCanvas.style.display = 'block'; newCanvas.style.display = 'block';
newCanvas.setAttribute("_left", x); newCanvas.setAttribute("_left", x);
newCanvas.setAttribute("_top", y); newCanvas.setAttribute("_top", y);
newCanvas.setAttribute("_width", width);
newCanvas.setAttribute("_height", height);
newCanvas.style.width = width * core.domStyle.scale + 'px'; newCanvas.style.width = width * core.domStyle.scale + 'px';
newCanvas.style.height = height * core.domStyle.scale + 'px'; newCanvas.style.height = height * core.domStyle.scale + 'px';
newCanvas.style.left = x * core.domStyle.scale + 'px'; newCanvas.style.left = x * core.domStyle.scale + 'px';
@ -3439,16 +3462,21 @@ ui.prototype.rotateCanvas = function (name, angle, centerX, centerY) {
} }
////// canvas重置 ////// ////// canvas重置 //////
ui.prototype.resizeCanvas = function (name, width, height, styleOnly, isTempCanvas) { ui.prototype.resizeCanvas = function (name, width, height, styleOnly) {
var ctx = core.getContextByName(name); var ctx = core.getContextByName(name);
const canvas = ctx.canvas;
if (!ctx) return null; if (!ctx) return null;
if (width != null) { if (width != null) {
if (!styleOnly) core.maps._setHDCanvasSize(ctx, width, null, isTempCanvas); if (!styleOnly && ctx.canvas.hasAttribute('isHD'))
core.maps._setHDCanvasSize(ctx, width, null);
ctx.canvas.style.width = width * core.domStyle.scale + 'px'; ctx.canvas.style.width = width * core.domStyle.scale + 'px';
canvas.setAttribute('_width', width);
} }
if (height != null) { if (height != null) {
if (!styleOnly) core.maps._setHDCanvasSize(ctx, null, height, isTempCanvas); if (!styleOnly && ctx.canvas.hasAttribute('isHD'))
core.maps._setHDCanvasSize(ctx, null, height);
ctx.canvas.style.height = height * core.domStyle.scale + 'px'; ctx.canvas.style.height = height * core.domStyle.scale + 'px';
canvas.setAttribute('_height', height);
} }
return ctx; return ctx;
} }

715
main.js

File diff suppressed because it is too large Load Diff

View File

@ -718,7 +718,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"firstData": { "firstData": {
"title": "天塔", "title": "天塔",
"name": "tianta", "name": "tianta",
"version": "Ver 2.10.0", "version": "Ver 2.10.3",
"floorId": "nandu", "floorId": "nandu",
"hero": { "hero": {
"image": "hero.png", "image": "hero.png",
@ -1595,6 +1595,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"enableMoveDirectly": true, "enableMoveDirectly": true,
"enableRouteFolding": true, "enableRouteFolding": true,
"disableShopOnDamage": false, "disableShopOnDamage": false,
"blurFg": false "blurFg": false,
"hideLeftStatusBar": false
} }
} }

View File

@ -907,6 +907,11 @@ main.floors.MT0=
"steps": [ "steps": [
"right:1" "right:1"
] ]
},
{
"type": "hide",
"remove": true,
"time": 0
} }
] ]
}, },

View File

@ -66,7 +66,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -136,7 +136,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -206,7 +206,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -276,7 +276,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -346,7 +346,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -416,7 +416,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -486,7 +486,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -556,7 +556,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -626,7 +626,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -696,7 +696,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -766,7 +766,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -836,7 +836,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -906,7 +906,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -985,7 +985,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -1450,7 +1450,7 @@ main.floors.MT16=
"opacity": 1, "opacity": 1,
"time": 0 "time": 0
}, },
"\t[杰克]这里似乎封印着类似于11层东南角的机遗迹一样的东西。", "\t[杰克]这里似乎封印着类似于11层东南角的机遗迹一样的东西。",
"\t[邵虎]..........好吧......我会注意的。", "\t[邵虎]..........好吧......我会注意的。",
{ {
"type": "hideImage", "type": "hideImage",
@ -1483,60 +1483,71 @@ main.floors.MT16=
] ]
} }
], ],
"11,7": [ "11,7": {
{ "trigger": "action",
"type": "if", "enable": true,
"condition": "(flag:xianjie2==1)", "noPass": null,
"true": [ "displayDamage": true,
{ "opacity": 1,
"type": "setBlock", "filter": {
"number": "339", "blur": 0,
"loc": [ "hue": 0,
[ "grayscale": 0,
11, "invert": false,
7 "shadow": 0
] },
] "data": [
}, {
{ "type": "if",
"type": "hide", "condition": "(flag:xianjie2==1)",
"remove": true "true": [
} {
], "type": "hide",
"false": [ "remove": true
{ }
"type": "if", ],
"condition": "(flag:xianjie==15)", "false": [
"true": [ {
{ "type": "if",
"type": "setBlock", "condition": "(flag:xianjie==15)",
"number": "89", "true": [
"loc": [ {
[ "type": "openDoor",
12, "loc": [
1 11,
7
] ]
] },
}, {
{ "type": "setBlock",
"type": "setValue", "number": "89",
"name": "flag:xianjie", "loc": [
"operator": "+=", [
"value": "1", 12,
"norefresh": true 1
}, ]
{ ]
"type": "setValue", },
"name": "flag:xianjie2", {
"operator": "+=", "type": "setValue",
"value": "1" "name": "flag:xianjie",
} "operator": "+=",
], "value": "1",
"false": [] "norefresh": true
} },
] {
} "type": "setValue",
], "name": "flag:xianjie2",
"operator": "+=",
"value": "1"
}
],
"false": []
}
]
}
]
},
"6,1": [ "6,1": [
{ {
"type": "function", "type": "function",
@ -1593,7 +1604,7 @@ main.floors.MT16=
"true": [ "true": [
{ {
"type": "setBlock", "type": "setBlock",
"number": "339", "number": "372",
"loc": [ "loc": [
[ [
11, 11,
@ -1606,7 +1617,133 @@ main.floors.MT16=
} }
] ]
} }
] ],
"8,8": {
"trigger": "action",
"enable": true,
"noPass": null,
"displayDamage": true,
"opacity": 1,
"filter": {
"blur": 0,
"hue": 0,
"grayscale": 0,
"invert": false,
"shadow": 0
},
"data": [
{
"type": "if",
"condition": "flag:112",
"true": [
{
"type": "vibrate",
"direction": "horizontal",
"time": 1000,
"speed": 10,
"power": 10,
"async": true
},
{
"type": "openDoor",
"loc": [
8,
8
]
},
{
"type": "openDoor",
"loc": [
5,
4
]
},
{
"type": "openDoor",
"loc": [
9,
4
]
},
{
"type": "openDoor",
"loc": [
5,
8
]
},
{
"type": "openDoor",
"loc": [
9,
8
]
}
],
"false": []
}
]
},
"5,4": {
"trigger": "action",
"enable": true,
"noPass": null,
"displayDamage": true,
"opacity": 1,
"filter": {
"blur": 0,
"hue": 0,
"grayscale": 0,
"invert": false,
"shadow": 0
},
"data": []
},
"5,8": {
"trigger": "action",
"enable": true,
"noPass": null,
"displayDamage": true,
"opacity": 1,
"filter": {
"blur": 0,
"hue": 0,
"grayscale": 0,
"invert": false,
"shadow": 0
},
"data": []
},
"9,4": {
"trigger": "action",
"enable": true,
"noPass": null,
"displayDamage": true,
"opacity": 1,
"filter": {
"blur": 0,
"hue": 0,
"grayscale": 0,
"invert": false,
"shadow": 0
},
"data": []
},
"9,8": {
"trigger": "action",
"enable": true,
"noPass": null,
"displayDamage": true,
"opacity": 1,
"filter": {
"blur": 0,
"hue": 0,
"grayscale": 0,
"invert": false,
"shadow": 0
},
"data": []
}
}, },
"changeFloor": { "changeFloor": {
"8,4": { "8,4": {
@ -1620,7 +1757,25 @@ main.floors.MT16=
"time": 200 "time": 200
} }
}, },
"afterBattle": {}, "afterBattle": {
"6,4": [
{
"type": "setValue",
"name": "flag:112",
"value": "true"
},
{
"type": "setBlock",
"number": "372",
"loc": [
[
8,
8
]
]
}
]
},
"afterGetItem": {}, "afterGetItem": {},
"afterOpenDoor": {}, "afterOpenDoor": {},
"cannotMove": {}, "cannotMove": {},
@ -1630,11 +1785,11 @@ main.floors.MT16=
[ 0,348,475, 0, 28, 0,475, 0, 2,475,475,218, 0,352, 0], [ 0,348,475, 0, 28, 0,475, 0, 2,475,475,218, 0,352, 0],
[ 0,348,218, 0, 2, 0, 0, 21, 2,206, 0, 0, 32,352, 0], [ 0,348,218, 0, 2, 0, 0, 21, 2,206, 0, 0, 32,352, 0],
[ 0,348, 0,475, 2, 2, 2, 2, 2, 81, 2, 2, 27,352, 0], [ 0,348, 0,475, 2, 2, 2, 2, 2, 81, 2, 2, 27,352, 0],
[ 0,348, 0,206, 81,372,213, 0, 87,372, 2,475, 31,352, 0], [ 0,348, 0,206, 81,361,213, 0, 87,361, 2,475, 31,352, 0],
[ 0,348, 2, 2, 2, 32, 0, 0, 0,206, 2, 0, 0,352, 0], [ 0,348, 2, 2, 2, 32, 0, 0, 0,206, 2, 0, 0,352, 0],
[ 0,348,475, 21, 2, 2, 2, 32, 2, 2, 2, 21,475,352, 0], [ 0,348,475, 21, 2, 2, 2, 32, 2, 2, 2, 21,475,352, 0],
[ 0,348, 0, 0, 2,206, 0, 0, 0, 32, 2, 2, 2,352, 0], [ 0,348, 0, 0, 2,206, 0, 0, 0, 32, 2, 2, 2,352, 0],
[ 0,348, 31,475, 2,372, 88,123,372,372, 81,206, 0,352, 0], [ 0,348, 31,475, 2,361, 88,123,361,361, 81,206, 0,352, 0],
[ 0,348, 27, 2, 2, 81, 2, 2, 2, 2, 2,475, 0,352, 0], [ 0,348, 27, 2, 2, 81, 2, 2, 2, 2, 2,475, 0,352, 0],
[ 0,348, 32,475, 0,206, 2, 21, 0, 0, 2,475,218,352, 0], [ 0,348, 32,475, 0,206, 2, 21, 0, 0, 2,475,218,352, 0],
[ 0,348, 0,218, 0,475, 2,475,475, 0, 28, 0, 0,352, 0], [ 0,348, 0,218, 0,475, 2,475,475, 0, 28, 0, 0,352, 0],

View File

@ -11,10 +11,20 @@ main.floors.XIANJIE=
"firstArrive": [], "firstArrive": [],
"events": { "events": {
"7,1": [ "7,1": [
{
"type": "setValue",
"name": "flag:isRMshop",
"value": "true"
},
{ {
"type": "openShop", "type": "openShop",
"id": "expShop1", "id": "expShop1",
"open": true "open": true
},
{
"type": "setValue",
"name": "flag:isRMshop",
"value": "false"
} }
] ]
}, },

View File

@ -326,12 +326,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.status.hero.exp += exp; core.status.hero.exp += exp;
core.status.hero.statistics.exp += exp; core.status.hero.statistics.exp += exp;
var hint = "打败 " + core.getEnemyValue(enemy, "name", x, y); var hint = "打败 " + core.getEnemyValue(enemy, "name", x, y);
if (core.flags.statusBarItems.indexOf('enableMoney') >= 0) if (core.flags.statusBarItems.indexOf('enableMoney') >= 0)
hint += ',' + core.getStatusLabel('money') + '+' + money; // hint += ",金币+" + money; hint += ',' + core.getStatusLabel('money') + '+' + money; // hint += ",金币+" + money;
if (core.flags.statusBarItems.indexOf('enableExp') >= 0) if (core.flags.statusBarItems.indexOf('enableExp') >= 0)
hint += ',' + core.getStatusLabel('exp') + '+' + exp; // hint += ",经验+" + exp; hint += ',' + core.getStatusLabel('exp') + '+' + exp; // hint += ",经验+" + exp;
if (!core.getFlag("isNoTip")) core.drawTip(hint, enemy.id); if (!core.getFlag("isNoTip")) core.drawTip(hint, enemy.id);
// 中毒 // 中毒
if (core.enemys.hasSpecial(special, 12)) { if (core.enemys.hasSpecial(special, 12)) {
@ -388,6 +388,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.push(todo, [{ "type": "insert", "name": "加点事件", "args": [point] }]); core.push(todo, [{ "type": "insert", "name": "加点事件", "args": [point] }]);
} }
//等待动画执行完毕
core.push(todo, [{ "type": "waitAsync" }]);
// 战后事件 // 战后事件
if (core.status.floorId != null) { if (core.status.floorId != null) {
core.push(todo, core.floors[core.status.floorId].afterBattle[x + "," + y]); core.push(todo, core.floors[core.status.floorId].afterBattle[x + "," + y]);

View File

@ -246,14 +246,14 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e =
"358": {"cls":"animates","id":"A358"}, "358": {"cls":"animates","id":"A358"},
"359": {"cls":"animates","id":"A359"}, "359": {"cls":"animates","id":"A359"},
"360": {"cls":"animates","id":"A360"}, "360": {"cls":"animates","id":"A360"},
"361": {"cls":"animates","id":"A361"}, "361": {"cls":"animates","id":"A361","animate":1,"trigger":"openDoor","doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{}}},
"362": {"cls":"animates","id":"A362"}, "362": {"cls":"animates","id":"A362"},
"363": {"cls":"animates","id":"A363"}, "363": {"cls":"animates","id":"A363"},
"364": {"cls":"animates","id":"A364"}, "364": {"cls":"animates","id":"A364"},
"365": {"cls":"animates","id":"A365"}, "365": {"cls":"animates","id":"A365"},
"366": {"cls":"animates","id":"A366"}, "366": {"cls":"animates","id":"A366"},
"367": {"cls":"animates","id":"A367","event":null,"canPass":true}, "367": {"cls":"animates","id":"A367","event":null,"canPass":true},
"368": {"cls":"animates","id":"A368"}, "368": {"cls":"animates","id":"A368","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{}}},
"369": {"cls":"animates","id":"A369"}, "369": {"cls":"animates","id":"A369"},
"370": {"cls":"animates","id":"A370"}, "370": {"cls":"animates","id":"A370"},
"371": {"cls":"npcs","id":"N371"}, "371": {"cls":"npcs","id":"N371"},

View File

@ -42,7 +42,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
if (clientWidth - 3 * BORDER >= core._PX_ + BAR_WIDTH || (clientWidth > clientHeight && horizontalMaxRatio < 1)) { if (clientWidth - 3 * BORDER >= core._PX_ + BAR_WIDTH || (clientWidth > clientHeight && horizontalMaxRatio < 1)) {
core.domStyle.isVertical = false; core.domStyle.isVertical = false;
core.clearMap('Vertical'); core.clearMap('Vertical');
} else { } else if (core.status.played) {
// 竖屏 // 竖屏
core.domStyle.isVertical = true; core.domStyle.isVertical = true;
core.createCanvas('Vertical', 0, 0, 480, 480, 200); core.createCanvas('Vertical', 0, 0, 480, 480, 200);
@ -1856,7 +1856,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
if (!name) return; if (!name) return;
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
canvas.id = name; canvas.id = name;
canvas.className = 'gameCanvas'; canvas.className = 'gameCanvas anti-aliasing';
// 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高 // 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高
if (main.mode != "editor") canvas.style.zIndex = zIndex || 0; if (main.mode != "editor") canvas.style.zIndex = zIndex || 0;
// 将图层插入进游戏内容 // 将图层插入进游戏内容
@ -3902,19 +3902,21 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
// 准备渐变 // 准备渐变
this.maskPrepare = function () { this.maskPrepare = function () {
// 执行后画面将凝固 // 执行后画面将凝固
core.ui.createCanvas2("mask", 0, 0, core.__PIXELS__, core.__PIXELS__, 155); var mask = core.ui.createCanvas2("mask", 0, 0, core.__PIXELS__ + 161, core.__PIXELS__, 200);
for (var m in core.canvas) { core.drawThumbnail(core.status.floorId, null, { ctx: mask, x: 161, y: 0, size: 1, damage: false, all: true });
core.dymCanvas.mask.drawImage(core.canvas[m].canvas, 0, 0); core.drawImage('mask', 'caidan.png', 0, 0);
}; // for (var m in core.canvas) {
// core.dymCanvas.mask.drawImage(core.canvas[m].canvas, 0, 0);
// };
} }
// 执行渐变 // 执行渐变
this.maskFliter = function (time, sample) { // sample为渐变图名称渐变图需要在全塔属性注册 this.maskFliter = function (time, sample) { // sample为渐变图名称渐变图需要在全塔属性注册
var tempCanvas = core.bigmap.tempCanvas; var tempCanvas = core.ui.createCanvas2("mask2", 0, 0, core.__PIXELS__ + 161, core.__PIXELS__, 200);
var tempWidth = core.__PIXELS__, var tempWidth = tempCanvas.canvas.width,
tempHeight = core.__PIXELS__; tempHeight = tempCanvas.canvas.height;
tempCanvas.canvas.width = tempWidth; //tempCanvas.canvas.width = tempWidth;
tempCanvas.canvas.height = tempHeight; //tempCanvas.canvas.height = tempHeight;
tempCanvas.clearRect(0, 0, tempWidth, tempHeight); tempCanvas.clearRect(0, 0, tempWidth, tempHeight);
tempCanvas.drawImage(core.material.images.images[sample], 0, 0, tempWidth, tempHeight); tempCanvas.drawImage(core.material.images.images[sample], 0, 0, tempWidth, tempHeight);
// 读取渐变图开始处理 // 读取渐变图开始处理

651
server.js Normal file
View File

@ -0,0 +1,651 @@
const http = require('http');
const fs = require('fs/promises');
const fss = require('fs');
const path = require('path');
const name = (() => {
const data = fss.readFileSync('./project/data.js', 'utf-8');
const json = JSON.parse(
data
.split(/(\n|\r\n)/)
.slice(1)
.join('\n')
);
return json.firstData.name;
})();
/** 核心服务器 */
const server = http.createServer();
/** 是否需要重新加载浏览器 */
let needReload = true;
/** 热重载信息 */
let hotReloadData = '';
/** 是否已经启动了热重载模块 */
let watched = false;
/** 是否已经启动了录像调试模块 */
let replayed = false;
/** 监听端口 */
let port = 3000;
const next = () => {
server.listen(port, '127.0.0.1');
server.on('error', () => {
console.log(`${port}端口已被占用`);
port++;
next();
});
};
next();
let repStart;
const listenedFloors = [];
// ----- GET file
/**
* 请求文件
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
* @param {string} path
*/
async function getFile(req, res, path) {
try {
const data = await fs.readFile(path);
if (path.endsWith('.js'))
res.writeHead(200, { 'Content-type': 'text/javascript' });
if (path.endsWith('.css'))
res.writeHead(200, { 'Content-type': 'text/css' });
if (path.endsWith('.html'))
res.writeHead(200, { 'Content-type': 'text/html' });
return res.end(data), true;
} catch {
return false;
}
}
/**
* 高层塔优化及动画加载
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
* @param {string[]} ids
* @param {string} suffix 后缀名
* @param {string} dir 文件夹路径
* @param {string} join 分隔符
*/
async function getAll(req, res, ids, suffix, dir, join) {
let data = {};
const tasks = ids.map(v => {
return new Promise(res => {
const d = path.resolve(__dirname, `${dir}${v}${suffix}`);
try {
fs.readFile(d).then(vv => {
data[v] = vv;
res(`${v} pack success.`);
});
} catch {
throw new ReferenceError(`The file ${d} does not exists.`);
}
});
});
await Promise.all(tasks);
const result = ids.map(v => data[v]);
return res.end(result.join(join)), true;
}
// ----- 样板的fs功能
/**
* 获取POST的数据
* @param {http.IncomingMessage} req
*/
async function getPostData(req) {
let data = '';
await new Promise(res => {
req.on('data', chunk => {
data += chunk.toString();
});
req.on('end', res);
});
return data;
}
/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
*/
async function readDir(req, res) {
const data = await getPostData(req);
const dir = path.resolve(__dirname, data.toString().slice(5));
try {
const info = await fs.readdir(dir);
res.end(JSON.stringify(info));
} catch (e) {
console.error(e);
res.end(`error: Read dir ${dir} fail. Does the dir exists?`);
}
}
/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
*/
async function mkdir(req, res) {
const data = await getPostData(req);
const dir = path.resolve(__dirname, data.toString().slice(5));
try {
await fs.mkdir(dir);
} catch (e) {}
res.end();
}
/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
*/
async function readFile(req, res) {
const data = (await getPostData(req)).toString();
const dir = path.resolve(__dirname, data.split('&name=')[1]);
try {
const type = /^type=(utf8|base64)/.exec(data)[0];
const info = await fs.readFile(dir, { encoding: type.slice(5) });
res.end(info);
} catch (e) {
res.end();
}
}
/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
*/
async function writeFile(req, res) {
const data = (await getPostData(req)).toString();
const name = data.split('&name=')[1].split('&value=')[0];
const dir = path.resolve(__dirname, name);
try {
const type = /^type=(utf8|base64)/.exec(data)[0].slice(5);
const value = /&value=[^]+/.exec(data)[0].slice(7);
await fs.writeFile(dir, value, { encoding: type });
testWatchFloor(name);
} catch (e) {
console.error(e);
res.end(
`error: Write file ${dir} fail. Does the parent folder exists?`
);
}
res.end();
}
/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
*/
async function rm(req, res) {
const data = (await getPostData(req)).toString();
const dir = path.resolve(__dirname, data.slice(5));
try {
await fs.rm(dir);
} catch (e) {
console.error(e);
res.end(`error: Remove file ${dir} fail. Does this file exists?`);
}
res.end();
}
/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
*/
async function moveFile(req, res) {
const data = (await getPostData(req)).toString();
const info = data.split('&dest=');
const src = path.resolve(__dirname, info[0].slice(4));
const dest = info[1];
try {
const data = await fs.readFile(src);
await fs.writeFile(path.resolve(__dirname, dest), data);
await fs.rm(src);
} catch (e) {
console.error(e);
res.end(`error: Move file ${dir} fail.`);
}
res.end();
}
/**
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
*/
async function writeMultiFiles(req, res) {
const data = (await getPostData(req)).toString();
const names = /name=[^]+&value=/.exec(data)[0].slice(5, -7).split(';');
const value = /&value=[^]+/.exec(data)[0].slice(7).split(';');
const tasks = names.map((v, i) => {
try {
return new Promise(res => {
fs.writeFile(
path.resolve(__dirname, v),
value[i],
'base64' // 多文件是base64写入的
).then(v => {
testWatchFloor(v);
res(`write ${v} success.`);
});
});
} catch {
console.error(e);
res.end(`error: Write multi files fail.`);
}
});
await Promise.all(tasks);
res.end();
}
// ----- extract path & utils
/**
* 解析路径
* @param {...string} dirs
* @returns {Promise<string[]>}
*/
async function extract(...dirs) {
const res = [];
const tasks = dirs.map(v => {
return new Promise(resolve => {
if (v.endsWith('/')) {
// 匹配路径
const dir = path.resolve(__dirname, v.slice(0, -1));
fs.readdir(dir).then(files => {
const all = files
.filter(v => v !== 'thirdparty') // 排除第三方库
.map(vv => v + vv);
res.push(...all);
resolve('success');
});
} else if (/\/\*.\w+$/.test(v)) {
// 匹配文件夹中的后缀名
const suffix = /\.\w+$/.exec(v)[0];
const d = v.split(`/*${suffix}`)[0];
const dir = path.resolve(__dirname, d);
fs.readdir(dir).then(files => {
const all = files
.filter(v => v.endsWith(suffix))
.map(v => `${d === '' ? '' : d + '/'}${v}`);
res.push(...all);
resolve('success');
});
} else {
res.push(v);
resolve('success');
}
});
});
await Promise.all(tasks);
return res;
}
// ----- hot reload
/**
* 监听文件变化
*/
async function watch() {
// 需要重新加载的文件
const refresh = await extract('main.js', 'index.html', 'libs/');
const option = {
interval: 1000
};
refresh.forEach(v => {
const dir = path.resolve(__dirname, v);
fss.watchFile(dir, option, () => {
needReload = true;
console.log(`change: ${v}`);
});
});
// css 热重载
const css = await extract('/*.css');
css.forEach(v => {
const dir = path.resolve(__dirname, v);
fss.watchFile(dir, option, () => {
hotReloadData += `@@css:${v}`;
console.log(`css hot reload: ${v}`);
});
});
// 楼层 热重载
// 注意这里要逐个监听,并通过创建文件来监听文件改变
const floors = await extract('project/floors/*.js');
floors.forEach(v => {
watchOneFloor(v.slice(15));
});
// 脚本编辑 及 插件 热重载
const scripts = await extract('project/functions.js', 'project/plugins.js');
scripts.forEach(v => {
const dir = path.resolve(__dirname, v);
const type = v.split('/').at(-1).slice(0, -3);
fss.watchFile(dir, option, () => {
hotReloadData += `@@script:${type}`;
console.log(`script hot reload: ${type}.js`);
});
});
// 数据热重载
const datas = (await extract('project/*.js')).filter(
v => !v.endsWith('functions.js') && !v.endsWith('plugins.js')
);
datas.forEach(v => {
const dir = path.resolve(__dirname, v);
const type = v.split('/').at(-1).slice(0, -3);
fss.watchFile(dir, option, () => {
hotReloadData += `@@data:${type}`;
console.log(`data hot reload: ${type}`);
});
});
}
/**
* 检测是否是楼层文件并进行监听
* @param {string} url 要测试的路径
*/
function testWatchFloor(url) {
if (/project(\/|\\)floors(\/|\\).*\.js/.test(url)) {
const f = url.slice(15);
if (!listenedFloors.includes(f.slice(0, -3))) {
watchOneFloor(f);
}
}
}
/**
* 监听一个楼层文件
* @param {string} file 要监听的文件
*/
function watchOneFloor(file) {
if (!/.*\.js/.test(file)) return;
const f = file.slice(0, -3);
listenedFloors.push(file.slice(0, -3));
fss.watchFile(`project/floors/${file}`, { interval: 1000 }, () => {
const floorId = f;
if (hotReloadData.includes(`@@floor:${floorId}`)) return;
hotReloadData += `@@floor:${floorId}`;
console.log(`floor hot reload: ${floorId}`);
});
}
/**
* 修改部分文件后重新加载及热重载
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {req: http.IncomingMessage;}} res
*/
function reload(req, res, hot = false) {
req.on('data', chunk => {
if (chunk.toString() === 'test' && !watched) {
watch();
watched = true;
console.log(`服务器热重载模块已开始服务`);
}
});
req.on('end', () => {
if (!hot) {
res.end(`${needReload}`);
needReload = false;
} else {
res.end(hotReloadData);
hotReloadData = '';
}
});
}
// ----- replay debugger
/**
* 录像调试
* @param {http.IncomingMessage} req
* @param {http.ServerResponse<http.IncomingMessage> & {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<http.IncomingMessage> & {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<http.IncomingMessage> & {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<http.IncomingMessage> & {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<http.IncomingMessage> & {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<http.IncomingMessage> & {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');
}
// ----- server
server.on('listening', () => {
console.log(`服务已启动编辑器地址http://127.0.0.1:${port}/editor.html`);
console.log(`游戏地址http://127.0.0.1:${port}`);
});
// 处理请求
server.on('request', async (req, res) => {
/** @type {string} */
const p = req.url.replace(`/games/${name}`, '').replace('/all/', '/');
if (req.method === 'GET') {
const dir = path
.resolve(__dirname, p === '/' ? 'index.html' : p.slice(1))
.split('?v=')[0];
if (await getFile(req, res, dir)) return;
if (p.startsWith('/__all_floors__.js')) {
const all = p.split('&id=')[1].split(',');
res.writeHead(200, { 'Content-type': 'text/javascript' });
return await getAll(req, res, all, '.js', 'project/floors/', '\n');
}
if (p.startsWith('/__all_animates__')) {
const all = p.split('&id=')[1].split(',');
return await getAll(
req,
res,
all,
'.animate',
'project/animates/',
'@@@~~~###~~~@@@'
);
}
}
if (req.method === 'POST') {
if (p === '/listFile') return await readDir(req, res);
if (p === '/makeDir') return await mkdir(req, res);
if (p === '/readFile') return await readFile(req, res);
if (p === '/writeFile') return await writeFile(req, res);
if (p === '/deleteFile') return await rm(req, res);
if (p === '/moveFile') return await moveFile(req, res);
if (p === '/writeMultiFiles') return await writeMultiFiles(req, res);
if (p === '/reload') return reload(req, res);
if (p === '/hotReload') return reload(req, res, true);
if (p === '/replay') return replay(req, res);
if (p === '/replayWrite') return await replayWrite(req, res);
if (p === '/replayCheck') return await replayCheck(req, res);
if (p === '/replayGet') return await replayGet(req, res, 'status');
if (p === '/replaySave') return await replaySave(req, res);
if (p === '/replayGetSave') return await replayGet(req, res, 'save');
}
res.statusCode = 404;
res.end();
});

View File

@ -527,4 +527,9 @@ p#name {
@font-face { @font-face {
font-family: Fira Code; font-family: Fira Code;
src: url(../src/fonts/FiraCode-Regular.ttf); src: url(../src/fonts/FiraCode-Regular.ttf);
}
/* 注释下面这三行以开启抗锯齿 */
.anti-aliasing {
image-rendering: pixelated;
} }

View File

@ -1,9 +0,0 @@
{
"compilerOptions": {
"allowJs": true,
"noEmit": true,
},
"include": [
"main.js", "project/**/*.js", "libs/**/*.js", "runtime.d.ts"
]
}

Binary file not shown.