Last active
April 24, 2019 21:36
-
-
Save tombailey/e1e2a06b7507937b573706a6ef056789 to your computer and use it in GitHub Desktop.
Tested on Minecraft BE v1.11.0 for Windows 10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| sources/handlers are of the form: | |
| when SOME_EVENT "POTENTIALLY A PARAMETER HERE", SOME_ACTION "POTENTIALLY A PARAMETER HERE" | |
| As an example, the following will send a chat message saying "Hello world" when a player first enters a world: | |
| when player enters world, send chat message "Hello world" | |
| Since sources/handlers are strings of text, you can either use single quotes when creating your string literal or simply escape the nested double quote of any parameter. For example: | |
| const sources = ['when player enters world, send chat message "Hello world"']; | |
| Or: | |
| const sources = ["when player enters world, send chat message \"Hello world\""]; | |
| At this early stage, the only supported events are: | |
| player enters world | |
| and | |
| player looks at mob "minecraft:pig" | |
| The only supported actions are: | |
| send chat message "Hello world" | |
| and | |
| spawn particle "minecraft:mobflame_emitter" at position "0 70 0" | |
| If any of this peaks your interest and you want to discuss it further tweet me, @tombailey64 on twitter |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //Super early preview of a parsing script for Minecraft Bedrock edition | |
| //Just edit "const sources = [...]" to create a mod with no JavaScript knowledge required | |
| //of course you need to know the syntax for sources (see the description for this gist) | |
| //comments, questions, tweet me @tombailey64 on twitter | |
| const clientSystem = client.registerSystem(0, 0); | |
| class Controller { | |
| constructor() { | |
| this.eventNameToHandler = { | |
| [Controller.EVENT_PLAYER_ENTERS_WORLD]: [], | |
| [Controller.EVENT_PLAYER_LOOKS_AT_MOB]: [], | |
| }; | |
| } | |
| add(event, action) { | |
| this.eventNameToHandler[event.name].push({ | |
| event, | |
| action, | |
| }); | |
| } | |
| invokeAction(action) { | |
| Controller.ACTIONS[action.name] | |
| .implementation | |
| .apply(undefined, action.params); | |
| } | |
| onPlayerEnterWorld() { | |
| this.eventNameToHandler[Controller.EVENT_PLAYER_ENTERS_WORLD].forEach((handler) => { | |
| this.invokeAction(handler.action); | |
| }); | |
| } | |
| onHitResultChanged(eventData) { | |
| if (eventData.entity.__type__ == "entity") { | |
| const identifier = eventData.entity.__identifier__; | |
| this.eventNameToHandler[Controller.EVENT_PLAYER_LOOKS_AT_MOB].forEach((handler) => { | |
| if (handler.event.params[0] == identifier) { | |
| this.invokeAction(handler.action); | |
| } | |
| }); | |
| } | |
| } | |
| } | |
| Controller.EVENT_PLAYER_ENTERS_WORLD = "player enters world"; | |
| Controller.EVENT_PLAYER_LOOKS_AT_MOB = "player looks at mob"; | |
| Controller.EVENTS = { | |
| [Controller.EVENT_PLAYER_ENTERS_WORLD]: { | |
| paramsLength: 0, | |
| }, | |
| [Controller.EVENT_PLAYER_LOOKS_AT_MOB]: { | |
| paramsLength: 1, | |
| }, | |
| }; | |
| //TODO: figure out where to put this | |
| function parsePosition(position) { | |
| const coordinates = position.split(" "); | |
| if (coordinates.length != 3) { | |
| throw `Invalid position, 3 coordinates were expected but only ${coordinates.length} were given`; | |
| } else { | |
| const parsedCoordinates = coordinates.map((coordinate) => { | |
| const parsedCoordinate = parseInt(coordinate); | |
| if (isNaN(parsedCoordinate)) { | |
| throw `Invalid position, integer expected but ${coordinate} was given`; | |
| } else { | |
| return parsedCoordinate; | |
| } | |
| }); | |
| return { | |
| x: parsedCoordinates[0], | |
| y: parsedCoordinates[1], | |
| z: parsedCoordinates[2], | |
| }; | |
| } | |
| } | |
| Controller.ACTION_SEND_CHAT_MESSAGE = "send chat message"; | |
| Controller.ACTION_SPAWN_PARTICLE_AT_POSITION = "spawn particle at position"; | |
| Controller.ACTIONS = { | |
| [Controller.ACTION_SEND_CHAT_MESSAGE]: { | |
| implementation: (message) => { | |
| clientSystem.broadcastEvent("minecraft:display_chat_event", message); | |
| }, | |
| paramsLength: 1, | |
| }, | |
| [Controller.ACTION_SPAWN_PARTICLE_AT_POSITION]: { | |
| implementation: (effect, position) => { | |
| clientSystem.broadcastEvent("minecraft:spawn_particle_in_world", { | |
| effect, | |
| position: parsePosition(position), | |
| }); | |
| }, | |
| paramsLength: 2, | |
| }, | |
| }; | |
| class Parser { | |
| parse(source) { | |
| const eventSource = this.getEventSource(source); | |
| const actionSource = source.substring(Parser.WHEN_PREFIX.length + eventSource.length + 2); | |
| const parsed = { | |
| event: this.parseSource(eventSource), | |
| action: this.parseSource(actionSource), | |
| }; | |
| //TODO: debug only | |
| clientSystem.broadcastEvent("minecraft:display_chat_event", "parsed=" + JSON.stringify(parsed)); | |
| this.validateEvent(parsed.event); | |
| this.validateAction(parsed.action); | |
| return parsed; | |
| } | |
| getEventSource(source) { | |
| if (!source.startsWith(Parser.WHEN_PREFIX)) { | |
| throw `Parsing error, "${Parser.WHEN_PREFIX}" expected but not found`; | |
| } else { | |
| let quoted = false; | |
| let eventSource = ""; | |
| for (let index = Parser.WHEN_PREFIX.length; index < source.length; index++) { | |
| if (source[index] == Parser.QUOTE) { | |
| quoted = !quoted; | |
| eventSource += source[index]; | |
| } else if (source[index] == Parser.SEPERATOR) { | |
| break; | |
| } else { | |
| eventSource += source[index]; | |
| } | |
| } | |
| return eventSource; | |
| } | |
| } | |
| parseSource(source) { | |
| let name = ""; | |
| let currentParam = ""; | |
| const params = []; | |
| let quoted = false; | |
| for (let index = 0; index < source.length; index++) { | |
| if (source[index] == Parser.QUOTE) { | |
| quoted = !quoted; | |
| if (!quoted) { | |
| params.push(currentParam.replace(/ +/g, " ")); | |
| currentParam = ""; | |
| } | |
| } else { | |
| if (quoted) { | |
| currentParam += source[index]; | |
| } else { | |
| const nextCharacterIsQuote = source.indexOf(Parser.QUOTE, index) == index + 1; | |
| if (!nextCharacterIsQuote) { | |
| name += source[index]; | |
| } | |
| } | |
| } | |
| } | |
| return { | |
| name: name, | |
| params, | |
| }; | |
| } | |
| validateEvent(event) { | |
| if (!Controller.EVENTS[event.name]) { | |
| throw `${event.name} is not recognised as an event`; | |
| } else if (Controller.EVENTS[event.name].paramsLength != event.params.length) { | |
| throw `${event.params.length} paramaters given for event ${event.name} but ${Controller.EVENTS[event.name].paramsLength} parameters were expected`; | |
| } | |
| } | |
| validateAction(action) { | |
| if (!Controller.ACTIONS[action.name]) { | |
| throw `${action.name} is not recognised as an action`; | |
| } else if (Controller.ACTIONS[action.name].paramsLength != action.params.length) { | |
| throw `${action.params.length} paramaters given for action ${action.name} but ${Controller.ACTIONS[action.name].paramsLength} parameters were expected`; | |
| } | |
| } | |
| } | |
| Parser.WHEN_PREFIX = "when "; | |
| Parser.SEPERATOR = ","; | |
| Parser.QUOTE = "\""; | |
| clientSystem.initialize = () => { | |
| const mainController = new Controller(); | |
| clientSystem.listenForEvent("minecraft:client_entered_world", () => { | |
| mainController.onPlayerEnterWorld(); | |
| }); | |
| clientSystem.listenForEvent("minecraft:hit_result_changed", (eventData) => { | |
| mainController.onHitResultChanged(eventData); | |
| }); | |
| const sources = [ | |
| //INSERT SOURCES HERE | |
| "when player enters world, send chat message \"Hello world\"", | |
| "when player enters world, spawn particle \"minecraft:mobflame_emitter\" at position \"45 70 170\"", | |
| "when player looks at mob \"minecraft:pig\", send chat message \"Oink!\"", | |
| "when player looks at mob \"minecraft:cow\", send chat message \"Moo!\"", | |
| "when player looks at mob \"minecraft:creeper\", send chat message \"Run!\"", | |
| ]; | |
| const parser = new Parser(); | |
| sources.forEach((source) => { | |
| const parsed = parser.parse(source); | |
| mainController.add(parsed.event, parsed.action); | |
| }); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment