diff --git a/src/lib/Toolbox/Toolbox.xml b/src/lib/Toolbox/Toolbox.xml index 13b5b91..2e348c8 100644 --- a/src/lib/Toolbox/Toolbox.xml +++ b/src/lib/Toolbox/Toolbox.xml @@ -3,6 +3,8 @@ + + @@ -16,6 +18,8 @@ + + @@ -43,6 +47,7 @@ + @@ -181,10 +186,18 @@ - + - + + + + hello world! + + + + + diff --git a/src/resources/blocks/control.js b/src/resources/blocks/control.js index 37c9eb4..cd05208 100644 --- a/src/resources/blocks/control.js +++ b/src/resources/blocks/control.js @@ -75,6 +75,60 @@ function register() { return `${code}\n`; }) + registerBlock(`${categoryPrefix}while`, { + message0: 'while %1 do %2 %3', + args0: [ + { + "type": "input_value", + "name": "CONDITION", + "check": "Boolean" + }, + { + "type": "input_dummy" + }, + { + "type": "input_statement", + "name": "BLOCKS" + } + ], + previousStatement: null, + nextStatement: null, + inputsInline: true, + colour: categoryColor + }, (block) => { + const CONDITION = javascriptGenerator.valueToCode(block, 'CONDITION', javascriptGenerator.ORDER_ATOMIC); + const BLOCKS = javascriptGenerator.statementToCode(block, 'BLOCKS'); + const code = `do { ${BLOCKS} } while (${CONDITION})`; + return `${code}\n`; + }) + + registerBlock(`${categoryPrefix}until`, { + message0: 'until %1 do %2 %3', + args0: [ + { + "type": "input_value", + "name": "CONDITION", + "check": "Boolean" + }, + { + "type": "input_dummy" + }, + { + "type": "input_statement", + "name": "BLOCKS" + } + ], + previousStatement: null, + nextStatement: null, + inputsInline: true, + colour: categoryColor + }, (block) => { + const CONDITION = javascriptGenerator.valueToCode(block, 'CONDITION', javascriptGenerator.ORDER_ATOMIC); + const BLOCKS = javascriptGenerator.statementToCode(block, 'BLOCKS'); + const code = `do { ${BLOCKS} } while (!(${CONDITION}))`; + return `${code}\n`; + }) + // if <> then {} registerBlock(`${categoryPrefix}ifthen`, { message0: 'if %1 then %2 %3', diff --git a/src/resources/blocks/events.js b/src/resources/blocks/events.js index bb8c529..3222db9 100644 --- a/src/resources/blocks/events.js +++ b/src/resources/blocks/events.js @@ -171,6 +171,90 @@ function register() { const code = `setTimeout(async () => { ${BLOCKS} }, (${TIME} * 1000));`; return `${code}\n`; }) + + registerBlock(`${categoryPrefix}whenkeypressed`, { + message0: 'when %1 key is down %2 %3', + args0: [ + { + "type": "field_dropdown", + "name": "KEY", + "options": keyBoard + }, + { + "type": "input_dummy" + }, + { + "type": "input_statement", + "name": "BLOCKS" + } + ], + nextStatement: null, + inputsInline: true, + colour: categoryColor, + }, (block) => { + const KEY = block.getFieldValue('KEY') + const BLOCKS = javascriptGenerator.statementToCode(block, 'BLOCKS'); + const code = `window.addEventListener("keydown", event => { + ${KEY===""?`${BLOCKS}`:`if (event.keyCode == '${KEY}') { ${BLOCKS}}`}});`; + return `${code}\n`; + }) } +const keyBoard = [ + ["ANY", ""], + ["SPACE", "32"], + ["UP ARROW", "38"], + ["DOWN ARROW", "40"], + ["LEFT ARROW", "37"], + ["RIGHT ARROW", "39"], + ["A", "65"], + ["B", "66"], + ["C", "67"], + ["D", "68"], + ["E", "69"], + ["F", "70"], + ["G", "71"], + ["H", "72"], + ["I", "73"], + ["J", "74"], + ["K", "75"], + ["L", "76"], + ["M", "77"], + ["N", "78"], + ["O", "79"], + ["P", "80"], + ["Q", "81"], + ["R", "82"], + ["S", "83"], + ["T", "84"], + ["U", "85"], + ["V", "86"], + ["W", "87"], + ["X", "88"], + ["Y", "89"], + ["Z", "90"], + ["0", "48"], + ["1", "49"], + ["2", "50"], + ["3", "51"], + ["4", "52"], + ["5", "53"], + ["6", "54"], + ["7", "55"], + ["8", "56"], + ["9", "57"], + ["F1", "112"], + ["F2", "113"], + ["F3", "114"], + ["F4", "115"], + ["F5", "116"], + ["F6", "117"], + ["F7", "118"], + ["F8", "119"], + ["F9", "120"], + ["F10", "121"], + ["F11", "122"], + ["F12", "123"], +]; + export default register; diff --git a/src/resources/blocks/player.js b/src/resources/blocks/player.js index 8c08f4b..cb7274d 100644 --- a/src/resources/blocks/player.js +++ b/src/resources/blocks/player.js @@ -76,7 +76,7 @@ function register() { const MENU2 = block.getFieldValue('MENU2'); return [`ModAPI.player?ModAPI.player.dimension===${MENU2}:""`, javascriptGenerator.ORDER_ATOMIC]; }) - + registerBlock(`${categoryPrefix}username`, { message0: 'username', args0: [], @@ -325,7 +325,245 @@ function register() { }) - registerBlock(`${categoryPrefix}keypressed`, { + registerBlock(`${categoryPrefix}setpropertyboolean`, { + message0: 'set player property %1 to %2', + args0: [ + { + "type": "field_dropdown", + "name": "PROPERTIES", + "options": [ + [ "is dead", "isdead" ], + [ "is invisible", "isinvisible" ], + [ "is in web", "isinweb" ], + [ "is sprinting", "issprinting" ], + [ "is sneaking", "issneaking" ], + [ "is silent", "issilent" ], + [ "can edit", "canedit" ], + ] + }, + { + "type": "input_value", + "name": "BOOLEAN", + "check": "Boolean" + }, + ], + previousStatement: null, + nextStatement: null, + inputsInline: true, + colour: categoryColor + }, (block) => { + const PROPERTY = block.getFieldValue('PROPERTIES'); + let BOOLEAN = javascriptGenerator.valueToCode(block, 'BOOLEAN', javascriptGenerator.ORDER_ATOMIC); + BOOLEAN = BOOLEAN ? `${Boolean(BOOLEAN)}` : 'false' + let code; + if (PROPERTY === "isdead") { + code = (BOOLEAN==="true"?`ModAPI.player.setDead()`:''); + } else if (PROPERTY === "isinvisible") { + code = `ModAPI.player.setInvisible({invisible: ${BOOLEAN}})` + } else if (PROPERTY === "isinweb") { + code = `ModAPI.player.setInWeb(${BOOLEAN})` + } else if (PROPERTY === "issprinting") { + code = `ModAPI.player.setSprinting({flag: ${BOOLEAN}})` + } else if (PROPERTY === "issneaking") { + code = `ModAPI.player.setSneaking({sneaking: ${BOOLEAN}})` + } else if (PROPERTY === "issilent") { + code = `ModAPI.player.setSilent({isSilent: ${BOOLEAN}})` + } else if (PROPERTY === "canedit") { + code = `ModAPI.player.allowEdit(${BOOLEAN})` + } + return code; + }) + + registerBlock(`${categoryPrefix}getpropertyboolean`, { + message0: "get player property %1", + args0: [ + { + "type": "field_dropdown", + "name": "PROPERTIES", + "options": [ + [ "is dead", "isdead" ], + [ "is invisible", "isinvisible" ], + [ "is in web", "isinweb" ], + [ "is sprinting", "issprinting" ], + [ "is sneaking", "issneaking" ], + [ "is silent", "issilent" ], + [ "can edit", "canedit" ], + [ "on ground", "onground" ], + [ "is moving", "ismoving" ], + ] + }, + ], + output: "Boolean", + inputsInline: true, + colour: categoryColor + }, (block) => { + const PROPERTY = block.getFieldValue('PROPERTIES'); + let code; + if (PROPERTY === "isdead") { + code = 'ModAPI.player.isDead'; + } else if (PROPERTY === "isinvisible") { + code = `ModAPI.player.isInvisible()` + } else if (PROPERTY === "isinweb") { + code = `ModAPI.player.isInWeb` + } else if (PROPERTY === "issprinting") { + code = `ModAPI.player.isSprinting()` + } else if (PROPERTY === "issneaking") { + code = `ModAPI.player.isSneaking()` + } else if (PROPERTY === "issilent") { + code = `ModAPI.player.isSilent()` + } else if (PROPERTY === "canedit") { + code = `ModAPI.player.isAllowEdit()` + } else if (PROPERTY === "onground") { + code = `ModAPI.player.onGround` + } else if (PROPERTY === "isdead") { + code = `ModAPI.player.isDead` + } else if (PROPERTY === "ismoving") { + code = `ModAPI.player.isMoving()` + } + return code; + }) + + registerBlock(`${categoryPrefix}setpropertynumber`, { + message0: 'set player property %1 to %2', + args0: [ + { + "type": "field_dropdown", + "name": "PROPERTIES", + "options": [ + [ "X position", "xposition"], + [ "Y position", "yposition"], + [ "Z position", "zposition"], + [ "X motion", "Xmotion"], + [ "Y motion", "Ymotion"], + [ "Z motion", "Zmotion"], + [ "food level", "foodLevel" ], + [ "food saturation level", "foodSaturationLevel" ], + [ "experience", "experience" ], + [ "experience level", "experiencelevel" ], + [ "walk speed", "walkspeed" ], + ] + }, + { + "type": "input_value", + "name": "INPUT", + "check": "Number" + } + ], + previousStatement: null, + nextStatement: null, + inputsInline: true, + colour: categoryColor + }, (block) => { + const PROPERTY = block.getFieldValue('PROPERTIES'); + let INPUT = javascriptGenerator.valueToCode(block, 'INPUT', javascriptGenerator.ORDER_ATOMIC); + if (INPUT == "") { + INPUT = 0; + } + let code; + if (PROPERTY === "foodLevel") { + code = `ModAPI.player.setFoodLevel({foodLevelIn: Math.round(${INPUT})})`; + } else if (PROPERTY === "foodSaturationLevel") { + code = `ModAPI.player.setFoodSaturationLevel({foodSaturationLevelIn: ${INPUT}})` + } else if (PROPERTY.indexOf('position') === 1) { + code = `ModAPI.player.${PROPERTY.charAt(0)} = ${INPUT}` + } else if (PROPERTY.indexOf('motion') === 1) { + code = `ModAPI.player.motion${PROPERTY.charAt(0)} = ${INPUT}` + } else if (PROPERTY === "experience") { + code = `ModAPI.player.experience = ${INPUT}`; + } else if (PROPERTY === "experiencelevel") { + code = `ModAPI.player.experienceLevel = ${INPUT}`; + } else if (PROPERTY === "walkspeed") { + code = `ModAPI.player.setSpeed({speed: Math.round(${INPUT})})`; + } + return code+';ModAPI.player.reload();'; + }) + + registerBlock(`${categoryPrefix}getpropertynumber`, { + message0: "get player property %1", + args0: [ + { + "type": "field_dropdown", + "name": "PROPERTIES", + "options": [ + [ "food level", "foodLevel" ], + [ "food saturation level", "foodSaturationLevel" ], + [ "experience", "experience" ], + [ "experience level", "experiencelevel" ], + [ "fall distance", "falldistance" ], + [ "total armor protection", "armorprotection" ], + [ "walk speed", "walkspeed" ], + ] + }, + ], + output: "Number", + inputsInline: true, + colour: categoryColor + }, (block) => { + const PROPERTY = block.getFieldValue('PROPERTIES'); + let code; + if (PROPERTY === "foodLevel") { + code = 'ModAPI.player.foodStats.foodLevel'; + } else if (PROPERTY === "foodSaturationLevel") { + code = `ModAPI.player.foodStats.foodSaturationLevel` + } else if (PROPERTY === "experience") { + code = `ModAPI.player.experience` + } else if (PROPERTY === "experiencelevel") { + code = `ModAPI.player.experienceLevel` + } else if (PROPERTY === "falldistance") { + code = `ModAPI.player.fallDistance` + } else if (PROPERTY === "walkspeed") { + code = `ModAPI.player.getSpeed()` + } else if (PROPERTY === "armorprotection") { + code = `ModAPI.player.getTotalArmorValue()` + } + + return [code, javascriptGenerator.ORDER_ATOMIC]; + }) + + registerBlock(`${categoryPrefix}execommand`, { + message0: 'execute command %1 as player', + args0: [ + { + "type": "input_value", + "name": "COMMAND" + } + ], + previousStatement: null, + nextStatement: null, + inputsInline: true, + colour: categoryColor + }, (block) => { + const COMMAND = javascriptGenerator.valueToCode(block, 'COMMAND', javascriptGenerator.ORDER_ATOMIC); + const code = ` + if (${COMMAND}.charAt(0)==="/") { + ModAPI.player.sendChatMessage({message: ${COMMAND}}) + }`; + return `${code}\n`; + }) + + registerBlock(`${categoryPrefix}sendchat`, { + message0: 'send %1 message in chat', + args0: [ + { + "type": "input_value", + "name": "COMMAND" + } + ], + previousStatement: null, + nextStatement: null, + inputsInline: true, + colour: categoryColor + }, (block) => { + const COMMAND = javascriptGenerator.valueToCode(block, 'COMMAND', javascriptGenerator.ORDER_ATOMIC); + const code = ` + if (${COMMAND}.charAt(0)!=="/") { + ModAPI.player.sendChatMessage({message: ${COMMAND}}) + }`; + return `${code}\n`; + }) + + + registerBlock(`${categoryPrefix}whengamekeypressed`, { message0: 'when in game key %1 pressed do %2 %3', args0: [ { @@ -355,9 +593,9 @@ function register() { const keyBoard = [ ["SPACE", "57"], ["UP ARROW", "200"], - ["UP DOWN", "208"], - ["UP LEFT", "203"], - ["UP RIGHT", "205"], + ["DOWN ARROW", "208"], + ["LEFT ARROW", "203"], + ["RIGHT ARROW", "205"], ["A", "30"], ["B", "48"], ["C", "46"], diff --git a/src/resources/blocks/sensing.js b/src/resources/blocks/sensing.js index f6fc90d..54a8937 100644 --- a/src/resources/blocks/sensing.js +++ b/src/resources/blocks/sensing.js @@ -133,8 +133,81 @@ function register() { }, (block) => { return [`ModAPI.getFPS()`, javascriptGenerator.ORDER_ATOMIC]; }) + + registerBlock(`${categoryPrefix}keypressed`, { + message0: "is key %1 pressed?", + args0: [ + { + "type": "field_dropdown", + "name": "KEY2", + "options": keyBoard + }, + ], + output: "Boolean", + inputsInline: true, + colour: categoryColor + }, (block) => { + const KEY2 = block.getFieldValue('KEY2'); + return [`pressedKeys[${KEY2}]===true?true:false`, javascriptGenerator.ORDER_ATOMIC]; + }) } +const keyBoard = [ + ["SPACE", "32"], + ["UP ARROW", "38"], + ["DOWN ARROW", "40"], + ["LEFT ARROW", "37"], + ["RIGHT ARROW", "39"], + ["A", "65"], + ["B", "66"], + ["C", "67"], + ["D", "68"], + ["E", "69"], + ["F", "70"], + ["G", "71"], + ["H", "72"], + ["I", "73"], + ["J", "74"], + ["K", "75"], + ["L", "76"], + ["M", "77"], + ["N", "78"], + ["O", "79"], + ["P", "80"], + ["Q", "81"], + ["R", "82"], + ["S", "83"], + ["T", "84"], + ["U", "85"], + ["V", "86"], + ["W", "87"], + ["X", "88"], + ["Y", "89"], + ["Z", "90"], + ["0", "48"], + ["1", "49"], + ["2", "50"], + ["3", "51"], + ["4", "52"], + ["5", "53"], + ["6", "54"], + ["7", "55"], + ["8", "56"], + ["9", "57"], + ["F1", "112"], + ["F2", "113"], + ["F3", "114"], + ["F4", "115"], + ["F5", "116"], + ["F6", "117"], + ["F7", "118"], + ["F8", "119"], + ["F9", "120"], + ["F10", "121"], + ["F11", "122"], + ["F12", "123"], +]; + Blockly.Extensions.register('single_character_validation', function() { this.getField('KEY').setValidator(function(newValue) { return newValue.substring(Math.max(newValue.length - 1, 0),newValue.length); diff --git a/src/resources/compiler/index.js b/src/resources/compiler/index.js index 39f0b56..9fc38f2 100644 --- a/src/resources/compiler/index.js +++ b/src/resources/compiler/index.js @@ -14,9 +14,14 @@ class Compiler { if (code.indexOf('ModAPI.player') > -1) { start+= "ModAPI.require('player');"; } - if (code.indexOf('variables["') > -1) { + if (code.indexOf('variables[') > -1) { start+= 'let variables = [];'; } + if (code.indexOf('pressedKeys[') > -1) { + start+= `var pressedKeys = {}; + window.onkeyup = function(e) { pressedKeys[e.keyCode] = false; } + window.onkeydown = function(e) { pressedKeys[e.keyCode] = true; }`; + } if (code.indexOf('document.createElement("eaglerpage")') > -1) { let style = "width:100%; height: 100%; position: fixed; top: 0; left: 0; z-index: 10; color: white; font-family: Minecraftia, sans-serif; overflow-y: scroll; overflow-x: hidden; background-image: url(data:image/png;base64,UklGRhoBAABXRUJQVlA4TA0BAAAvn8AnAIWjtpEECdnA2N0DsTROy7xUqfrWw0jbyLkJKTz0+I20jTT/Bo89e1YR/Wfktm0Y+wNKLobT7QP/n/B7Z/naW26QHoTpHB7LFouyKHlzeHxfCStSuj9KdbC8z1IJ5iWiyQed48vtYJ+lUu0t4VwranS1XMIutSiLYlbb8G54uf2p3VPSfRZtSrlsPFjOzZZrd/us3B3uK+HcHJQql+xbLMrS/WqNpm6DeZ/VIPVYaN/KzUbp91nd9xl5pYu50dU2W417nbdTj5l2Ne92uM9qXNpyf6+oXkabHKXaZ1HS4Iaqpim+1KIJ+0M49/LjNbTGP5mrrMZEuc7Uzcb1ViOJ6TuOt4NGJs+zDgA=); background-color: rgb(60,60,60); background-blend-mode: multiply; background-size: 64px; ".replaceAll('; ', ';\n ') start+= `