From e5d5d494914a3db74e69fcfa7dc3305188e77b54 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Sat, 7 Jan 2017 13:43:10 +1100 Subject: [PATCH] Added facings list, fixed a bunch of bugs introduced in recent refactoring. Added explicit roof fill option. Added roof to tower example. Fixed box-shed. --- README.rst | 70 ++++++++------ .../mechanicalcat/pycode/gui/GuiTextArea.java | 1 + .../pycode/script/BlockMethods.java | 2 +- .../pycode/script/HandMethods.java | 11 +-- .../pycode/script/PyRegistry.java | 11 +-- .../pycode/script/PythonCode.java | 6 +- .../mechanicalcat/pycode/script/RoofGen.java | 95 +++++++++++-------- 7 files changed, 115 insertions(+), 81 deletions(-) diff --git a/README.rst b/README.rst index b8cd3c4..27ecf78 100644 --- a/README.rst +++ b/README.rst @@ -82,20 +82,12 @@ use the "hand" name here too: pos.add(1, 0, 4) # East/X 1, Up/Y 0 and North/Z 4 ``chat("message")`` Have the message appear in the in-game chat. -``water(pos)`` - Have a water source be created at the position, for example - ``water(pos.up())``. This will only work if the target position is clear. -``lava(pos)`` - Have a water source be created at the position. This will only work if - the target position is clear. -``clear(pos)`` - Clear the block at the position nominated. ``colors`` - A list of all the standard Minecraft dye color names. Combine with - random.choice() for fun! - - Note: using clear with the Python Block position will remove the block! + A list of all the standard Minecraft dye color names. +``facings`` + A list of all the standard Minecraft facing names. +Choose colors and facings with random.choice() for extra creativity! Event Handlers ~~~~~~~~~~~~~~ @@ -125,7 +117,13 @@ Doc TBD:: Event Handlers ~~~~~~~~~~~~~~ -Doc TBD:: +Both Python Blocks and Hands may define a "run" function:: + + def run(): + # invoked when the Python Wand is used on the block + +Additionally, Python Blocks may define other functions related +to world interaction with the block:: def powerOn(): # invoked when a redstone signal powers block @@ -289,13 +287,19 @@ You may alter block variations after they've been put down:: hand.put('wool', color='red') hand.alter(color='yellow') # any of the keywords above are acceptable -Roof styles include "hip", "gable" and "box-gable" (filled gable). To get a box gable +Roof styles include "hip", "gable", "box-gable" (flat ended gable), +"shed" (sloped one direction) and "box-shed". To get a box gable with overhang you could:: hand.roof(7, 5, 'oak', style='box-gable') hand.sidle(1) hand.roof(9, 5, 'dark_oak', style='gable') +By default roofs are filled to prevent spawning, but you can turn it +off: + + hand.roof(7, 5, 'oak', fill=False) + Examples ~~~~~~~~ @@ -330,12 +334,12 @@ Put each of these functions on a different page of the book:: def tower(): hand.down() hand.circle(5, 'cobblestone', fill=True) - for i in range(8): + for i in range(9): hand.up() if i in (3, 7): hand.circle(5, 'planks', fill=True) hand.circle(5, 'stone') - if i in (0, 4): + if i in (0, 4, 8): hand.put('torch') # page 2: door and ladder access @@ -369,24 +373,32 @@ Put each of these functions on a different page of the book:: # page 4: the complete tower def run(): + with hand.remember(): tower() + with hand.remember(): access() + with hand.remember(): furnish() with hand.remember(): - tower() - with hand.remember(): - access() - furnish() + hand.back(6) + hand.sidle(5) + hand.up(9) + hand.roof(11, 11, 'dark_oak', fill=False) Roof demo:: STYLES = ["hip", "gable", "shed", "box-gable", "box-shed"] - hand.face('east') - for style in STYLES: - for i in range(4): - hand.forward(2) - hand.roof(7, 5, 'oak', style=style) - hand.left() - hand.forward(2) - hand.forward(20) + def roofs(fill): + for style in STYLES: + for i in range(4): + hand.forward(2) + hand.roof(7, 5, 'oak', style=style, + fill=fill) + hand.left() + hand.forward(2) + hand.forward(20) + with hand.remember(): + roofs(False) + hand.sidle(20) + roofs(True) Wand ---- @@ -537,4 +549,4 @@ This is not an exhaustive list, and should probably be put into github issues. - texture map replacement *hand* - more roof generation styles - - allow roof generation to work with plain blocks as fallback + - tick() handling diff --git a/src/main/java/net/mechanicalcat/pycode/gui/GuiTextArea.java b/src/main/java/net/mechanicalcat/pycode/gui/GuiTextArea.java index 8a090ec..366a496 100644 --- a/src/main/java/net/mechanicalcat/pycode/gui/GuiTextArea.java +++ b/src/main/java/net/mechanicalcat/pycode/gui/GuiTextArea.java @@ -160,6 +160,7 @@ protected void keyTyped(char typedChar, int keyCode) throws IOException { } if (GuiScreen.isKeyComboCtrlV(keyCode)) { this._editString(GuiScreen.getClipboardString()); + this.setCursorPosition(0, 0); return; } diff --git a/src/main/java/net/mechanicalcat/pycode/script/BlockMethods.java b/src/main/java/net/mechanicalcat/pycode/script/BlockMethods.java index 6b5d61c..ea2f2aa 100644 --- a/src/main/java/net/mechanicalcat/pycode/script/BlockMethods.java +++ b/src/main/java/net/mechanicalcat/pycode/script/BlockMethods.java @@ -203,7 +203,7 @@ public void roof(PyObject[] args, String[] kws) throws BlockTypeError { if (this.world == null || this.world.isRemote) return; ArgParser r = new ArgParser("roof", s("pos", "width", "depth", "blockname"), // TODO PyRegistry.BLOCK_VARIATIONS - s("style", "color", "facing", "type", "half", "shape")); + s("style", "color", "facing", "type", "half", "shape", "fill")); r.parse(args, kws); MyBlockPos mpos = (MyBlockPos)r.get("pos").__tojava__(MyBlockPos.class); RoofGen.roof(r, this.world, mpos.blockPos, EnumFacing.NORTH); diff --git a/src/main/java/net/mechanicalcat/pycode/script/HandMethods.java b/src/main/java/net/mechanicalcat/pycode/script/HandMethods.java index 48ec15c..e312edd 100644 --- a/src/main/java/net/mechanicalcat/pycode/script/HandMethods.java +++ b/src/main/java/net/mechanicalcat/pycode/script/HandMethods.java @@ -117,16 +117,13 @@ private String[] s(String ... strings) { return strings; } - private IBlockState getBlockVariant(ArgParser spec) { - return PyRegistry.getBlockVariant(spec, this.hand.getPosition(), this.hand.getHorizontalFacing(), - (WorldServer)this.world); - } - public void put(PyObject[] args, String[] kws) { if (this.world == null || this.world.isRemote) return; ArgParser r = new ArgParser("put", s("blockname"), PyRegistry.BLOCK_VARIATIONS); r.parse(args, kws); - this.put(this.hand.getFacedPos(), getBlockVariant(r), this.hand.getHorizontalFacing()); + IBlockState state = PyRegistry.getBlockVariant(r, this.hand.getFacedPos(), this.hand.getHorizontalFacing(), + (WorldServer)this.world); + this.put(this.hand.getFacedPos(),state, this.hand.getHorizontalFacing()); } public void alter(PyObject[] args, String[] kws) { @@ -217,7 +214,7 @@ public void roof(PyObject[] args, String[] kws) throws BlockTypeError { if (this.world == null || this.world.isRemote) return; ArgParser r = new ArgParser("roof", s("width", "depth", "blockname"), // TODO PyRegistry.BLOCK_VARIATIONS - s("style", "color", "facing", "type", "half", "shape")); + s("style", "color", "facing", "type", "half", "shape", "fill")); r.parse(args, kws); RoofGen.roof(r, this.world, this.hand.getPosition(), this.hand.getHorizontalFacing()); } diff --git a/src/main/java/net/mechanicalcat/pycode/script/PyRegistry.java b/src/main/java/net/mechanicalcat/pycode/script/PyRegistry.java index 53d0654..c36d46a 100644 --- a/src/main/java/net/mechanicalcat/pycode/script/PyRegistry.java +++ b/src/main/java/net/mechanicalcat/pycode/script/PyRegistry.java @@ -75,7 +75,6 @@ public static IBlockState getBlockVariant(ArgParser spec, BlockPos pos, EnumFaci } IBlockState block_state = block.getDefaultState(); EnumFacing opposite = facing.getOpposite(); - BlockPos faced = pos.offset(facing); PropertyDirection direction; block_state = modifyBlockStateFromSpec(block_state, spec, facing); @@ -83,14 +82,14 @@ public static IBlockState getBlockVariant(ArgParser spec, BlockPos pos, EnumFaci // if we haven't had an explicit facing set then try to determine a good one if (!spec.has("facing")) { try { - direction = (PropertyDirection) block_state.getBlock().getClass().getField("FACING").get(block_state.getBlock()); - if (world.isAirBlock(faced)) { - // check whether the next pos along (pos -> faced -> farpos) is solid (attachable) - BlockPos farpos = faced.add(facing.getDirectionVec()); + direction = (PropertyDirection)block.getClass().getField("FACING").get(block); + if (world.isAirBlock(pos)) { + // check whether the next pos along (pos -> farpos) is solid (attachable) + BlockPos farpos = pos.offset(facing); if (world.isSideSolid(farpos, opposite, true)) { // attach in faced pos on farpos block_state = block_state.withProperty(direction, opposite); - FMLLog.fine("attach in faced pos=%s on farpos=%s", pos, opposite); + FMLLog.fine("attach in pos=%s facing=%s", pos, opposite); } } } catch (NoSuchFieldException | IllegalAccessException e) { diff --git a/src/main/java/net/mechanicalcat/pycode/script/PythonCode.java b/src/main/java/net/mechanicalcat/pycode/script/PythonCode.java index 8cafc62..f42ea46 100644 --- a/src/main/java/net/mechanicalcat/pycode/script/PythonCode.java +++ b/src/main/java/net/mechanicalcat/pycode/script/PythonCode.java @@ -213,11 +213,12 @@ public boolean eval(WorldServer world, BlockPos pos) { } } - private String[] utils = {"water", "lava", "clear", "colors"}; + private String[] utils = {"colors", "facings"}; public static HashMap COLORMAP = new HashMap(); public static HashMap FACINGMAP = new HashMap(); public static List colors = new LinkedList<>(); + public static List facings = new LinkedList<>(); public static void init() { COLORMAP.put("white", EnumDyeColor.WHITE); COLORMAP.put("orange", EnumDyeColor.ORANGE); @@ -246,6 +247,9 @@ public static void init() { for (String name : COLORMAP.keySet()) { colors.add(name); } + for (String name : FACINGMAP.keySet()) { + facings.add(name); + } } } diff --git a/src/main/java/net/mechanicalcat/pycode/script/RoofGen.java b/src/main/java/net/mechanicalcat/pycode/script/RoofGen.java index af51110..62b00e9 100644 --- a/src/main/java/net/mechanicalcat/pycode/script/RoofGen.java +++ b/src/main/java/net/mechanicalcat/pycode/script/RoofGen.java @@ -35,9 +35,9 @@ // it made sense at the time public class RoofGen { - private IBlockState stair, slab, fill; + private IBlockState stair, slab, filler; private WorldServer world; - private boolean north_south; + private boolean north_south, fill; private int width, depth; private BlockPos pos; @@ -81,12 +81,13 @@ public RoofGen(WorldServer world, BlockPos pos, EnumFacing actualFacing, this.stair = this.getRoofStair(material); if (this.stair == null) { // not a stair material so go with just blocks - this.stair = this.fill = this.slab = PyRegistry.getBlockVariant(spec, pos, actualFacing, world); + this.stair = this.filler = this.slab = PyRegistry.getBlockVariant(spec, pos, actualFacing, world); } else { - this.fill = this.getRoofFiller(material); + this.filler = this.getRoofFiller(material); this.slab = this.getSlabBlock(material); } this.north_south = actualFacing == EnumFacing.NORTH || actualFacing == EnumFacing.SOUTH; + this.fill = spec.getBoolean("fill", true); // alter pos, width and depth based on orientation so that the // code which always generates in the EAST facing will work @@ -158,8 +159,8 @@ public void hip() { IBlockState state = stair; if (x == 0) { // bottom side - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.EAST); if (z == 0) { @@ -169,8 +170,8 @@ public void hip() { } } } else if (x == depth-1) { - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { // top side state = state.withProperty(BlockStairs.FACING, EnumFacing.WEST); @@ -182,20 +183,22 @@ public void hip() { } } else if (z == 0) { // left side - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.SOUTH); } } else if (z == width - 1) { // right side - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.NORTH); } } else if (z < width-1) { - state = fill; + // don't fill the inside? + if (!fill) continue; + state = filler; } this.world.setBlockState(pos.add(x, 0, z), state); } @@ -223,39 +226,45 @@ public void gable(boolean box) { IBlockState state = stair; if (north_south) { if (z == 0) { - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.SOUTH); } } else if (z == width - 1) { - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.NORTH); } - } else if (box) { - // only fill if box gable - state = fill; + } else if (box && (x == 0 || x == depth - 1)) { + // fill ends flush if box gable + state = filler; + } else if (fill) { + // fill insides + state = filler; } else { continue; } } else { if (x == 0) { - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.EAST); } } else if (x == depth - 1) { - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.WEST); } - } else if (box) { - // only fill if box gable - state = fill; + } else if (box && (z == 0 || z == width - 1)) { + // fill ends flush if box style + state = filler; + } else if (fill) { + // fill insides + state = filler; } else { continue; } @@ -294,27 +303,39 @@ public void shed(boolean box) { IBlockState state = stair; if (north_south) { if (z == 0) { - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.SOUTH); } - } else if (box) { - // only fill if box gable - state = fill; + } else if (box && z == width - 1) { + // fill ends flush if box style + state = filler; + } else if (box && (x == 0 || x == depth - 1)) { + // fill ends flush if box style + state = filler; + } else if (fill) { + // fill insides + state = filler; } else { continue; } } else { if (x == 0) { - if (stair == fill) { - state = fill; + if (stair == filler) { + state = filler; } else { state = state.withProperty(BlockStairs.FACING, EnumFacing.EAST); } - } else if (box) { - // only fill if box gable - state = fill; + } else if (box && x == depth - 1) { + // fill ends flush if box style + state = filler; + } else if (box && (z == 0 || z == width - 1)) { + // fill ends flush if box style + state = filler; + } else if (fill) { + // fill insides + state = filler; } else { continue; }