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.

This commit is contained in:
sk89q 2010-10-02 01:21:48 -07:00
parent da021f8519
commit c8054b95fe
5 changed files with 250 additions and 4 deletions

3
manifest.mf Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path: js.jar

View File

@ -0,0 +1,53 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
*
* @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);
}
}

View File

@ -0,0 +1,49 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
*
* @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);
}
}

72
src/EditScriptPlayer.java Normal file
View File

@ -0,0 +1,72 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
*
* @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());
}
}

View File

@ -21,6 +21,8 @@
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 WorldEdit() {
commands.put("/editoverlay", "<ID> - Overlay the area one layer");
commands.put("/removeabove", "<Size> - Remove blocks above head");
commands.put("/editfill", "<ID> <Radius> <Depth> - Fill a hole");
commands.put("/editscript", "<Filename> [Args...] - Run an editscript");
}
/**
@ -190,16 +193,16 @@ private boolean handleEditCommand(Player player, String[] split)
// 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 @@ private boolean handleEditCommand(Player player, String[] split)
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();