From c8054b95fed9f0ab8f5557a9607f9e6e0d8519d7 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 2 Oct 2010 01:21:48 -0700 Subject: [PATCH] Added preliminary JavaScript scripting support. Currently it can be used to do routines such as forest creation but it cannot make hooks or do anything fancy. --- manifest.mf | 3 ++ src/EditScriptContext.java | 53 ++++++++++++++++++++ src/EditScriptMinecraftContext.java | 49 ++++++++++++++++++ src/EditScriptPlayer.java | 72 +++++++++++++++++++++++++++ src/WorldEdit.java | 77 +++++++++++++++++++++++++++-- 5 files changed, 250 insertions(+), 4 deletions(-) create mode 100644 manifest.mf create mode 100644 src/EditScriptContext.java create mode 100644 src/EditScriptMinecraftContext.java create mode 100644 src/EditScriptPlayer.java diff --git a/manifest.mf b/manifest.mf new file mode 100644 index 000000000..a9afe32fc --- /dev/null +++ b/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: js.jar + diff --git a/src/EditScriptContext.java b/src/EditScriptContext.java new file mode 100644 index 000000000..b0df3ffd1 --- /dev/null +++ b/src/EditScriptContext.java @@ -0,0 +1,53 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +/** + * + * @author sk89q + */ +public class EditScriptContext { + public EditScriptPlayer player; + + /** + * Constructs the context. A player object has to be passed. + * + * @param player + */ + public EditScriptContext(EditScriptPlayer player) { + this.player = player; + } + + /** + * Prints a message to the player. + * + * @param msg + */ + public void print(String msg) { + player.print(msg); + } + + /** + * Prints an error message to the player. + * + * @param msg + */ + public void error(String msg) { + player.error(msg); + } +} diff --git a/src/EditScriptMinecraftContext.java b/src/EditScriptMinecraftContext.java new file mode 100644 index 000000000..99fd7c9a3 --- /dev/null +++ b/src/EditScriptMinecraftContext.java @@ -0,0 +1,49 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +/** + * + * @author Albert + */ +public class EditScriptMinecraftContext { + /** + * Sets the block at position x, y, z with a block type. + * + * @param x + * @param y + * @param z + * @param blockType + * @return + */ + public boolean setBlock(int x, int y, int z, int blockType) { + return etc.getMCServer().e.d(x, y, z, blockType); + } + + /** + * Gets the block type at a position x, y, z. + * + * @param x + * @param y + * @param z + * @return + */ + public int getBlock(int x, int y, int z) { + return etc.getMCServer().e.a(x, y, z); + } +} diff --git a/src/EditScriptPlayer.java b/src/EditScriptPlayer.java new file mode 100644 index 000000000..52f4b2bda --- /dev/null +++ b/src/EditScriptPlayer.java @@ -0,0 +1,72 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +/** + * + * @author Albert + */ +public class EditScriptPlayer { + private Player player; + + public String name; + public double pitch; + public double yaw; + public double x; + public double y; + public double z; + public int blockX; + public int blockY; + public int blockZ; + + /** + * Prints a message to the player. + * + * @param msg + */ + public void print(String msg) { + player.sendMessage(msg); + } + + /** + * Prints an error message to the player. + * + * @param msg + */ + public void error(String msg) { + player.sendMessage(Colors.Rose + msg); + } + + /** + * Constructs the player instance. + * + * @param player + */ + public EditScriptPlayer(Player player) { + this.player = player; + name = player.getName(); + pitch = player.getPitch(); + yaw = player.getRotation(); + x = player.getX(); + y = player.getY(); + z = player.getZ(); + blockX = (int)Math.floor(player.getX()); + blockY = (int)Math.floor(player.getY()); + blockZ = (int)Math.floor(player.getZ()); + } +} diff --git a/src/WorldEdit.java b/src/WorldEdit.java index eb06089e1..1c1486434 100644 --- a/src/WorldEdit.java +++ b/src/WorldEdit.java @@ -21,6 +21,8 @@ import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import java.util.Map; +import java.io.*; +import org.mozilla.javascript.*; /** * @@ -42,6 +44,7 @@ public class WorldEdit extends Plugin { commands.put("/editoverlay", " - Overlay the area one layer"); commands.put("/removeabove", " - Remove blocks above head"); commands.put("/editfill", " - Fill a hole"); + commands.put("/editscript", " [Args...] - Run an editscript"); } /** @@ -190,16 +193,16 @@ public class WorldEdit extends Plugin { // Set edit position #1 if (split[0].equalsIgnoreCase("/editpos1")) { session.setPos1((int)Math.floor(player.getX()), - (int)Math.floor(player.getY()), - (int)Math.floor(player.getZ())); + (int)Math.floor(player.getY()), + (int)Math.floor(player.getZ())); player.sendMessage(Colors.LightPurple + "First edit position set."); return true; // Set edit position #2 } else if (split[0].equalsIgnoreCase("/editpos2")) { session.setPos2((int)Math.floor(player.getX()), - (int)Math.floor(player.getY()), - (int)Math.floor(player.getZ())); + (int)Math.floor(player.getY()), + (int)Math.floor(player.getZ())); player.sendMessage(Colors.LightPurple + "Second edit position set."); return true; @@ -246,6 +249,72 @@ public class WorldEdit extends Plugin { player.sendMessage(Colors.LightPurple + affected + " block(s) have been removed."); return true; + + // Run an editscript + } else if (split[0].equalsIgnoreCase("/editscript")) { + checkArgs(split, 1); + String filename = split[1].replace("\0", "") + ".js"; + File dir = new File("editscripts"); + File f = new File("editscripts", filename); + + try { + String filePath = f.getCanonicalPath(); + String dirPath = dir.getCanonicalPath(); + + if (!filePath.substring(0, dirPath.length()).equals(dirPath)) { + player.sendMessage(Colors.Rose + "Editscript file does not exist."); + } else { + // Read file + StringBuffer buffer = new StringBuffer(); + FileInputStream stream = new FileInputStream(f); + BufferedReader in = new BufferedReader(new InputStreamReader(stream, "UTF-8")); + int c; + while ((c = in.read()) > -1) { + buffer.append((char)c); + } + in.close(); + String code = buffer.toString(); + + // Evaluate + Context cx = Context.enter(); + try { + ScriptableObject scope = cx.initStandardObjects(); + + // Add args + String[] args = new String[split.length - 2]; + System.arraycopy(split, 2, args, 0, split.length - 2); + ScriptableObject.putProperty(scope, "args", + Context.javaToJS(args, scope)); + + // Add context + EditScriptPlayer scriptPlayer = new EditScriptPlayer(player); + EditScriptContext context = new EditScriptContext( + scriptPlayer); + ScriptableObject.putProperty(scope, "context", + Context.javaToJS(context, scope)); + ScriptableObject.putProperty(scope, "player", + Context.javaToJS(scriptPlayer, scope)); + + // Add Minecraft context + EditScriptMinecraftContext minecraft = new EditScriptMinecraftContext(); + ScriptableObject.putProperty(scope, "minecraft", + Context.javaToJS(minecraft, scope)); + + cx.evaluateString(scope, code, filename, 1, null); + player.sendMessage(Colors.LightPurple + filename + " executed successfully."); + } catch (RhinoException re) { + player.sendMessage(Colors.Rose + "JS error: " + re.getMessage()); + re.printStackTrace(); + } finally { + Context.exit(); + } + + return true; + } + } catch (IOException e) { + player.sendMessage(Colors.Rose + "Editscript could not read or it does not exist."); + } + return true; } int lowerX = session.getLowerX();