From a1f243cef0f95a4b619a2f2f823ad4723646107c Mon Sep 17 00:00:00 2001 From: walterhiggins Date: Thu, 27 Dec 2012 12:55:05 +0000 Subject: [PATCH] it lives! --- CommandScript.java | 264 ++++++++++++++++++++++++++++ ServerCommandManager.patch | 2 + cottage.js | 33 ++++ drone.js | 351 +++++++++++++++++++++++++++++++++++++ 4 files changed, 650 insertions(+) create mode 100644 CommandScript.java create mode 100644 ServerCommandManager.patch create mode 100644 cottage.js create mode 100644 drone.js diff --git a/CommandScript.java b/CommandScript.java new file mode 100644 index 0000000..f6544c5 --- /dev/null +++ b/CommandScript.java @@ -0,0 +1,264 @@ +package net.minecraft.src; + +import java.util.List; +import java.io.*; +import javax.swing.JFileChooser; +import net.minecraft.server.MinecraftServer; +import sun.org.mozilla.javascript.*; +import net.minecraft.client.*; +/** + * This mod lets you load and run javascript to build structures which would otherwise be tedious. + * Build road networks, rows of houses, factories and sky-scrapers. ScriptCraft takes building to a whole new level + * by making it easy to create javascript scripts that do the building for you. + * The following code creates a simple cottage at the crosshair location or the player's current location... + * load("./drone.js"); + * var drone = new Drone(); + * drone.box0(48,7,6,2) // 4 walls + * .right(3).door() // a door front-center + * .left(2).box(102) // windows left and right of door + * .right(4).box(102) // + * .home().up(2).prism0(53,7,6); // a gable roof + * + */ +public class CommandScript extends CommandBase { + + public static class MCScope extends ImporterTopLevel{ + public MCScope(Context ctx){ + super(ctx); + } + } + public static class PlayerPos + { + public double x; + public double y; + public double z; + public double rotationYaw; + public String toString(){ + return super.toString() + " x:" + this.x + " ,y:" + this.y + " ,z:" + this.z + " ,rotationYaw:" + this.rotationYaw; + } + + } + + + public static PlayerPos getPlayerPosImpl() + { + PlayerPos pos = new PlayerPos(); + EntityPlayer player = (EntityPlayer)CommandScript.sender; + + pos.x = player.posX; + pos.y = player.posY; + pos.z = player.posZ; + pos.rotationYaw = player.rotationYaw; + return pos; + } + public static PlayerPos getMousePosImpl() + { + Minecraft mc = net.minecraft.client.Minecraft.getMinecraft(); + MovingObjectPosition omo = mc.objectMouseOver; + if (omo == null){ + return null; + } + PlayerPos pos = new PlayerPos(); + pos.x = omo.blockX; + pos.y = omo.blockY; + pos.z = omo.blockZ; + return pos; + } + public static void putSignImpl(String[] texts, int x, int y, int z, int block, int meta) + { + CommandScript.putBlockImpl(x,y,z,block,meta); + EntityPlayer player = (EntityPlayer)CommandScript.sender; + 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 static void putBlockImpl(int x, int y, int z, int blockId, int meta){ + EntityPlayer player = (EntityPlayer)CommandScript.sender; + player.worldObj.setBlockAndMetadata(x,y,z,blockId,meta); + } + + public String getCommandName() { + return "js"; + } + private Context ctx = null; + private Scriptable scope = null; + + public int getRequiredPermissionLevel() { + // WPH return 2; + return 0; + } + private static ICommandSender sender; + + public void processCommand(ICommandSender par1ICommandSender, String[] args) + { + CommandScript.sender = par1ICommandSender; + + if (this.ctx == null){ + this.ctx = Context.enter(); + } + if (this.scope == null){ + ScriptableObject importer = new CommandScript.MCScope(ctx); + this.scope = this.ctx.initStandardObjects(importer); + ctx.evaluateString(scope,"importPackage(net.minecraft.src)","",1,null); + String[] names = { + "print" + ,"load" + ,"help" + ,"getPlayerPos" + ,"getMousePos" + ,"putBlock" + ,"putSign" + }; + importer.defineFunctionProperties(names, CommandScript.class,ScriptableObject.DONTENUM); + importer.defineProperty("minecraft", net.minecraft.client.Minecraft.getMinecraft(),ScriptableObject.DONTENUM); + EntityPlayer player = (EntityPlayer)par1ICommandSender; + importer.defineProperty("player", player,ScriptableObject.DONTENUM); + importer.defineProperty("world", player.worldObj,ScriptableObject.DONTENUM); + } + if (System.out !=null){ + System.out.println(this.scope); + } + + // Collect the arguments into a single string. + String s = ""; + for (int i=0; i < args.length; i++) { + s += args[i] + " "; + } + // Now evaluate the string we've colected. + notifyAdmins(par1ICommandSender, "js> " + s, (Object[])args); + Object result = ctx.evaluateString(scope, s, "", 1, null); + if (result != null){ + notifyAdmins(par1ICommandSender, Context.toString(result), (Object[])args); + } + return; + } + public static void load(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + { + 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; + } + }else{ + scriptFile = new File((String)args[0]); + } + + FileReader in = null; + try { + in = new FileReader(scriptFile); + } + catch (FileNotFoundException ex) { + Context.reportError("Couldn't open file \"" + scriptFile + "\"."); + return; + } + filename = scriptFile.getAbsolutePath(); + ((ScriptableObject)thisObj).defineProperty("$SCRIPT",scriptFile.getAbsolutePath(),ScriptableObject.DONTENUM); + ((ScriptableObject)thisObj).defineProperty("$SCRIPTPATH",scriptFile.getParentFile().getAbsolutePath(),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. + cx.evaluateReader(thisObj, in, filename, 1, null); + } + catch (WrappedException we) { + System.err.println(we.getWrappedException().toString()); + we.printStackTrace(); + } + catch (EvaluatorException ee) { + System.err.println("js: " + ee.getMessage()); + } + catch (JavaScriptException jse) { + System.err.println("js: " + jse.getMessage()); + } + catch (IOException ioe) { + System.err.println(ioe.toString()); + } + finally { + try { + in.close(); + } + catch (IOException ioe) { + System.err.println(ioe.toString()); + } + } + } + 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", + "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]); + notifyAdmins(CommandScript.sender, s, args); + System.out.print(s); + } + System.out.println(); + } + public static PlayerPos getPlayerPos(Context cx, Scriptable thisObj,Object[] args, Function funObj){ + return getPlayerPosImpl(); + } + public static PlayerPos getMousePos(Context cx, Scriptable thisObj,Object[] args, Function funObj){ + return getMousePosImpl(); + } + public static void putBlock(Context cx, Scriptable thisObj,Object[] args, Function funObj){ + int x = new Double(args[0].toString()).intValue(); + int y = new Double(args[1].toString()).intValue(); + int z = new Double(args[2].toString()).intValue(); + int b = new Double(args[3].toString()).intValue(); + int m = new Double(args[4].toString()).intValue(); + putBlockImpl(x,y,z,b,m); + } + public static void putSign(Context cx, Scriptable thisObj,Object[] args, Function funObj){ + List jsArray = (List)args[0]; + System.out.println("putSign jsArray=" + jsArray); + + 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(); + putSignImpl(texts,x,y,z,b,m); + } + +} diff --git a/ServerCommandManager.patch b/ServerCommandManager.patch new file mode 100644 index 0000000..231096f --- /dev/null +++ b/ServerCommandManager.patch @@ -0,0 +1,2 @@ +9a10 +> this.registerCommand(new CommandScript()); diff --git a/cottage.js b/cottage.js new file mode 100644 index 0000000..c2031b4 --- /dev/null +++ b/cottage.js @@ -0,0 +1,33 @@ +// +// need to use the drone module to create buildings easily +// it can be done using calls to putBlock(), putSign(), getPlayerPos() and getMousePos() +// but it's easier to use the Drone class +// +load($SCRIPTPATH + "/drone.js"); // assumes cottage.js and drone.js are in same directory +// +// usage: +// [1] to build a cottage at the player's current location or the cross-hairs location... +// +// /js cottage(); +// +// [2] to build a cottage using an existing drone... +// +// /js cottage(drone); +// +var cottage = function(drone){ + if (typeof drone == "undefined"){ + drone = new Drone(); + } + drone + .box0(48,7,6,2) // 4 walls + .right(3).door() // door front and center + .up(1).left(2).box(102) // windows to left and right + .right(4).box(102) + .left(5).up().prism0(53,7,6); + // + // put up a sign near door. + // + drone.down().right(4).sign(["Home","Sweet","Home"],68); + + return drone.down().left(4); +}; diff --git a/drone.js b/drone.js new file mode 100644 index 0000000..eebbdad --- /dev/null +++ b/drone.js @@ -0,0 +1,351 @@ +var ScriptCraft = ScriptCraft || {}; +(function(){ + // + // Drone Constructor + // + var Drone = function(x,y,z,dir) + { + var usePlayerCoords = false; + var playerPos = getPlayerPos(); + if (typeof x == "undefined"){ + var mp = getMousePos(); + if (mp){ + this.x = mp.x; + this.y = mp.y; + this.z = mp.z; + }else{ + // base it on the player's current location + usePlayerCoords = true; + this.x = playerPos.x; + this.y = playerPos.y; + this.z = playerPos.z; + } + }else{ + this.x = x; + this.y = y; + this.z = z; + } + if (typeof dir == "undefined"){ + this.dir = getDirFromRotation(playerPos.rotationYaw); + }else{ + this.dir = dir%4; + } + if (usePlayerCoords){ + this.fwd(2); + } + this.homeCoords = {x:this.x,y:this.y,z:this.z,dir:this.dir}; + }; + var getDirFromRotation = function(r){ + var result = 1; + r = Math.abs(Math.ceil(r)); + if (r >= 45 && r < 135){ + result = 0; + } + if (r >= 135 && r < 225){ + result = 3; + } + if (r >= 225 && r < 315){ + result = 2; + } + return result; + }; + // + // movement + // + var movements = [{},{},{},{}]; + // east + movements[0].right = function(that,n){ that.z +=n; return that;}; + movements[0].left = function(that,n){ that.z -=n; return that;}; + movements[0].fwd = function(that,n){ that.x +=n; return that;}; + movements[0].back = function(that,n){ that.x -= n; return that;}; + // south + movements[1].right = movements[0].back; + movements[1].left = movements[0].fwd; + movements[1].fwd = movements[0].right; + movements[1].back = movements[0].left; + // west + movements[2].right = movements[0].left; + movements[2].left = movements[0].right; + movements[2].fwd = movements[0].back; + movements[2].back = movements[0].fwd; + // north + movements[3].right = movements[0].fwd; + movements[3].left = movements[0].back; + movements[3].fwd = movements[0].left; + movements[3].back = movements[0].right; + Drone.prototype.turn = function(n) + { + if (typeof n == "undefined"){ + this.dir++; + }else{ + this.dir += n; + } + this.dir %=4; + return this; + }; + Drone.prototype.right = function(n){ if (typeof n == "undefined"){ n = 1;} return movements[this.dir].right(this,n);}; + Drone.prototype.left = function(n){ if (typeof n == "undefined"){ n = 1;} return movements[this.dir].left(this,n);}; + Drone.prototype.fwd = function(n){ if (typeof n == "undefined"){ n = 1;} return movements[this.dir].fwd(this,n);}; + Drone.prototype.back = function(n){ if (typeof n == "undefined"){ n = 1;} return movements[this.dir].back(this,n);}; + Drone.prototype.up = function(n){ if (typeof n == "undefined"){ n = 1;} this.y+=n; return this;}; + Drone.prototype.down = function(n){ if (typeof n == "undefined"){ n = 1;} this.y-=n; return this;}; + Drone.prototype.home = function() + { + this.x = this.homeCoords.x; + this.y = this.homeCoords.y; + this.z = this.homeCoords.z; + this.dir = this.homeCoords.dir; + return this; + }; + // + // building + // + var traverse = [{},{},{},{}]; + // east + traverse[0].width = function(that,n,callback){ + var s = that.z, e = s + n; + for (; that.z < e; that.z++){ + callback(); + } + that.z = s; + }; + traverse[0].depth = function(that,n,callback){ + var s = that.x, e = s+n; + for (;that.x < e;that.x++){ + callback(); + } + that.x = s; + }; + // south + traverse[1].width = function(that,n,callback){ + var s = that.x, e = s-n; + for (;that.x > e;that.x--){ + callback(); + } + that.x = s; + }; + traverse[1].depth = traverse[0].width; + // west + traverse[2].width = function(that,n,callback){ + var s = that.z, e = s-n; + for (;that.z > e;that.z--){ + callback(); + } + that.z = s; + }; + traverse[2].depth = traverse[1].width; + // north + traverse[3].width = traverse[0].depth; + traverse[3].depth = traverse[2].width; + traverseHeight = function(that,n,callback){ + var s = that.y, e = s + n; + for (; that.y < e; that.y++){ + callback(); + } + that.y = s; + }; + var getBlockIdAndMeta = function(b){ + if (typeof b == 'string'){ + var bs = b; + var sp = bs.indexOf(':') + b = parseInt(bs.substring(0,sp)); + md = parseInt(bs.substring(sp+1,bs.length)); + return [b,md]; + }else{ + return [b,0]; + } + }; + Drone.prototype.sign = function(message,block){ + if (message.constructor == Array){ + }else{ + message = [message]; + } + var bm = getBlockIdAndMeta(block); + block = bm[0]; + meta = bm[1]; + if (block != 63 && block != 68){ + print("ERROR: Invalid block id for use in signs"); + return; + } + if (block == 68){ + meta = this.playerToSignDirs[this.dir]; + this.back(); + } + putSign(message,this.x,this.y,this.z,block,meta); + if (block == 68){ + this.fwd(); + } + return this; + }; + + Drone.prototype.cuboid = function(block,w,d,h){ + var md = 0; + if (typeof block == 'object'){ + block = block.blockID; + }else{ + var bm = getBlockIdAndMeta(block); + block = bm[0]; + md = bm[1]; + } + if (typeof h == "undefined"){ + h = 1; + } + if (typeof d == "undefined"){ + d = 1; + } + if (typeof w == "undefined"){ + w = 1; + } + var that = this; + traverse[this.dir].width(that,w,function(){ + traverseHeight(that,h,function(){ + traverse[that.dir].depth(that,d,function(){ + putBlock(that.x,that.y,that.z,block,md); + }); + }); + }); + return this; + }; + Drone.prototype.cuboid0 = function(block,w,d,h){ + return this.cuboid(block,w,d,h).fwd().right().cuboid(0,w-2,d-2,h).back().left(); + }; + Drone.prototype.door = function(door){ + if (typeof door == "undefined"){ + door = 64; + }else{ + door = 71; + } + return this.cuboid(door+':' + this.dir,1,1,1).up().cuboid(door+':8',1,1,1).down(); + }; + // player dirs: 0 = east, 1 = south, 2 = west, 3 = north + // block dirs: 0 = east, 1 = west, 2 = south , 3 = north + // sign dirs: 5 = east, 3 = south, 4 = west, 2 = north + Drone.prototype.playerToBlockDirs = [0,2,1,3]; + Drone.prototype.playerToSignDirs = [4,2,5,3]; + + Drone.prototype.prism0 = function(block,w,d){ + this.prism(block,w,d).fwd().right().prism(0,w-2,d-2).left().back(); + var se = Drone.STAIRBLOCKS[block]; + if (d % 2 == 1 && se){ + // top of roof will be open - need repair + var f = Math.floor(d/2); + this.fwd(f).up(f).cuboid(se,w,1,1).down(f).back(f); + } + }; + Drone.STAIRBLOCKS = {53: 5 // oak wood + ,67: 4 // cobblestone + ,108: 45 // brick + ,109: 98 // stone brick + ,114: 112 // nether brick + ,128: 24 // sandstone + ,134: '5:1' // spruce wood + ,135: '5:2' // birch wood + ,136: '5:3' // jungle wood + }; + + // /\ + // /##\ + // /####\ + // 012345 + // d = 6, m = 3 + // + // /#\ + // /###\ + // 01234 + // d = 5, m = 2 + // + // /\ + // /##\ + // 0123 + // d = 4, m = 2 + // + // /#\ + // 012 + // d = 3, m = 1 + // + Drone.prototype.prism = function(block,w,d){ + var stairEquiv = Drone.STAIRBLOCKS[block]; + if (stairEquiv){ + this.fwd().prism(stairEquiv,w,d-2).back(); + var d2 = 0; + var middle = Math.floor(d/2); + var uc = 0,dc = 0; + while (d2 < d) + { + var di = (d2 < middle?this.dir:(this.dir+2)%4); + var bd = block + ':' + this.playerToBlockDirs[di]; + var putStep = true; + if (d2 == middle){ + if (d % 2 == 1){ + putStep = false; + } + } + if (putStep) + this.cuboid(bd,w,1,1); + if (d2 < middle-1){ + this.up(); + uc++; + } + var modulo = d % 2; + if (modulo == 1){ + if (d2 > middle && d2= middle && d2