mirror of
https://github.com/IvarK/AntimatterDimensionsSourceCode.git
synced 2024-11-22 04:05:42 +00:00
Address second round of PR feedback (automator-improvements)
This commit is contained in:
parent
0c22340663
commit
458d111b67
@ -1,3 +1,5 @@
|
||||
import { AutomatorPanels } from "../../../src/components/tabs/automator/AutomatorDocs";
|
||||
|
||||
/** @abstract */
|
||||
class AutomatorCommandInterface {
|
||||
constructor(id) {
|
||||
@ -180,6 +182,12 @@ export const AutomatorData = {
|
||||
|
||||
MAX_ALLOWED_SCRIPT_CHARACTERS: 10000,
|
||||
MAX_ALLOWED_TOTAL_CHARACTERS: 60000,
|
||||
MAX_ALLOWED_SCRIPT_NAME_LENGTH: 15,
|
||||
MAX_ALLOWED_SCRIPT_COUNT: 20,
|
||||
MAX_ALLOWED_CONSTANT_NAME_LENGTH: 20,
|
||||
// Note that a study string with ALL studies in unshortened form without duplicated studies is ~230 characters
|
||||
MAX_ALLOWED_CONSTANT_VALUE_LENGTH: 250,
|
||||
MAX_ALLOWED_CONSTANT_COUNT: 30,
|
||||
|
||||
scriptIndex() {
|
||||
return player.reality.automator.state.editorScript;
|
||||
@ -428,7 +436,7 @@ export const AutomatorBackend = {
|
||||
|
||||
step() {
|
||||
if (this.stack.isEmpty) return false;
|
||||
for (let steps = 0; steps < 100; steps++) {
|
||||
for (let steps = 0; steps < 100 && !this.hasJustCompleted; steps++) {
|
||||
switch (this.runCurrentCommand()) {
|
||||
case AUTOMATOR_COMMAND_STATUS.SAME_INSTRUCTION:
|
||||
return true;
|
||||
@ -442,14 +450,22 @@ export const AutomatorBackend = {
|
||||
case AUTOMATOR_COMMAND_STATUS.SKIP_INSTRUCTION:
|
||||
this.nextCommand();
|
||||
}
|
||||
|
||||
// We need to break out of the loop if the last commands are all SKIP_INSTRUCTION, or else it'll start
|
||||
// trying to execute from an undefined stack if it isn't set to automatically repeat
|
||||
if (!this.stack.top) this.hasJustCompleted = true;
|
||||
}
|
||||
|
||||
// This should in practice never happen by accident due to it requiring 100 consecutive commands that don't do
|
||||
// anything (looping a smaller group of no-ops will instead trigger the loop check every tick). Nevertheless,
|
||||
// better to not have an explicit infinite loop so that the game doesn't hang if the player decides to be funny
|
||||
// and input 3000 comments in a row
|
||||
GameUI.notify.error("Automator halted - too many consecutive no-ops detected");
|
||||
AutomatorData.logCommandEvent("Automator halted due to excessive no-op commands", this.currentLineNumber);
|
||||
// and input 3000 comments in a row. If hasJustCompleted is true, then we actually broke out because the end of
|
||||
// the script has no-ops and we just looped through them, and therefore shouldn't show these messages
|
||||
if (!this.hasJustCompleted) {
|
||||
GameUI.notify.error("Automator halted - too many consecutive no-ops detected");
|
||||
AutomatorData.logCommandEvent("Automator halted due to excessive no-op commands", this.currentLineNumber);
|
||||
}
|
||||
|
||||
this.stop();
|
||||
return false;
|
||||
},
|
||||
@ -612,6 +628,26 @@ export const AutomatorBackend = {
|
||||
this.reset(this.stack._data[0].commands);
|
||||
},
|
||||
|
||||
changeModes(scriptID) {
|
||||
Tutorial.moveOn(TUTORIAL_STATE.AUTOMATOR);
|
||||
if (player.reality.automator.type === AUTOMATOR_TYPE.BLOCK) {
|
||||
// This saves the script after converting it.
|
||||
BlockAutomator.parseTextFromBlocks();
|
||||
player.reality.automator.type = AUTOMATOR_TYPE.TEXT;
|
||||
if (player.reality.automator.currentInfoPane === AutomatorPanels.BLOCKS) {
|
||||
player.reality.automator.currentInfoPane = AutomatorPanels.COMMANDS;
|
||||
}
|
||||
} else {
|
||||
const toConvert = AutomatorTextUI.editor.getDoc().getValue();
|
||||
// Needs to be called to update the lines prop in the BlockAutomator object
|
||||
BlockAutomator.fromText(toConvert);
|
||||
AutomatorBackend.saveScript(scriptID, toConvert);
|
||||
player.reality.automator.type = AUTOMATOR_TYPE.BLOCK;
|
||||
player.reality.automator.currentInfoPane = AutomatorPanels.BLOCKS;
|
||||
}
|
||||
AutomatorHighlighter.clearAllHighlightedLines();
|
||||
},
|
||||
|
||||
stack: {
|
||||
_data: [],
|
||||
push(commands) {
|
||||
|
@ -525,6 +525,10 @@ import { AutomatorLexer } from "./lexer";
|
||||
foundChildren += nestedCommands
|
||||
? nestedCommands.map(c => validatedCount(c) + 1).reduce((sum, val) => sum + val, 0)
|
||||
: 0;
|
||||
|
||||
// Trailing newlines get turned into a command with a single EOF argument; we return -1 because one level up
|
||||
// on the recursion this looks like an otherwise valid command and would be counted as such
|
||||
if (key === "EOF") return -1;
|
||||
}
|
||||
return foundChildren;
|
||||
};
|
||||
|
@ -912,32 +912,42 @@ simply completing more Realities.
|
||||
<br>
|
||||
<br>
|
||||
The Automator uses a scripting language that allows you to automate nearly the entire game.
|
||||
The interface has two panes, a script pane on the left where you enter the commands to automate the game, and a
|
||||
multiple function pane on the right.
|
||||
The interface has two panes, a script pane on the left where you enter the commands to automate the game and a
|
||||
pane on the right which has multiple panels which do many different things. The panels on the right side include:
|
||||
<br>
|
||||
These functions include:
|
||||
- The command list, with information on all the commands available to you (some may not be available until you have
|
||||
unlocked certain things)
|
||||
<br>
|
||||
- a brief introduction to the Automator
|
||||
- The template creator, which allows you to generate premade script templates to accomplish certain tasks
|
||||
<br>
|
||||
- the command list, with information on all the commands available to you
|
||||
- All errors in the current Automator script, as well as possible suggestions on how to fix them; the button for
|
||||
this panel will light up if you have any errors in your current script
|
||||
<br>
|
||||
- the template creator, which allows you to fill in premade templates to suit your own purposes
|
||||
- All recently executed commands, what those commands did, and how recently they were executed
|
||||
<br>
|
||||
- a list of all errors in the current Automator script
|
||||
- A constant definition panel where you can define as shorthand for values within the automator (eg. special numbers
|
||||
or certain Time Study trees)
|
||||
<br>
|
||||
- a list of recently executed commands and what those commands did
|
||||
<br>
|
||||
- if you are in the Block mode of the Automator, the command blocks used to write the script
|
||||
- If you are in the block mode of the Automator, there will also be a panel for the command blocks used to write the
|
||||
script
|
||||
<br>
|
||||
<br>
|
||||
You can use as many rows as you need.
|
||||
<br>
|
||||
Some commands are gated behind unlocks, which will only become visible once you have unlocked them.
|
||||
There are a few limitations to scripts in order to reduce lag and prevent save file size from getting too large.
|
||||
Individual scripts are limited to a maximum of ${formatInt(AutomatorData.MAX_ALLOWED_SCRIPT_CHARACTERS)}
|
||||
characters each, and all your scripts together cannot exceed a <i>total</i> character count of
|
||||
${formatInt(AutomatorData.MAX_ALLOWED_TOTAL_CHARACTERS)}. Any changes made to scripts while above these limits
|
||||
will not be saved if you refresh the page.
|
||||
<br>
|
||||
<br>
|
||||
You are able to create new scripts by clicking on the dropdown, and then clicking the "Create New..." option.
|
||||
To rename a script, click the pencil next to the dropdown. Scripts are automatically saved as you edit them.
|
||||
You can create as many scripts as you want.
|
||||
You are able to create new scripts by clicking on the dropdown, and then clicking the "Create new script..." option.
|
||||
To rename a script, click the pencil next to the dropdown and edit the name to whatever you with the script to be
|
||||
called (max ${formatInt(AutomatorData.MAX_ALLOWED_SCRIPT_NAME_LENGTH)} characters). You are allowed to create a
|
||||
maximum of ${formatInt(AutomatorData.MAX_ALLOWED_SCRIPT_COUNT)} scripts.
|
||||
<br>
|
||||
<br>
|
||||
Scripts are automatically saved as you edit them, but are not saved to your game save until the global autosave timer
|
||||
(ie. "Time since last save") triggers a full game save. If you make changes to scripts right before closing the game,
|
||||
you should wait until the game saves afterwards in order to not lose your changes.
|
||||
<br>
|
||||
<br>
|
||||
If you want a larger workspace, you can press the button in the top right corner of the documentation pane of the
|
||||
@ -946,11 +956,15 @@ panes if you want more room to write your script or read documentation.
|
||||
<br>
|
||||
<br>
|
||||
By pressing the top-right button on the script pane, you can switch to block mode, which may be more approachable if
|
||||
you are unfamiliar with programming. To enter commands in block mode, drag the box for the relevant command from the
|
||||
documentation pane into the script pane and drop it where you want the command to go. Commands can be freely
|
||||
rearranged by dragging the blocks around if needed. Clicking the top-right button in block mode will switch back to
|
||||
text mode, and switching between block and text mode will automatically translate your script as well.
|
||||
Note that scripts can only be converted into block mode if they have no errors!
|
||||
you are unfamiliar with programming. To enter commands in block mode, select the command block pane on the right and
|
||||
drag the box for the relevant command into the script pane and drop it where you want the command to go. Commands can be
|
||||
freely rearranged by dragging the blocks around if needed.
|
||||
<br>
|
||||
<br>
|
||||
Clicking the top-right button in block mode will switch back to text mode, and switching between block and text mode
|
||||
will automatically translate your script as well. If you have a script in text mode which has errors, the Automator
|
||||
may not be able to figure out what blocks to convert the lines with errors into. This may result in part of your
|
||||
script being lost if you attempt to convert a text script with errors into a bock script.
|
||||
<br>
|
||||
<br>
|
||||
Just like your entire savefile, individual Automator scripts can be imported and exported from the game.
|
||||
|
@ -1447,6 +1447,15 @@ GameStorage.devMigrations = {
|
||||
}
|
||||
player.reality.automator.scripts[key].content = lines.join("\n");
|
||||
}
|
||||
|
||||
// Migrate IDs for all saves made during wave 3 testing, to prevent odd overwriting behavior on importing
|
||||
const newScripts = {};
|
||||
const oldScriptKeys = Object.keys(player.reality.automator.scripts);
|
||||
for (let newID = 1; newID <= oldScriptKeys.length; newID++) {
|
||||
newScripts[newID] = player.reality.automator.scripts[oldScriptKeys[newID - 1]];
|
||||
newScripts[newID].id = newID;
|
||||
}
|
||||
player.reality.automator.scripts = newScripts;
|
||||
}
|
||||
],
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
--color-blockmator-block-background: #f5f5f5;
|
||||
--color-blockmator-block-command: #401090;
|
||||
--color-blockmator-block-required: #50aaaa;
|
||||
--color-blockmator-block-optional: #bbbbbb;
|
||||
--color-blockmator-block-optional: #684700;
|
||||
--color-blockmator-editor-background: white;
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
--color-blockmator-block-background: #000115;
|
||||
--color-blockmator-block-command: #a142ff;
|
||||
--color-blockmator-block-required: #005050;
|
||||
--color-blockmator-block-optional: #555555;
|
||||
--color-blockmator-block-optional: #684700;
|
||||
--color-blockmator-editor-background: black;
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,9 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// This modal is used by both study importing and preset editing but only has a prop actually passed in when
|
||||
// editing (which is the preset index). Needs to be an undefined check because index can be zero
|
||||
// This modal is used by both study importing and preset editing, but is given an id of -1 when importing
|
||||
isImporting() {
|
||||
return this.id === undefined;
|
||||
return this.id === -1;
|
||||
},
|
||||
// This represents the state reached from importing into an empty tree
|
||||
importedTree() {
|
||||
|
@ -38,19 +38,7 @@ export default {
|
||||
this.isCurrentlyBlocks = player.reality.automator.type === AUTOMATOR_TYPE.BLOCK;
|
||||
},
|
||||
toggleAutomatorMode() {
|
||||
const scriptID = this.currentScriptID;
|
||||
Tutorial.moveOn(TUTORIAL_STATE.AUTOMATOR);
|
||||
if (this.isCurrentlyBlocks) {
|
||||
// This saves the script after converting it.
|
||||
BlockAutomator.parseTextFromBlocks();
|
||||
player.reality.automator.type = AUTOMATOR_TYPE.TEXT;
|
||||
} else {
|
||||
const toConvert = AutomatorTextUI.editor.getDoc().getValue();
|
||||
// Needs to be called to update the lines prop in the BlockAutomator object
|
||||
BlockAutomator.fromText(toConvert);
|
||||
AutomatorBackend.saveScript(scriptID, toConvert);
|
||||
player.reality.automator.type = AUTOMATOR_TYPE.BLOCK;
|
||||
}
|
||||
AutomatorBackend.changeModes(this.currentScriptID);
|
||||
this.callback?.();
|
||||
}
|
||||
}
|
||||
@ -73,7 +61,8 @@ export default {
|
||||
commands.
|
||||
<b>
|
||||
Warning: If these errors are caused by malformed loops or IFs, this may end up deleting large portions of
|
||||
your script! Changing editor modes currently will delete {{ quantifyInt("block", lostBlocks) }}!
|
||||
your script! Changing editor modes currently will cause {{ quantifyInt("line", lostBlocks) }} of code to be
|
||||
lost!
|
||||
</b>
|
||||
</div>
|
||||
<br>
|
||||
|
@ -24,6 +24,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
BlockAutomator.initialize();
|
||||
AutomatorData.recalculateErrors();
|
||||
BlockAutomator.editor.scrollTo(0, BlockAutomator.previousScrollPosition);
|
||||
BlockAutomator.gutter.style.bottom = `${BlockAutomator.editor.scrollTop}px`;
|
||||
},
|
||||
|
@ -234,7 +234,6 @@ export default {
|
||||
}
|
||||
this.recalculateErrorCount();
|
||||
},
|
||||
|
||||
// This gets called whenever blocks are changed, but we also need to halt execution if the currently visible script
|
||||
// is also the one being run
|
||||
recalculateErrorCount() {
|
||||
@ -246,10 +245,17 @@ export default {
|
||||
},
|
||||
errorTooltip() {
|
||||
if (!this.hasError || this.suppressTooltip) return undefined;
|
||||
|
||||
// We want to keep the verbose error info for the error panel, but we need to shorten it for the tooltips here
|
||||
// The problematic errors all seem to have the same format, which we can explicitly modify
|
||||
let errorInfo = this.errors.find(e => e.startLine === this.lineNumber).info;
|
||||
errorInfo = errorInfo
|
||||
.replaceAll("\n", "")
|
||||
.replace(/Expecting: one of these possible Token sequences:.*but found: (.*)/ui, "Unexpected input format: $1");
|
||||
return {
|
||||
content:
|
||||
`<div class="c-block-automator-error">
|
||||
<div>${this.errors.find(e => e.startLine === this.lineNumber).info}</div>
|
||||
<div>${errorInfo}</div>
|
||||
</div>`,
|
||||
html: true,
|
||||
trigger: "manual",
|
||||
@ -298,7 +304,7 @@ export default {
|
||||
v-model="textContents"
|
||||
v-tooltip="errorTooltip()"
|
||||
:class="textInputClassObject()"
|
||||
@keyup="validateInput()"
|
||||
@keyup="changeBlock()"
|
||||
@focusin="handleFocus(true)"
|
||||
@focusout="handleFocus(false)"
|
||||
>
|
||||
|
@ -197,7 +197,7 @@ export const automatorBlocksMap = automatorBlocks.mapToObject(b => b.cmd, b => b
|
||||
</p>
|
||||
<br>
|
||||
<p>
|
||||
Inputs with a <span class="c-automator-input-optional">gray</span> color are optional, while inputs with a
|
||||
Inputs with a <span class="c-automator-input-optional">brown</span> color are optional, while inputs with a
|
||||
<span class="c-automator-input-required">teal</span> color are required. For more details, check the Scripting
|
||||
Information pane.
|
||||
</p>
|
||||
|
@ -13,7 +13,13 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
maxConstantCount() {
|
||||
return 30;
|
||||
return AutomatorData.MAX_ALLOWED_CONSTANT_COUNT;
|
||||
},
|
||||
maxNameLength() {
|
||||
return AutomatorData.MAX_ALLOWED_CONSTANT_NAME_LENGTH;
|
||||
},
|
||||
maxValueLength() {
|
||||
return AutomatorData.MAX_ALLOWED_CONSTANT_VALUE_LENGTH;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@ -29,7 +35,8 @@ export default {
|
||||
<div class="l-panel-padding">
|
||||
This panel allows you to define case-sensitive constant values which can be used in place of numbers or Time Study
|
||||
import strings. These definitions are shared across all of your scripts and are limited to a maximum of
|
||||
{{ maxConstantCount }} defined constants.
|
||||
{{ maxConstantCount }} defined constants. Additionally, constant names and values are limited to lengths of
|
||||
{{ maxNameLength }} and {{ maxValueLength }} characters respectively.
|
||||
<br>
|
||||
<br>
|
||||
As a usage example, defining
|
||||
@ -59,6 +66,7 @@ export default {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: solid 0.1rem var(--color-automator-docs-font);
|
||||
border-radius: var(--var-border-radius, 0.5rem);
|
||||
padding: 0.5rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
@ -14,6 +14,14 @@ export default {
|
||||
valueString: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
maxNameLength() {
|
||||
return AutomatorData.MAX_ALLOWED_CONSTANT_NAME_LENGTH;
|
||||
},
|
||||
maxValueLength() {
|
||||
return AutomatorData.MAX_ALLOWED_CONSTANT_VALUE_LENGTH;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.aliasString = this.constant;
|
||||
this.oldAlias = this.aliasString;
|
||||
@ -34,7 +42,6 @@ export default {
|
||||
return matchObj ? matchObj[0] === this.aliasString : false;
|
||||
});
|
||||
|
||||
if (this.aliasString.length >= 20) return "Constant name must be shorter than 20 characters";
|
||||
if (!isValidName) return "Constant name must be alphanumeric and cannot start with a number";
|
||||
if (alreadyExists) return "You have already defined a constant with this name";
|
||||
if (hasCommandConflict) return "Constant name conflicts with a command key word";
|
||||
@ -43,11 +50,9 @@ export default {
|
||||
|
||||
const isNumber = this.valueString.match(/^-?(0|[1-9]\d*)(\.\d+)?([eE][+-]?\d+)?$/u);
|
||||
// Note: Does not do validation for studies existing
|
||||
const isStudyString = this.valueString.match(/^\d{2,3}(,\d{2,3})*(\|\d\d?)?$/u);
|
||||
const isStudyString = TimeStudyTree.isValidImportString(this.valueString);
|
||||
|
||||
if (!isNumber && !isStudyString) return "Constant value must either be a number or Time Study string";
|
||||
// Note that a study string with ALL studies is ~230 characters
|
||||
if (this.valueString.length >= 250) return "Constant value must be shorter than 250 characters";
|
||||
return null;
|
||||
},
|
||||
errorTooltip() {
|
||||
@ -85,7 +90,9 @@ export default {
|
||||
<input
|
||||
v-model="aliasString"
|
||||
class="c-define-textbox c-alias"
|
||||
:class="{ 'l-limit-textbox' : aliasString.length === maxNameLength }"
|
||||
placeholder="New constant..."
|
||||
:maxlength="maxNameLength"
|
||||
@focusin="handleFocus(true)"
|
||||
@focusout="handleFocus(false)"
|
||||
>
|
||||
@ -100,7 +107,9 @@ export default {
|
||||
v-if="aliasString"
|
||||
v-model="valueString"
|
||||
class="c-define-textbox c-value"
|
||||
:class="{ 'l-limit-textbox' : valueString && valueString.length === maxValueLength }"
|
||||
placeholder="Value for constant..."
|
||||
:maxlength="maxValueLength"
|
||||
@focusin="handleFocus(true)"
|
||||
@focusout="handleFocus(false)"
|
||||
>
|
||||
@ -115,6 +124,9 @@ export default {
|
||||
}
|
||||
|
||||
.o-arrow-padding {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
@ -133,11 +145,16 @@ export default {
|
||||
background: var(--color-automator-error-background);
|
||||
}
|
||||
|
||||
.l-limit-textbox {
|
||||
border-style: dotted;
|
||||
border-color: var(--color-automator-error-outline);
|
||||
}
|
||||
|
||||
.c-alias {
|
||||
width: 14rem;
|
||||
min-width: 14.5rem;
|
||||
}
|
||||
|
||||
.c-value {
|
||||
width: 30rem;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
@ -63,7 +63,7 @@ export default {
|
||||
},
|
||||
nameTooltip() {
|
||||
return this.isNameTooLong
|
||||
? `Names cannot be longer than ${formatInt(this.maxScriptNameLength)} characters!`
|
||||
? `Names cannot be longer than ${formatInt(AutomatorData.MAX_ALLOWED_SCRIPT_NAME_LENGTH)} characters!`
|
||||
: "";
|
||||
},
|
||||
currentScriptID: {
|
||||
@ -89,14 +89,14 @@ export default {
|
||||
maxTotalChars() {
|
||||
return AutomatorData.MAX_ALLOWED_TOTAL_CHARACTERS;
|
||||
},
|
||||
maxScriptNameLength() {
|
||||
return 15;
|
||||
},
|
||||
maxScriptCount() {
|
||||
return 20;
|
||||
return AutomatorData.MAX_ALLOWED_SCRIPT_COUNT;
|
||||
},
|
||||
panelEnum() {
|
||||
return AutomatorPanels;
|
||||
},
|
||||
importTooltip() {
|
||||
return this.canMakeNewScript ? "Import automator script" : "You have too many scripts to import another!";
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -138,6 +138,7 @@ export default {
|
||||
}
|
||||
},
|
||||
importScript() {
|
||||
if (!this.canMakeNewScript) return;
|
||||
Modal.importScript.show();
|
||||
},
|
||||
onGameLoad() {
|
||||
@ -201,7 +202,7 @@ export default {
|
||||
let newName = "";
|
||||
if (trimmed.length === 2 && trimmed[1].length > 0) newName = trimmed[1];
|
||||
|
||||
if (newName.length > this.maxScriptNameLength) {
|
||||
if (newName.length > AutomatorData.MAX_ALLOWED_SCRIPT_NAME_LENGTH) {
|
||||
this.isNameTooLong = true;
|
||||
return;
|
||||
}
|
||||
@ -290,8 +291,9 @@ export default {
|
||||
@click="exportScript"
|
||||
/>
|
||||
<AutomatorButton
|
||||
v-tooltip="'Import automator script'"
|
||||
v-tooltip="importTooltip"
|
||||
class="fa-file-import"
|
||||
:class="{ 'c-automator__status-text--error' : !canMakeNewScript }"
|
||||
@click="importScript"
|
||||
/>
|
||||
<div class="l-automator__script-names">
|
||||
|
@ -1,6 +1,4 @@
|
||||
<script>
|
||||
import { AutomatorPanels } from "./AutomatorDocs";
|
||||
|
||||
export default {
|
||||
name: "AutomatorModeSwitch",
|
||||
data() {
|
||||
@ -65,38 +63,25 @@ export default {
|
||||
},
|
||||
toggleAutomatorMode() {
|
||||
const currScript = player.reality.automator.scripts[this.currentScriptID].content;
|
||||
const hasInvalidCommands = BlockAutomator.hasUnparsableCommands(currScript);
|
||||
const hasInvalidCommands = BlockAutomator.hasUnparsableCommands(currScript) &&
|
||||
this.automatorType === AUTOMATOR_TYPE.TEXT;
|
||||
|
||||
// While we normally have the player option override the modal, script deletion due to failed parsing can have a
|
||||
// big enough adverse impact on the gameplay experience that we force the modal here regardless of the setting
|
||||
if (hasInvalidCommands || (player.options.confirmations.switchAutomatorMode && AutomatorBackend.isRunning)) {
|
||||
const blockified = AutomatorGrammar.blockifyTextAutomator(currScript);
|
||||
|
||||
// We explicitly pass in 0 for lostBlocks if converting from block to text since nothing is ever lost in that
|
||||
// conversion direction
|
||||
const lostBlocks = this.automatorType === AUTOMATOR_TYPE.TEXT
|
||||
? blockified.validatedBlocks - blockified.visitedBlocks
|
||||
: 0;
|
||||
Modal.switchAutomatorEditorMode.show({
|
||||
callBack: () => this.$recompute("currentScriptContent"),
|
||||
lostBlocks: blockified.validatedBlocks - blockified.visitedBlocks,
|
||||
lostBlocks,
|
||||
});
|
||||
} else {
|
||||
const scriptID = this.currentScriptID;
|
||||
Tutorial.moveOn(TUTORIAL_STATE.AUTOMATOR);
|
||||
if (this.automatorType === AUTOMATOR_TYPE.BLOCK) {
|
||||
// This saves the script after converting it.
|
||||
BlockAutomator.parseTextFromBlocks();
|
||||
player.reality.automator.type = AUTOMATOR_TYPE.TEXT;
|
||||
if (player.reality.automator.currentInfoPane === AutomatorPanels.BLOCKS) {
|
||||
player.reality.automator.currentInfoPane = AutomatorPanels.COMMANDS;
|
||||
}
|
||||
// Don't use this.currentScriptContent here due to reactivity issues, but on the other hand reactively
|
||||
// updating content might lead to decreased performance.
|
||||
} else {
|
||||
const toConvert = AutomatorTextUI.editor.getDoc().getValue();
|
||||
// Needs to be called to update the lines prop in the BlockAutomator object
|
||||
BlockAutomator.fromText(toConvert);
|
||||
AutomatorBackend.saveScript(scriptID, toConvert);
|
||||
player.reality.automator.type = AUTOMATOR_TYPE.BLOCK;
|
||||
player.reality.automator.currentInfoPane = AutomatorPanels.BLOCKS;
|
||||
}
|
||||
this.$recompute("currentScriptContent");
|
||||
AutomatorHighlighter.clearAllHighlightedLines();
|
||||
AutomatorBackend.changeModes(this.currentScriptID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ export default {
|
||||
</PrimaryButton>
|
||||
<PrimaryButton
|
||||
class="o-primary-btn--subtab-option"
|
||||
onclick="Modal.studyString.show()"
|
||||
onclick="Modal.studyString.show({ id: -1 })"
|
||||
>
|
||||
Import tree
|
||||
</PrimaryButton>
|
||||
|
Loading…
Reference in New Issue
Block a user