From 97f8fe54668197a33db00eb117b8e16750d1f995 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Fri, 29 Nov 2019 17:04:59 +0800 Subject: [PATCH] precompile --- _docs/api.md | 10 +++ libs/events.js | 174 ++++++++++++++++++++++++++++++++++++++++++++++++- libs/utils.js | 41 +++++++----- 3 files changed, 207 insertions(+), 18 deletions(-) diff --git a/_docs/api.md b/_docs/api.md index 735ddd86..21f84d9f 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -987,10 +987,15 @@ core.getCommonEvent(name) core.recoverEvents(data) 恢复事件现场。一般用于呼出怪物手册、呼出存读档页面等时,恢复事件执行流。 + core.checkAutoEvents() 检测自动事件并执行。 +core.precompile(events) +尝试预编译一段事件。 + + // ------ 点击状态栏图标时执行的一些操作 ------ // core.openBook(fromUserAction) @@ -1918,6 +1923,11 @@ core.replayText(text, need, times) 将一段文字中的${}(表达式)进行替换。need和time一般可以直接忽略。 +core.replaceValue(value) +对一个表达式中的特殊规则进行替换,如status:xxx等。 +请注意,此项不会对独立开关如switch:A进行替换。 + + core.calValue(value, prefix, need, time) 计算一个表达式的值,支持status:xxx等的计算。 prefix为前缀(switch:xxx的独立开关使用),need和time一般可以直接忽略。 diff --git a/libs/events.js b/libs/events.js index b92e6ab3..76b59731 100644 --- a/libs/events.js +++ b/libs/events.js @@ -931,6 +931,8 @@ events.prototype.insertAction = function (action, x, y, callback, addToLast) { } if (!action) return; + action = this.precompile(action); + if (core.status.event.id != 'action') { this.startEvents(action, x, y, callback); } @@ -1039,6 +1041,98 @@ events.prototype.popEventLoc = function () { } } +events.prototype.precompile = function (data) { + var array = this.__precompile_getArray(); + if (typeof data == 'string') { + return this.__precompile_text(data); + } + if (data instanceof Array) { + for (var i = 0; i < data.length; ++i) { + data[i] = this.precompile(data[i]); + } + return data; + } + if (data && data.type) { + if (this["_precompile_" + data.type]) { + data = this["_precompile_" + data.type](data); + } + if (array.texts.indexOf(data.type) >= 0) { + data.text = this.__precompile_text(data.text); + } + if (array.locs.indexOf(data.type) >= 0) { + data.loc = this.__precompile_array(data.loc); + } + if (array.values.indexOf(data.type) >= 0) { + data.value = core.replaceValue(data.value); + } + if (array.uievents.indexOf(data.type) >= 0) { + data.x = core.replaceValue(data.x); + data.y = core.replaceValue(data.y); + data.width = core.replaceValue(data.width); + data.height = core.replaceValue(data.height); + } + if (data.type in array.others) { + array.others[data.type].forEach(function (field) { + data[field] = core.replaceValue(data[field]); + }) + } + } + return data; +} + +events.prototype.__precompile_getArray = function () { + var texts = [ + "text", "autoText", "scrollText", "tip", "textImage", "input", "input2", + "choices", "confirm", "fillText", "fillBoldText", "drawTextContent" + ]; + var locs = [ + "show", "hide", "setBlock", "showFloorImg", "hideFloorImg", "showBgFgMap", + "hideBgFgMap", "setBgFgBlock", "animate", "setViewport", "move", "jumoHero", + "changeFloor", "changePos", "showTextImage", "showGif", "openDoor", + "closeDoor", "battle", "trigger", "insert" + ]; + var values = [ + "setValue", "setValue2", "addValue", "setEnemy", "setFloor", "setGlobalValue", + ]; + var uievents = [ + "clearMap", "fillText", "fillBoldText", "fillRect", "strokeRect", "strokeCircle", + "drawIcon", "drawSelector", "drawBackground", + ]; + var others = { + "strokeCircle": ["r"], + "drawLine": ["x1", "y1", "x2", "y2"], + "drawArrow": ["x1", "y1", "x2", "y2"], + "drawImage": ["x", "y", "w", "h", "x1", "y1", "w1", "h1"], + "drawTextContent": ["left", "top"], + }; + return { + texts: texts, + locs: locs, + values: values, + uievents: uievents, + others: others + }; +} + +events.prototype.__precompile_text = function (text) { + return text.replace(/\${(.*?)}/g, function (word, value) { + return "${" + core.replaceValue(value) + "}"; + }); +} + +events.prototype.__precompile_array = function (value) { + if (typeof value == 'string') { + value = core.replaceValue(value); + return value; + } + if (value instanceof Array) { + for (var i = 0; i < value.length; ++i) { + value[i] = this.__precompile_array(value[i]); + } + } + return value; +} + // ------ 样板提供的的自定义事件 ------ // events.prototype.__action_checkReplaying = function () { @@ -1231,6 +1325,12 @@ events.prototype._action_jump = function (data, x, y, prefix) { this.__action_doAsyncFunc(data.async, core.jumpBlock, from[0], from[1], to[0], to[1], data.time, data.keep); } +events.prototype._precompile_jump = function (data) { + data.from = this.__precompile_array(data.from); + data.to = this.__precompile_array(data.to); + return data; +} + events.prototype._action_jumpHero = function (data, x, y, prefix) { var loc = this.__action_getHeroLoc(data.loc, prefix); this.__action_doAsyncFunc(data.async, core.jumpHero, loc[0], loc[1], data.time); @@ -1258,6 +1358,12 @@ events.prototype._action_showImage = function (data, x, y, prefix) { data.code, data.image, data.sloc, data.loc, data.opacity, data.time); } +events.prototype._precompile_showImage = function (data) { + data.sloc = this.__precompile_array(data.sloc); + data.loc = this.__precompile_array(data.loc); + return data; +} + events.prototype._action_showTextImage = function (data, x, y, prefix) { var loc = this.__action_getLoc(data.loc, 0, 0, prefix); if (core.isReplaying()) data.time = 0; @@ -1281,6 +1387,11 @@ events.prototype._action_moveImage = function (data, x, y, prefix) { this.__action_doAsyncFunc(data.async, core.moveImage, data.code, data.to, data.opacity, data.time); } +events.prototype._precompile_moveImage = function (data) { + data.to = this.__precompile_array(data.to); + return data; +} + events.prototype._action_setFg = function (data, x, y, prefix) { return this._action_setCurtain(data, x, y, prefix); } @@ -1552,6 +1663,13 @@ events.prototype._action_if = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_if = function (data) { + data.condition = core.replaceValue(data.condition); + data["true"] = this.precompile(data["true"]); + data["false"] = this.precompile(data["false"]); + return data; +} + events.prototype._action_switch = function (data, x, y, prefix) { var key = core.calValue(data.condition, prefix) var list = []; @@ -1567,6 +1685,15 @@ events.prototype._action_switch = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_switch = function (data) { + data.condition = core.replaceValue(data.condition); + for (var i = 0; i < data.caseList.length; i++) { + data.caseList[i]["case"] = core.replaceValue(data.caseList[i]["case"]); + data.caseList[i].action = this.precompile(data.caseList[i].action); + } + return data; +} + events.prototype._action_choices = function (data, x, y, prefix) { data.choices = data.choices.filter(function (x) { if (x.condition == null || x.condition == '') return true; @@ -1593,6 +1720,16 @@ events.prototype._action_choices = function (data, x, y, prefix) { core.ui.drawChoices(data.text, data.choices); } +events.prototype._precompile_choices = function (data) { + if (!(data.choices instanceof Array)) return data; + for (var i = 0; i < data.choices.length; ++i) { + data.choices[i].condition = core.replaceValue(data.choices[i].condition); + data.choices[i].text = this.__precompile_text(data.choices[i].text); + data.choices[i].action = this.precompile(data.choices[i].action); + } + return data; +} + events.prototype._action_confirm = function (data, x, y, prefix) { core.status.event.ui = {"text": data.text, "yes": data.yes, "no": data.no}; if (core.isReplaying()) { @@ -1619,6 +1756,12 @@ events.prototype._action_confirm = function (data, x, y, prefix) { core.ui.drawConfirmBox(data.text); } +events.prototype._precompile_confirm = function (data) { + data.yes = this.precompile(data.yes); + data.no = this.precompile(data.no); + return data; +} + events.prototype._action_while = function (data, x, y, prefix) { if (core.calValue(data.condition, prefix)) { core.unshift(core.status.event.data.list, @@ -1628,6 +1771,12 @@ events.prototype._action_while = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_while = function (data) { + data.condition = core.replaceValue(data.condition); + data.data = this.precompile(data.data); + return data; +} + events.prototype._action_dowhile = function (data, x, y, prefix) { core.unshift(core.status.event.data.list, {"todo": core.clone(data.data), "total": core.clone(data.data), "condition": data.condition} @@ -1635,6 +1784,12 @@ events.prototype._action_dowhile = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_dowhile = function (data) { + data.condition = core.replaceValue(data.condition); + data.data = this.precompile(data.data); + return data; +} + events.prototype._action_break = function (data, x, y, prefix) { core.status.event.data.list.shift(); core.doAction(); @@ -1651,11 +1806,11 @@ events.prototype._action_continue = function (data, x, y, prefix) { } events.prototype._action_win = function (data, x, y, prefix) { - this.win(data.reason, data.norank, data.noexit); + this.win(core.replaceText(data.reason), data.norank, data.noexit); } events.prototype._action_lose = function (data, x, y, prefix) { - this.lose(data.reason); + this.lose(core.replaceText(data.reason)); } events.prototype._action_restart = function (data, x, y, prefix) { @@ -1819,6 +1974,11 @@ events.prototype._action_previewUI = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_previewUI = function (data) { + data.action = this.precompile(data.action); + return data; +} + events.prototype.__action_doUIEvent = function (data) { this.__action_doUIEvent_doOne(data); var current = core.status.event.data.list[0]; @@ -1859,6 +2019,11 @@ events.prototype._action_fillPolygon = function (data, x, y, prefix) { this.__action_doUIEvent(data); } +events.prototype._precompile_fillPolygon = function (data) { + data.nodes = this.__precompile_array(data.nodes); + return data; +} + events.prototype._action_strokeRect = function (data, x, y, prefix) { this.__action_doUIEvent(data); } @@ -1867,6 +2032,11 @@ events.prototype._action_strokePolygon = function (data, x, y, prefix) { this.__action_doUIEvent(data); } +events.prototype._precompile_strokePolygon = function (data) { + data.nodes = this.__precompile_array(data.nodes); + return data; +} + events.prototype._action_fillCircle = function (data, x, y, prefix) { this.__action_doUIEvent(data); } diff --git a/libs/utils.js b/libs/utils.js index 3f345fa8..059f48d6 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -66,29 +66,38 @@ utils.prototype.replaceText = function (text, need, times) { }); } +utils.prototype.replaceValue = function (value) { + if (typeof value == "string" && value.indexOf(":") >= 0) { + if (value.indexOf('status:') >= 0) + value = value.replace(/status:([a-zA-Z0-9_]+)/g, "core.getStatus('$1')"); + if (value.indexOf('item:') >= 0) + value = value.replace(/item:([a-zA-Z0-9_]+)/g, "core.itemCount('$1')"); + if (value.indexOf('flag:') >= 0) + value = value.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getFlag('$1', 0)"); + //if (value.indexOf('switch:' >= 0)) + // value = value.replace(/switch:([a-zA-Z0-9_]+)/g, "core.getFlag('" + (prefix || ":f@x@y") + "@$1', 0)"); + if (value.indexOf('global:') >= 0) + value = value.replace(/global:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getGlobal('$1', 0)"); + if (value.indexOf('enemy:')>=0) + value = value.replace(/enemy:([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)/g, "core.material.enemys['$1'].$2"); + if (value.indexOf('blockId:')>=0) + value = value.replace(/blockId:(\d+),(\d+)/g, "core.getBlockId($1, $2)"); + if (value.indexOf('blockCls:')>=0) + value = value.replace(/blockCls:(\d+),(\d+)/g, "core.getBlockCls($1, $2)"); + if (value.indexOf('equip:')>=0) + value = value.replace(/equip:(\d)/g, "core.getEquip($1)"); + } + return value; +} + ////// 计算表达式的值 ////// utils.prototype.calValue = function (value, prefix, need, times) { if (!core.isset(value)) return null; if (typeof value === 'string') { if (value.indexOf(':') >= 0) { - if (value.indexOf('status:') >= 0) - value = value.replace(/status:([a-zA-Z0-9_]+)/g, "core.getStatus('$1')"); - if (value.indexOf('item:') >= 0) - value = value.replace(/item:([a-zA-Z0-9_]+)/g, "core.itemCount('$1')"); - if (value.indexOf('flag:') >= 0) - value = value.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getFlag('$1', 0)"); if (value.indexOf('switch:' >= 0)) value = value.replace(/switch:([a-zA-Z0-9_]+)/g, "core.getFlag('" + (prefix || ":f@x@y") + "@$1', 0)"); - if (value.indexOf('global:') >= 0) - value = value.replace(/global:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getGlobal('$1', 0)"); - if (value.indexOf('enemy:')>=0) - value = value.replace(/enemy:([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)/g, "core.material.enemys['$1'].$2"); - if (value.indexOf('blockId:')>=0) - value = value.replace(/blockId:(\d+),(\d+)/g, "core.getBlockId($1, $2)"); - if (value.indexOf('blockCls:')>=0) - value = value.replace(/blockCls:(\d+),(\d+)/g, "core.getBlockCls($1, $2)"); - if (value.indexOf('equip:')>=0) - value = value.replace(/equip:(\d)/g, "core.getEquip($1)"); + value = this.replaceValue(value); } return eval(value); }