diff --git a/IScriptCraft.java b/IScriptCraft.java new file mode 100644 index 0000000..7d9de18 --- /dev/null +++ b/IScriptCraft.java @@ -0,0 +1,12 @@ +package net.minecraft.src; + +public interface IScriptCraft +{ + public double[] getPlayerPos(); + public double[] getMousePos(); + public void putSign(String[] texts,int x, int y, int z, int block, int meta); + public void putBlock(int x, int y, int z, int blockId, int meta); + public String getBlock(int x, int y, int z); + public void notifyAdministrators(String message); + public void setInvoker(Object invoker); +} diff --git a/ScriptCraftEvaluator.java b/ScriptCraftEvaluator.java new file mode 100644 index 0000000..cf810db --- /dev/null +++ b/ScriptCraftEvaluator.java @@ -0,0 +1,265 @@ +package net.minecraft.src; + +import org.mozilla.javascript.*; +import java.util.List; +import java.io.*; +import javax.swing.JFileChooser; + +public class ScriptCraftEvaluator +{ + protected static IScriptCraft sc = null; + protected Context ctx = null; + protected Scriptable scope = null; + + public static class MCScope extends ImporterTopLevel{ + public MCScope(Context ctx){ + super(ctx); + } + } + public ScriptCraftEvaluator(IScriptCraft scImpl) + { + ScriptCraftEvaluator.sc = scImpl; + this.ctx = Context.enter(); + ScriptableObject importer = new ScriptCraftEvaluator.MCScope(ctx); + this.scope = this.ctx.initStandardObjects(importer); + // + // for mcp debug only + //ctx.evaluateString(scope,"importPackage(net.minecraft.src)","",1,null); + // + String[] names = { + "print" + ,"load" + ,"help" + ,"getPlayerPos" + ,"getMousePos" + ,"putBlock" + ,"getBlock" + ,"putSign" + }; + importer.defineFunctionProperties(names, + ScriptCraftEvaluator.class, + ScriptableObject.DONTENUM); + } + /** + * So clients can add their own properties ... + * + * evaluator.getScope().defineProperty("jsVarName",javaObject); + */ + public ScriptableObject getScope() + { + return (ScriptableObject)this.scope; + } + + public Object eval(String javascript, Object invoker) + { + ScriptCraftEvaluator.sc.setInvoker(invoker); + ScriptCraftEvaluator.sc.notifyAdministrators("js> " + javascript); + Object result = null; + try + { + result = ctx.evaluateString(this.scope, javascript, "", 1, null); + } + catch(Exception e) + { + e.printStackTrace(System.err); + ScriptCraftEvaluator.sc.notifyAdministrators("Exception: " + e.getMessage()); + } + if (result != null) + { + ScriptCraftEvaluator.sc.notifyAdministrators(Context.toString(result)); + } + return result; + } + + /** + * Load a javascript source file and evaluate its contents. + */ + public static Object load(Context cx, Scriptable thisObj, Object[] args, Function funObj) + { + Object result = null; + + File scriptFile = null; + String filename = null; + + if (args.length == 0) + { + JFileChooser fc = new javax.swing.JFileChooser(); + int rc = fc.showOpenDialog(null); + if (rc ==JFileChooser.APPROVE_OPTION){ + scriptFile = fc.getSelectedFile(); + }else{ + return result; + } + }else{ + scriptFile = new File((String)args[0]); + } + + FileReader in = null; + try { + in = new FileReader(scriptFile); + } + catch (FileNotFoundException ex) + { + ex.printStackTrace(System.err); + ScriptCraftEvaluator.sc.notifyAdministrators( "Error - File not found " + args[0]); + Context.reportError("Couldn't open file \"" + scriptFile + "\"."); + return null; + } + filename = scriptFile.getAbsolutePath(); + System.out.println("ScripCraftEvaluator: filename=" + filename); + File parentFile = scriptFile.getParentFile(); + String filedir = null; + if (parentFile !=null){ + filedir = parentFile.getAbsolutePath(); + } + // + // setup the special script-context-only variables + // + ((ScriptableObject)thisObj).defineProperty("$SCRIPT",filename,ScriptableObject.DONTENUM); + ((ScriptableObject)thisObj).defineProperty("$SCRIPT_DIR",filedir==null?"":filedir,ScriptableObject.DONTENUM); + + try { + // Here we evalute the entire contents of the file as + // a script. Text is printed only if the print() function + // is called. + ScriptCraftEvaluator.sc.notifyAdministrators( "Loading " + filename); + result = cx.evaluateReader(thisObj, in, filename, 1, null); + ScriptCraftEvaluator.sc.notifyAdministrators( "Successfully loaded " + filename); + } + catch (WrappedException we) { + we.printStackTrace(System.err); + String wes = we.getWrappedException().toString(); + ScriptCraftEvaluator.sc.notifyAdministrators("WrappedException while loading " + filename + ": " + wes); + System.err.println(wes); + we.printStackTrace(); + } + catch (EvaluatorException ee) { + ee.printStackTrace(System.err); + System.err.println("js: " + ee.getMessage()); + ScriptCraftEvaluator.sc.notifyAdministrators( "EvaluatorException while loading " + filename + ": " + ee.getMessage()); + } + catch (JavaScriptException jse) { + jse.printStackTrace(System.err); + System.err.println("js: " + jse.getMessage()); + ScriptCraftEvaluator.sc.notifyAdministrators("JavascriptException while loading " + filename + ": " + jse.getMessage()); + } + catch (IOException ioe) { + ioe.printStackTrace(System.err); + System.err.println(ioe.toString()); + ScriptCraftEvaluator.sc.notifyAdministrators( "IOException while loading " + filename + ": " + ioe.getMessage()); + } + finally { + try { + in.close(); + } + catch (IOException ioe) { + System.err.println(ioe.toString()); + } + } + return result; + } + public static void help(Context cx, Scriptable thisObj, Object[] args, Function funObj) + { + String cwd = java.lang.System.getProperty("user.dir"); + String[] helpArgs = {"Current Working Directory: " + cwd, + "load('path-to-script.js')", + "load() (with no params) lets you choose a script file", + "getPlayerPos() returns player coords", + "getMousePos() returns mouse/crosshair coords", + "getBlock(x,y,z) returns the block and metadata e.g. '98' for a stone block or '98:2' for a mossy stone block", + "putBlock(x,y,z,blockId,meta) e.g. putBlock(100,2,50,44,2) puts a sandstone slab (44:2) at position 100,2,50. See http://www.minecraftinfo.com/idlist.htm for block ids" + }; + print(cx,thisObj,helpArgs,funObj); + } + + public static void print(Context cx, Scriptable thisObj,Object[] args, Function funObj) + { + for (int i=0; i < args.length; i++) { + if (i > 0){ + System.out.print(" "); + } + + // Convert the arbitrary JavaScript value into a string form. + String s = Context.toString(args[i]); + ScriptCraftEvaluator.sc.notifyAdministrators(s); + System.out.print(s); + } + System.out.println(); + } + public static double[] getPlayerPos(Context cx, Scriptable thisObj,Object[] args, Function funObj) + { + return ScriptCraftEvaluator.sc.getPlayerPos(); + } + public static double[] getMousePos(Context cx, Scriptable thisObj,Object[] args, Function funObj) + { + return ScriptCraftEvaluator.sc.getMousePos(); + } + public static void putBlock(Context cx, Scriptable thisObj,Object[] args, Function funObj) + { + int x; + int y; + int z; + int b; + int m; + + if (args.length == 2){ + double[] mousePos = ScriptCraftEvaluator.sc.getMousePos(); + if (mousePos != null){ + x = (int)mousePos[0]; + y = (int)mousePos[1]; + z = (int)mousePos[2]; + b = new Double(args[0].toString()).intValue(); + m = new Double(args[1].toString()).intValue(); + }else{ + return; + } + }else { + x = new Double(args[0].toString()).intValue(); + y = new Double(args[1].toString()).intValue(); + z = new Double(args[2].toString()).intValue(); + b = new Double(args[3].toString()).intValue(); + m = new Double(args[4].toString()).intValue(); + } + ScriptCraftEvaluator.sc.putBlock(x,y,z,b,m); + } + // + // gets the blockId and metadata at the given coords + // if no coords are provided then the mouse position is used instead. + // + public static String getBlock(Context cx, Scriptable thisObj,Object[] args, Function funObj){ + int x; + int y; + int z; + + if (args.length != 0){ + x = new Double(args[0].toString()).intValue(); + y = new Double(args[1].toString()).intValue(); + z = new Double(args[2].toString()).intValue(); + }else{ + double[] mousePos = ScriptCraftEvaluator.sc.getMousePos(); + if (mousePos != null){ + x = (int)mousePos[0]; + y = (int)mousePos[1]; + z = (int)mousePos[2]; + }else{ + return null; + } + } + return ScriptCraftEvaluator.sc.getBlock(x,y,z); + } + public static void putSign(Context cx, Scriptable thisObj,Object[] args, Function funObj){ + List jsArray = (List)args[0]; + + String[] texts = new String[4]; + for (int i = 0; i < jsArray.size() && i <= 3;i++){ + texts[i] = (String)jsArray.get(i); + } + int x = new Double(args[1].toString()).intValue(); + int y = new Double(args[2].toString()).intValue(); + int z = new Double(args[3].toString()).intValue(); + int b = new Double(args[4].toString()).intValue(); + int m = new Double(args[5].toString()).intValue(); + ScriptCraftEvaluator.sc.putSign(texts,x,y,z,b,m); + } + +} diff --git a/ScriptCraftMCP.java b/ScriptCraftMCP.java new file mode 100644 index 0000000..88b9429 --- /dev/null +++ b/ScriptCraftMCP.java @@ -0,0 +1,109 @@ +package net.minecraft.src; +import net.minecraft.client.*; +/** + * An implementation of the IScriptCraft interface for + * Minecraft Coder Pack-style install + * + */ +public class ScriptCraftMCP implements IScriptCraft +{ + protected CommandBase command = null; + + public ScriptCraftMCP(CommandBase mcpCommand){ + this.command = mcpCommand; + } + + protected ICommandSender invoker; + // + // following code depends on MCP + // + public double[] getPlayerPos() + { + double[] result = new double[4]; + if (this.invoker instanceof EntityPlayer){ + EntityPlayer player = (EntityPlayer)this.invoker; + result[0] = player.posX; + result[1] = player.posY; + result[2] = player.posZ; + result[3] = player.rotationYaw; + return result; + } + return null; + } + public double[] getMousePos() + { + Minecraft mc = net.minecraft.client.Minecraft.getMinecraft(); + MovingObjectPosition omo = mc.objectMouseOver; + if (omo == null){ + return null; + } + double[] result = new double[4]; + result[0] = omo.blockX; + result[1] = omo.blockY; + result[2] = omo.blockZ; + return result; + } + public void putSign(String[] texts, int x, int y, int z, int block, int meta) + { + this.putBlock(x,y,z,block,meta); + EntityPlayer player = (EntityPlayer)this.invoker; + World world = player.worldObj; + TileEntitySign sign = (TileEntitySign)world.getBlockTileEntity(x,y,z); + for (int i=0 ; i < texts.length && i <= 3;i++){ + String text = texts[i]; + if (text != null){ + if (text.length() > 15){ + text = text.substring(0,15); + } + sign.signText[i] = text; + } + } + sign.onInventoryChanged(); + world.markBlockForUpdate(x,y,z); + } + + public void putBlock(int x, int y, int z, int blockId, int meta) + { + World world = null; + if (this.invoker instanceof EntityPlayer) + { + world = ((EntityPlayer)(this.invoker)).worldObj; + } + else if (this.invoker instanceof TileEntity) + { + world = ((TileEntity)(this.invoker)).getWorldObj(); + } + world.setBlockAndMetadata(x,y,z,blockId,meta); + + switch (blockId) + { + case 6: + ((BlockSapling)Block.sapling).growTree(world,x,y,z,world.rand); + break; + } + } + // + // returns the block id and metadata at a given location in the world + // e.g. returns "98" for a stone block or "98:2" for a mossy stone block. + // + public String getBlock(int x, int y, int z) + { + EntityPlayer player = (EntityPlayer)this.invoker; + World world = player.worldObj; + int blockId = world.getBlockId(x,y,z); + int metadata = world.getBlockMetadata(x,y,z); + if (metadata !=0){ + return "" + blockId + ":" + metadata; + }else{ + return "" + blockId; + } + } + public void notifyAdministrators(String message) + { + this.command.notifyAdmins(this.invoker,message,(Object[])null); + } + public void setInvoker(Object invoker) + { + this.invoker = (ICommandSender)invoker; + } +}