diff --git a/build.gradle b/build.gradle index 36bb9be..cdf5a24 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ apply plugin: 'net.minecraftforge.gradle.forge' //Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. -version = "1.12.2-2.6" +version = "1.12.2-2.8" group = "nl.requios.effortlessbuilding" // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = "effortlessbuilding" @@ -21,7 +21,7 @@ compileJava { } minecraft { - version = "1.12.2-14.23.5.2768" + version = "1.12.2-14.23.5.2825" runDir = "run" // the mappings can be changed at any time, and must be in the following format. diff --git a/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java b/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java index b0d2da7..eaf33a6 100644 --- a/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java +++ b/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java @@ -39,7 +39,7 @@ public class EffortlessBuilding { public static final String MODID = "effortlessbuilding"; public static final String NAME = "Effortless Building"; - public static final String VERSION = "1.12.2-2.6"; + public static final String VERSION = "1.12.2-2.8"; @Mod.Instance(EffortlessBuilding.MODID) public static EffortlessBuilding instance; diff --git a/src/main/java/nl/requios/effortlessbuilding/EventHandler.java b/src/main/java/nl/requios/effortlessbuilding/EventHandler.java index 95d2bac..5ca6cec 100644 --- a/src/main/java/nl/requios/effortlessbuilding/EventHandler.java +++ b/src/main/java/nl/requios/effortlessbuilding/EventHandler.java @@ -98,7 +98,7 @@ public class EventHandler //But modifiers and QuickReplace should still work //Send message to client, which sends message back with raytrace info - EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(event.getPos(), event.getState()), (EntityPlayerMP) player); + EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()), (EntityPlayerMP) player); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java index e5f8e65..b34687c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java @@ -191,8 +191,9 @@ public class BuildModes { return currentlyBreaking.get(player) != null; } + //Find coordinates on a line bound by a plane - protected static Vec3d findXBound(double x, Vec3d start, Vec3d look) { + public static Vec3d findXBound(double x, Vec3d start, Vec3d look) { //then y and z are double y = (x - start.x) / look.x * look.y + start.y; double z = (x - start.x) / look.x * look.z + start.z; @@ -200,7 +201,7 @@ public class BuildModes { return new Vec3d(x, y, z); } - protected static Vec3d findYBound(double y, Vec3d start, Vec3d look) { + public static Vec3d findYBound(double y, Vec3d start, Vec3d look) { //then x and z are double x = (y - start.y) / look.y * look.x + start.x; double z = (y - start.y) / look.y * look.z + start.z; @@ -208,7 +209,7 @@ public class BuildModes { return new Vec3d(x, y, z); } - protected static Vec3d findZBound(double z, Vec3d start, Vec3d look) { + public static Vec3d findZBound(double z, Vec3d start, Vec3d look) { //then x and y are double x = (z - start.z) / look.z * look.x + start.x; double y = (z - start.z) / look.z * look.y + start.y; @@ -216,5 +217,4 @@ public class BuildModes { return new Vec3d(x, y, z); } - } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java index 29206f8..8b16b9a 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java @@ -4,33 +4,157 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import nl.requios.effortlessbuilding.helper.ReachHelper; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class Cube implements IBuildMode { + //In singleplayer client and server variables are shared + //Split everything that needs separate values and may not be called twice in one click + private Dictionary rightClickClientTable = new Hashtable<>(); + private Dictionary rightClickServerTable = new Hashtable<>(); + private Dictionary firstPosTable = new Hashtable<>(); + private Dictionary secondPosTable = new Hashtable<>(); + private Dictionary sideHitTable = new Hashtable<>(); + private Dictionary hitVecTable = new Hashtable<>(); + @Override public void initialize(EntityPlayer player) { - + rightClickClientTable.put(player.getUniqueID(), 0); + rightClickServerTable.put(player.getUniqueID(), 0); + firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN); + sideHitTable.put(player.getUniqueID(), EnumFacing.UP); + hitVecTable.put(player.getUniqueID(), Vec3d.ZERO); } @Override public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { - return new ArrayList<>(); + List list = new ArrayList<>(); + + Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; + int rightClickNr = rightClickTable.get(player.getUniqueID()); + rightClickNr++; + rightClickTable.put(player.getUniqueID(), rightClickNr); + + if (rightClickNr == 1) { + //If clicking in air, reset and try again + if (blockPos == null) { + rightClickTable.put(player.getUniqueID(), 0); + return list; + } + + //First click, remember starting position + firstPosTable.put(player.getUniqueID(), blockPos); + sideHitTable.put(player.getUniqueID(), sideHit); + hitVecTable.put(player.getUniqueID(), hitVec); + //Keep list empty, dont place any blocks yet + } else if (rightClickNr == 2) { + //Second click, find other floor point + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + BlockPos secondPos = Floor.findFloor(player, firstPos, skipRaytrace); + + if (secondPos == null) { + rightClickTable.put(player.getUniqueID(), 1); + return list; + } + + secondPosTable.put(player.getUniqueID(), secondPos); + + } else { + //Third click, place cube with height + list = findCoordinates(player, blockPos, skipRaytrace); + rightClickTable.put(player.getUniqueID(), 0); + } + + return list; } @Override public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { - return new ArrayList<>(); + List list = new ArrayList<>(); + Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; + int rightClickNr = rightClickTable.get(player.getUniqueID()); + + if (rightClickNr == 0) { + if (blockPos != null) + list.add(blockPos); + } else if (rightClickNr == 1) { + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + + BlockPos secondPos = Floor.findFloor(player, firstPos, skipRaytrace); + if (secondPos == null) return list; + + //Add whole floor + //Limit amount of blocks you can place per row + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + + int x1 = firstPos.getX(), x2 = secondPos.getX(); + int y = firstPos.getY(); + int z1 = firstPos.getZ(), z2 = secondPos.getZ(); + + //limit axis + if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; + if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1; + if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; + if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; + + for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { + + for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { + + list.add(new BlockPos(l, y, n)); + } + } + + } else { + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + BlockPos secondPos = secondPosTable.get(player.getUniqueID()); + + BlockPos thirdPos = DiagonalLine.findHeight(player, secondPos, skipRaytrace); + if (thirdPos == null) return list; + + //Add whole cube + //Limit amount of blocks you can place per row + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); + + int x1 = firstPos.getX(), x2 = thirdPos.getX(); + int y1 = firstPos.getY(), y2 = thirdPos.getY(); + int z1 = firstPos.getZ(), z2 = thirdPos.getZ(); + + //limit axis + if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; + if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1; + if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1; + if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1; + if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; + if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; + + for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { + + for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { + + //check if whole row fits within limit + if (Math.abs(y1 - y2) < limit - list.size()) { + + for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { + list.add(new BlockPos(l, m, n)); + } + } + } + } + } + + return list; } @Override public EnumFacing getSideHit(EntityPlayer player) { - return null; + return sideHitTable.get(player.getUniqueID()); } @Override public Vec3d getHitVec(EntityPlayer player) { - return null; + return hitVecTable.get(player.getUniqueID()); } -} +} \ No newline at end of file diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java index 1823ad5..cee5498 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java @@ -3,34 +3,226 @@ package nl.requios.effortlessbuilding.buildmode; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; +import nl.requios.effortlessbuilding.helper.ReachHelper; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class DiagonalLine implements IBuildMode { + //In singleplayer client and server variables are shared + //Split everything that needs separate values and may not be called twice in one click + private Dictionary rightClickClientTable = new Hashtable<>(); + private Dictionary rightClickServerTable = new Hashtable<>(); + private Dictionary firstPosTable = new Hashtable<>(); + private Dictionary secondPosTable = new Hashtable<>(); + private Dictionary sideHitTable = new Hashtable<>(); + private Dictionary hitVecTable = new Hashtable<>(); + + static class HeightCriteria { + Vec3d planeBound; + Vec3d lineBound; + double distToLineSq; + double distToPlayerSq; + + HeightCriteria(Vec3d planeBound, BlockPos secondPos, Vec3d start) { + this.planeBound = planeBound; + this.lineBound = toLongestLine(this.planeBound, secondPos); + this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSquared(); + this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared(); + } + + //Make it from a plane into a line, on y axis only + private Vec3d toLongestLine(Vec3d boundVec, BlockPos secondPos) { + BlockPos bound = new BlockPos(boundVec); + return new Vec3d(secondPos.getX(), bound.getY(), secondPos.getZ()); + } + + //check if its not behind the player and its not too close and not too far + //also check if raytrace from player to block does not intersect blocks + public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) { + + boolean intersects = false; + if (!skipRaytrace) { + //collision within a 1 block radius to selected is fine + RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, lineBound, false, true, false); + intersects = rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK && + planeBound.subtract(rayTraceResult.hitVec).lengthSquared() > 4; + } + + return planeBound.subtract(start).dotProduct(look) > 0 && + distToPlayerSq > 2 && distToPlayerSq < reach * reach && + !intersects; + } + } + @Override public void initialize(EntityPlayer player) { - + rightClickClientTable.put(player.getUniqueID(), 0); + rightClickServerTable.put(player.getUniqueID(), 0); + firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN); + sideHitTable.put(player.getUniqueID(), EnumFacing.UP); + hitVecTable.put(player.getUniqueID(), Vec3d.ZERO); } @Override public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { - return new ArrayList<>(); + List list = new ArrayList<>(); + + Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; + int rightClickNr = rightClickTable.get(player.getUniqueID()); + rightClickNr++; + rightClickTable.put(player.getUniqueID(), rightClickNr); + + if (rightClickNr == 1) { + //If clicking in air, reset and try again + if (blockPos == null) { + rightClickTable.put(player.getUniqueID(), 0); + return list; + } + + //First click, remember starting position + firstPosTable.put(player.getUniqueID(), blockPos); + sideHitTable.put(player.getUniqueID(), sideHit); + hitVecTable.put(player.getUniqueID(), hitVec); + //Keep list empty, dont place any blocks yet + } else if (rightClickNr == 2) { + //Second click, find other floor point + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + BlockPos secondPos = Floor.findFloor(player, firstPos, true); + + if (secondPos == null) { + rightClickTable.put(player.getUniqueID(), 1); + return list; + } + + secondPosTable.put(player.getUniqueID(), secondPos); + + } else { + //Third click, place diagonal line with height + list = findCoordinates(player, blockPos, skipRaytrace); + rightClickTable.put(player.getUniqueID(), 0); + } + + return list; } @Override public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { - return new ArrayList<>(); + List list = new ArrayList<>(); + Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; + int rightClickNr = rightClickTable.get(player.getUniqueID()); + + if (rightClickNr == 0) { + if (blockPos != null) + list.add(blockPos); + } else if (rightClickNr == 1) { + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + + BlockPos secondPos = Floor.findFloor(player, firstPos, true); + if (secondPos == null) return list; + + //Add diagonal line from first to second + list.addAll(getDiagonalLineBlocks(player , firstPos, secondPos, 10)); + + } else { + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + BlockPos secondPos = secondPosTable.get(player.getUniqueID()); + + BlockPos thirdPos = findHeight(player, secondPos, skipRaytrace); + if (thirdPos == null) return list; + + //Add diagonal line from first to third + list.addAll(getDiagonalLineBlocks(player , firstPos, thirdPos, 10)); + } + + return list; + } + + //Finds height after floor has been chosen in buildmodes with 3 clicks + public static BlockPos findHeight(EntityPlayer player, BlockPos secondPos, boolean skipRaytrace) { + Vec3d look = player.getLookVec(); + Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ); + + List criteriaList = new ArrayList<>(3); + + //X + Vec3d xBound = BuildModes.findXBound(secondPos.getX(), start, look); + criteriaList.add(new HeightCriteria(xBound, secondPos, start)); + + //Z + Vec3d zBound = BuildModes.findZBound(secondPos.getZ(), start, look); + criteriaList.add(new HeightCriteria(zBound, secondPos, start)); + + //Remove invalid criteria + int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach + criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace)); + + //If none are valid, return empty list of blocks + if (criteriaList.isEmpty()) return null; + + //If only 1 is valid, choose that one + HeightCriteria selected = criteriaList.get(0); + + //If multiple are valid, choose based on criteria + if (criteriaList.size() > 1) { + //Select the one that is closest (from wall position to its line counterpart) + for (int i = 1; i < criteriaList.size(); i++) { + HeightCriteria criteria = criteriaList.get(i); + if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) { + //Both very close to line, choose closest to player + if (criteria.distToPlayerSq < selected.distToPlayerSq) + selected = criteria; + } else { + //Pick closest to line + if (criteria.distToLineSq < selected.distToLineSq) + selected = criteria; + } + } + } + return new BlockPos(selected.lineBound); + } + + //Add diagonal line from first to second + public static List getDiagonalLineBlocks(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, int sampleMultiplier) { + List list = new ArrayList<>(); + + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + + int x1 = firstPos.getX(), x2 = secondPos.getX(); + int y1 = firstPos.getY(), y2 = secondPos.getY(); + int z1 = firstPos.getZ(), z2 = secondPos.getZ(); + + //limit axis + if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; + if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1; + if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1; + if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1; + if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; + if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; + + Vec3d first = new Vec3d(x1, y1, z1).add(0.5, 0.5, 0.5); + Vec3d second = new Vec3d(x2, y2, z2).add(0.5, 0.5, 0.5); + + int iterations = (int) Math.ceil(first.distanceTo(second)) * sampleMultiplier; + for (double t = 0; t <= 1.0; t += 1.0/iterations) { + Vec3d lerp = first.add(second.subtract(first).scale(t)); + BlockPos candidate = new BlockPos(lerp); + //Only add if not equal to the last in the list + if (list.isEmpty() || !list.get(list.size() - 1).equals(candidate)) + list.add(candidate); + } + + return list; } @Override public EnumFacing getSideHit(EntityPlayer player) { - return null; + return sideHitTable.get(player.getUniqueID()); } @Override public Vec3d getHitVec(EntityPlayer player) { - return null; + return hitVecTable.get(player.getUniqueID()); } -} +} \ No newline at end of file diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java index 5f25335..7ba351c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java @@ -4,33 +4,135 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import nl.requios.effortlessbuilding.helper.ReachHelper; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class DiagonalWall implements IBuildMode { + //In singleplayer client and server variables are shared + //Split everything that needs separate values and may not be called twice in one click + private Dictionary rightClickClientTable = new Hashtable<>(); + private Dictionary rightClickServerTable = new Hashtable<>(); + private Dictionary firstPosTable = new Hashtable<>(); + private Dictionary secondPosTable = new Hashtable<>(); + private Dictionary sideHitTable = new Hashtable<>(); + private Dictionary hitVecTable = new Hashtable<>(); + @Override public void initialize(EntityPlayer player) { - + rightClickClientTable.put(player.getUniqueID(), 0); + rightClickServerTable.put(player.getUniqueID(), 0); + firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN); + sideHitTable.put(player.getUniqueID(), EnumFacing.UP); + hitVecTable.put(player.getUniqueID(), Vec3d.ZERO); } @Override public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { - return new ArrayList<>(); + List list = new ArrayList<>(); + + Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; + int rightClickNr = rightClickTable.get(player.getUniqueID()); + rightClickNr++; + rightClickTable.put(player.getUniqueID(), rightClickNr); + + if (rightClickNr == 1) { + //If clicking in air, reset and try again + if (blockPos == null) { + rightClickTable.put(player.getUniqueID(), 0); + return list; + } + + //First click, remember starting position + firstPosTable.put(player.getUniqueID(), blockPos); + sideHitTable.put(player.getUniqueID(), sideHit); + hitVecTable.put(player.getUniqueID(), hitVec); + //Keep list empty, dont place any blocks yet + } else if (rightClickNr == 2) { + //Second click, find other floor point + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + BlockPos secondPos = Floor.findFloor(player, firstPos, true); + + if (secondPos == null) { + rightClickTable.put(player.getUniqueID(), 1); + return list; + } + + secondPosTable.put(player.getUniqueID(), secondPos); + + } else { + //Third click, place diagonal wall with height + list = findCoordinates(player, blockPos, skipRaytrace); + rightClickTable.put(player.getUniqueID(), 0); + } + + return list; } @Override public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { - return new ArrayList<>(); + List list = new ArrayList<>(); + Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; + int rightClickNr = rightClickTable.get(player.getUniqueID()); + + if (rightClickNr == 0) { + if (blockPos != null) + list.add(blockPos); + } else if (rightClickNr == 1) { + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + + BlockPos secondPos = Floor.findFloor(player, firstPos, true); + if (secondPos == null) return list; + + //Add diagonal line + list.addAll(DiagonalLine.getDiagonalLineBlocks(player, firstPos, secondPos, 1)); + + } else { + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + BlockPos secondPos = secondPosTable.get(player.getUniqueID()); + + BlockPos thirdPos = DiagonalLine.findHeight(player, secondPos, skipRaytrace); + if (thirdPos == null) return list; + + //Add diagonal wall + list.addAll(getDiagonalWallBlocks(player, firstPos, secondPos, thirdPos)); + } + + return list; + } + + //Add diagonal wall from first to second + public static List getDiagonalWallBlocks(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, BlockPos thirdPos) { + List list = new ArrayList<>(); + + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + + //Get diagonal line blocks + List diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, firstPos, secondPos, 1); + + //Limit amount of blocks we can place + int lowest = Math.min(firstPos.getY(), thirdPos.getY()); + int highest = Math.max(firstPos.getY(), thirdPos.getY()); + + if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1; + + //Copy diagonal line on y axis + for (int y = lowest; y <= highest; y++) { + for (BlockPos blockPos : diagonalLineBlocks) { + list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ())); + } + } + + return list; } @Override public EnumFacing getSideHit(EntityPlayer player) { - return null; + return sideHitTable.get(player.getUniqueID()); } @Override public Vec3d getHitVec(EntityPlayer player) { - return null; + return hitVecTable.get(player.getUniqueID()); } -} +} \ No newline at end of file diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java index 0a3e6c7..3a7f97b 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java @@ -5,7 +5,6 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; -import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.helper.ReachHelper; import java.util.*; @@ -13,13 +12,13 @@ import java.util.*; public class Floor implements IBuildMode { //In singleplayer client and server variables are shared //Split everything that needs separate values and may not be called twice in one click - Dictionary rightClickClientTable = new Hashtable<>(); - Dictionary rightClickServerTable = new Hashtable<>(); - Dictionary firstPosTable = new Hashtable<>(); - Dictionary sideHitTable = new Hashtable<>(); - Dictionary hitVecTable = new Hashtable<>(); + private Dictionary rightClickClientTable = new Hashtable<>(); + private Dictionary rightClickServerTable = new Hashtable<>(); + private Dictionary firstPosTable = new Hashtable<>(); + private Dictionary sideHitTable = new Hashtable<>(); + private Dictionary hitVecTable = new Hashtable<>(); - class Criteria { + static class Criteria { Vec3d planeBound; double distToPlayerSq; @@ -101,32 +100,13 @@ public class Floor implements IBuildMode { if (secondPos == null) return list; //Add whole floor - //Limit amount of blocks you can place per row - int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); - - int x1 = firstPos.getX(), x2 = secondPos.getX(); - int y1 = firstPos.getY(), y2 = secondPos.getY(); - int z1 = firstPos.getZ(), z2 = secondPos.getZ(); - - for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { - - for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { - - //check if whole row fits within limit - if (Math.abs(y1 - y2) < limit - list.size()) { - - for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { - list.add(new BlockPos(l, m, n)); - } - } - } - } + list.addAll(getFloorBlocks(player, firstPos, secondPos)); } return list; } - public BlockPos findFloor(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) { + public static BlockPos findFloor(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) { Vec3d look = player.getLookVec(); Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ); @@ -149,6 +129,33 @@ public class Floor implements IBuildMode { return new BlockPos(selected.planeBound); } + public static List getFloorBlocks(EntityPlayer player, BlockPos firstPos, BlockPos secondPos) { + List list = new ArrayList<>(); + + //Limit amount of blocks you can place per row + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + + int x1 = firstPos.getX(), x2 = secondPos.getX(); + int y = firstPos.getY(); + int z1 = firstPos.getZ(), z2 = secondPos.getZ(); + + //limit axis + if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; + if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1; + if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; + if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; + + for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { + + for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { + + list.add(new BlockPos(l, y, n)); + } + } + + return list; + } + @Override public EnumFacing getSideHit(EntityPlayer player) { return sideHitTable.get(player.getUniqueID()); diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java index e5dde8c..95db40c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java @@ -5,7 +5,6 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; -import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.helper.ReachHelper; import java.util.*; @@ -13,13 +12,13 @@ import java.util.*; public class Line implements IBuildMode { //In singleplayer client and server variables are shared //Split everything that needs separate values and may not be called twice in one click - Dictionary rightClickClientTable = new Hashtable<>(); - Dictionary rightClickServerTable = new Hashtable<>(); - Dictionary firstPosTable = new Hashtable<>(); - Dictionary sideHitTable = new Hashtable<>(); - Dictionary hitVecTable = new Hashtable<>(); + private Dictionary rightClickClientTable = new Hashtable<>(); + private Dictionary rightClickServerTable = new Hashtable<>(); + private Dictionary firstPosTable = new Hashtable<>(); + private Dictionary sideHitTable = new Hashtable<>(); + private Dictionary hitVecTable = new Hashtable<>(); - class Criteria { + static class Criteria { Vec3d planeBound; Vec3d lineBound; double distToLineSq; @@ -124,31 +123,13 @@ public class Line implements IBuildMode { BlockPos secondPos = findLine(player, firstPos, skipRaytrace); if (secondPos == null) return list; - //Limit amount of blocks we can place - int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); - - //Add whole line - int x1 = firstPos.getX(), x2 = secondPos.getX(); - int y1 = firstPos.getY(), y2 = secondPos.getY(); - int z1 = firstPos.getZ(), z2 = secondPos.getZ(); - - outerloop: - for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { - - for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { - - for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { - if (list.size() >= axisLimit) break outerloop; - list.add(new BlockPos(l, m, n)); - } - } - } + list.addAll(getLineBlocks(player, firstPos, secondPos)); } return list; } - public BlockPos findLine(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) { + public static BlockPos findLine(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) { Vec3d look = player.getLookVec(); Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ); @@ -197,6 +178,31 @@ public class Line implements IBuildMode { return new BlockPos(selected.lineBound); } + public static List getLineBlocks(EntityPlayer player, BlockPos firstPos, BlockPos secondPos) { + List list = new ArrayList<>(); + + //Limit amount of blocks we can place + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + + //Add whole line + int x1 = firstPos.getX(), x2 = secondPos.getX(); + int y1 = firstPos.getY(), y2 = secondPos.getY(); + int z1 = firstPos.getZ(), z2 = secondPos.getZ(); + + outerloop: + for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { + + for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { + + for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { + if (list.size() >= axisLimit) break outerloop; + list.add(new BlockPos(l, m, n)); + } + } + } + + return list; + } @Override public EnumFacing getSideHit(EntityPlayer player) { diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java index b3c3d74..6f1589c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java @@ -4,33 +4,173 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import nl.requios.effortlessbuilding.helper.ReachHelper; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class SlopeFloor implements IBuildMode { + //In singleplayer client and server variables are shared + //Split everything that needs separate values and may not be called twice in one click + private Dictionary rightClickClientTable = new Hashtable<>(); + private Dictionary rightClickServerTable = new Hashtable<>(); + private Dictionary firstPosTable = new Hashtable<>(); + private Dictionary secondPosTable = new Hashtable<>(); + private Dictionary sideHitTable = new Hashtable<>(); + private Dictionary hitVecTable = new Hashtable<>(); + @Override public void initialize(EntityPlayer player) { - + rightClickClientTable.put(player.getUniqueID(), 0); + rightClickServerTable.put(player.getUniqueID(), 0); + firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN); + sideHitTable.put(player.getUniqueID(), EnumFacing.UP); + hitVecTable.put(player.getUniqueID(), Vec3d.ZERO); } @Override public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { - return new ArrayList<>(); + List list = new ArrayList<>(); + + Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; + int rightClickNr = rightClickTable.get(player.getUniqueID()); + rightClickNr++; + rightClickTable.put(player.getUniqueID(), rightClickNr); + + if (rightClickNr == 1) { + //If clicking in air, reset and try again + if (blockPos == null) { + rightClickTable.put(player.getUniqueID(), 0); + return list; + } + + //First click, remember starting position + firstPosTable.put(player.getUniqueID(), blockPos); + sideHitTable.put(player.getUniqueID(), sideHit); + hitVecTable.put(player.getUniqueID(), hitVec); + //Keep list empty, dont place any blocks yet + } else if (rightClickNr == 2) { + //Second click, find other floor point + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + BlockPos secondPos = Floor.findFloor(player, firstPos, true); + + if (secondPos == null) { + rightClickTable.put(player.getUniqueID(), 1); + return list; + } + + secondPosTable.put(player.getUniqueID(), secondPos); + + } else { + //Third click, place slope floor with height + list = findCoordinates(player, blockPos, skipRaytrace); + rightClickTable.put(player.getUniqueID(), 0); + } + + return list; } @Override public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { - return new ArrayList<>(); + List list = new ArrayList<>(); + Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; + int rightClickNr = rightClickTable.get(player.getUniqueID()); + + if (rightClickNr == 0) { + if (blockPos != null) + list.add(blockPos); + } else if (rightClickNr == 1) { + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + + BlockPos secondPos = Floor.findFloor(player, firstPos, true); + if (secondPos == null) return list; + + //Add whole floor + list.addAll(Floor.getFloorBlocks(player, firstPos, secondPos)); + + } else { + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + BlockPos secondPos = secondPosTable.get(player.getUniqueID()); + + BlockPos thirdPos = DiagonalLine.findHeight(player, secondPos, skipRaytrace); + if (thirdPos == null) return list; + + //Add whole cube + list.addAll(getSlopeFloorBlocks(player, firstPos, secondPos, thirdPos)); + } + + return list; + } + + //Add slope floor from first to second + public static List getSlopeFloorBlocks(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, BlockPos thirdPos) { + List list = new ArrayList<>(); + + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + + //Determine whether to use x or z axis to slope up + boolean onXAxis = true; + + int xLength = Math.abs(secondPos.getX() - firstPos.getX()); + int zLength = Math.abs(secondPos.getZ() - firstPos.getZ()); + + //Slope along short edge + if (zLength > xLength) onXAxis = false; + + //TODO add option for Slope along long edge + //if (zLength > xLength) onXAxis = true; + + if (onXAxis) { + //Along X goes up + + //Get diagonal line blocks + BlockPos linePoint = new BlockPos(secondPos.getX(), thirdPos.getY(), firstPos.getZ()); + List diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, firstPos, linePoint, 1); + + //Limit amount of blocks we can place + int lowest = Math.min(firstPos.getZ(), secondPos.getZ()); + int highest = Math.max(firstPos.getZ(), secondPos.getZ()); + + if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1; + + //Copy diagonal line on x axis + for (int z = lowest; z <= highest; z++) { + for (BlockPos blockPos : diagonalLineBlocks) { + list.add(new BlockPos(blockPos.getX(), blockPos.getY(), z)); + } + } + + } else { + //Along Z goes up + + //Get diagonal line blocks + BlockPos linePoint = new BlockPos(firstPos.getX(), thirdPos.getY(), secondPos.getZ()); + List diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, firstPos, linePoint, 1); + + //Limit amount of blocks we can place + int lowest = Math.min(firstPos.getX(), secondPos.getX()); + int highest = Math.max(firstPos.getX(), secondPos.getX()); + + if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1; + + //Copy diagonal line on x axis + for (int x = lowest; x <= highest; x++) { + for (BlockPos blockPos : diagonalLineBlocks) { + list.add(new BlockPos(x, blockPos.getY(), blockPos.getZ())); + } + } + } + + + return list; } @Override public EnumFacing getSideHit(EntityPlayer player) { - return null; + return sideHitTable.get(player.getUniqueID()); } @Override public Vec3d getHitVec(EntityPlayer player) { - return null; + return hitVecTable.get(player.getUniqueID()); } -} +} \ No newline at end of file diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java index 64e4273..1ac9c69 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java @@ -1,12 +1,10 @@ package nl.requios.effortlessbuilding.buildmode; -import com.sun.javafx.geom.Vec2d; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; -import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.helper.ReachHelper; import java.util.*; @@ -14,13 +12,13 @@ import java.util.*; public class Wall implements IBuildMode { //In singleplayer client and server variables are shared //Split everything that needs separate values and may not be called twice in one click - Dictionary rightClickClientTable = new Hashtable<>(); - Dictionary rightClickServerTable = new Hashtable<>(); - Dictionary firstPosTable = new Hashtable<>(); - Dictionary sideHitTable = new Hashtable<>(); - Dictionary hitVecTable = new Hashtable<>(); + private Dictionary rightClickClientTable = new Hashtable<>(); + private Dictionary rightClickServerTable = new Hashtable<>(); + private Dictionary firstPosTable = new Hashtable<>(); + private Dictionary sideHitTable = new Hashtable<>(); + private Dictionary hitVecTable = new Hashtable<>(); - class Criteria { + static class Criteria { Vec3d planeBound; double distToPlayerSq; double angle; @@ -29,9 +27,7 @@ public class Wall implements IBuildMode { this.planeBound = planeBound; this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared(); Vec3d wall = this.planeBound.subtract(new Vec3d(firstPos)); - Vec2d horizontalWall = new Vec2d(wall.x, wall.z); - Vec2d horizontalLook = new Vec2d(look.x, look.z); - this.angle = horizontalWall.x * horizontalLook.x + horizontalWall.y * horizontalLook.y; + this.angle = wall.x * look.x + wall.z * look.z; //dot product ignoring y (looking up/down should not affect this angle) } //check if its not behind the player and its not too close and not too far @@ -107,41 +103,13 @@ public class Wall implements IBuildMode { if (secondPos == null) return list; //Add whole wall - //Limit amount of blocks we can place per row - int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); - int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); - - int x1 = firstPos.getX(), x2 = secondPos.getX(); - int y1 = firstPos.getY(), y2 = secondPos.getY(); - int z1 = firstPos.getZ(), z2 = secondPos.getZ(); - - //limit axis - if (x2 - x1 > axisLimit) x2 = x1 + axisLimit; - if (x1 - x2 > axisLimit) x2 = x1 - axisLimit; - if (y2 - y1 > axisLimit) y2 = y1 + axisLimit; - if (y1 - y2 > axisLimit) y2 = y1 - axisLimit; - if (z2 - z1 > axisLimit) z2 = z1 + axisLimit; - if (z1 - z2 > axisLimit) z2 = z1 - axisLimit; - - for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { - - for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { - - //check if whole row fits within limit - if (Math.abs(y1 - y2) < limit - list.size()) { - - for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { - list.add(new BlockPos(l, m, n)); - } - } - } - } + list.addAll(getWallBlocks(player, firstPos, secondPos)); } return list; } - public BlockPos findWall(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) { + public static BlockPos findWall(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) { Vec3d look = player.getLookVec(); Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ); @@ -179,6 +147,42 @@ public class Wall implements IBuildMode { return new BlockPos(selected.planeBound); } + public static List getWallBlocks(EntityPlayer player, BlockPos firstPos, BlockPos secondPos) { + List list = new ArrayList<>(); + + //Limit amount of blocks we can place per row + int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + + int x1 = firstPos.getX(), x2 = secondPos.getX(); + int y1 = firstPos.getY(), y2 = secondPos.getY(); + int z1 = firstPos.getZ(), z2 = secondPos.getZ(); + + //limit axis + if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; + if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1; + if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1; + if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1; + if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; + if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; + + for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { + + for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { + + //check if whole row fits within limit + if (Math.abs(y1 - y2) < limit - list.size()) { + + for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { + list.add(new BlockPos(l, m, n)); + } + } + } + } + + return list; + } + @Override public EnumFacing getSideHit(EntityPlayer player) { return sideHitTable.get(player.getUniqueID()); diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BlockSet.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BlockSet.java index 6098f2e..0e9619f 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BlockSet.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BlockSet.java @@ -1,7 +1,7 @@ package nl.requios.effortlessbuilding.buildmodifier; +import mod.chiselsandbits.api.IBitLocation; import net.minecraft.block.state.IBlockState; -import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -9,15 +9,17 @@ import java.util.List; public class BlockSet { private List coordinates; - private List blockStates; + private List previousBlockStates; + private List newBlockStates; private Vec3d hitVec; private BlockPos firstPos; private BlockPos secondPos; - public BlockSet(List coordinates, List blockStates, Vec3d hitVec, + public BlockSet(List coordinates, List previousBlockStates, List newBlockStates, Vec3d hitVec, BlockPos firstPos, BlockPos secondPos) { this.coordinates = coordinates; - this.blockStates = blockStates; + this.previousBlockStates = previousBlockStates; + this.newBlockStates = newBlockStates; this.hitVec = hitVec; this.firstPos = firstPos; this.secondPos = secondPos; @@ -27,8 +29,12 @@ public class BlockSet { return coordinates; } - public List getBlockStates() { - return blockStates; + public List getPreviousBlockStates() { + return previousBlockStates; + } + + public List getNewBlockStates() { + return newBlockStates; } public Vec3d getHitVec() { diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java index 32916a7..642fd87 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java @@ -3,7 +3,6 @@ package nl.requios.effortlessbuilding.buildmodifier; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; @@ -11,14 +10,10 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import nl.requios.effortlessbuilding.BuildConfig; -import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.compatibility.CompatHelper; -import nl.requios.effortlessbuilding.helper.FixedStack; import nl.requios.effortlessbuilding.helper.InventoryHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.item.ItemRandomizerBag; -import nl.requios.effortlessbuilding.network.BlockPlacedMessage; import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; import java.util.*; @@ -42,10 +37,19 @@ public class BuildModifiers { //check if valid blockstates if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return; + //remember previous blockstates for undo + List previousBlockStates = new ArrayList<>(coordinates.size()); + List newBlockStates = new ArrayList<>(coordinates.size()); + for (BlockPos coordinate : coordinates) { + previousBlockStates.add(world.getBlockState(coordinate)); + } + if (world.isRemote) { BlockPreviewRenderer.onBlocksPlaced(); + newBlockStates = blockStates; + } else { //place blocks @@ -58,45 +62,75 @@ public class BuildModifiers { //check itemstack empty if (itemStack.isEmpty()) { //try to find new stack, otherwise continue - itemStack = InventoryHelper.findItemStackInInventory(player, blockState); + itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock()); if (itemStack.isEmpty()) continue; } - SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false); + SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false, false); } } + + //find actual new blockstates for undo + for (BlockPos coordinate : coordinates) { + newBlockStates.add(world.getBlockState(coordinate)); + } } //add to undo stack BlockPos firstPos = startCoordinates.get(0); BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1); - UndoRedo.addUndo(player, new BlockSet(coordinates, blockStates, hitVec, firstPos, secondPos)); + UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos)); } - public static void onBlockBroken(EntityPlayer player, List posList, boolean breakStartPos) { + public static void onBlockBroken(EntityPlayer player, List startCoordinates, boolean breakStartPos) { World world = player.world; - List coordinates = findCoordinates(player, posList); + List coordinates = findCoordinates(player, startCoordinates); if (coordinates.isEmpty()) return; + //remember previous blockstates for undo + List previousBlockStates = new ArrayList<>(coordinates.size()); + List newBlockStates = new ArrayList<>(coordinates.size()); + for (BlockPos coordinate : coordinates) { + previousBlockStates.add(world.getBlockState(coordinate)); + } + if (world.isRemote) { BlockPreviewRenderer.onBlocksBroken(); - return; - } - //If the player is going to instabreak grass or a plant, only break other instabreaking things - boolean onlyInstaBreaking = !player.isCreative() && - world.getBlockState(posList.get(0)).getBlockHardness(world, posList.get(0)) == 0f; + //list of air blockstates + for (BlockPos coordinate : coordinates) { + newBlockStates.add(Block.getBlockById(0).getDefaultState()); + } - //break all those blocks - for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) { - BlockPos coordinate = coordinates.get(i); - if (world.isBlockLoaded(coordinate, false)) { - if (!onlyInstaBreaking || world.getBlockState(coordinate).getBlockHardness(world, coordinate) == 0f) { - SurvivalHelper.breakBlock(world, player, coordinate); + } else { + + //If the player is going to instabreak grass or a plant, only break other instabreaking things + boolean onlyInstaBreaking = !player.isCreative() && + world.getBlockState(startCoordinates.get(0)).getBlockHardness(world, startCoordinates.get(0)) == 0f; + + //break all those blocks + for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) { + BlockPos coordinate = coordinates.get(i); + if (world.isBlockLoaded(coordinate, false)) { + if (!onlyInstaBreaking || world.getBlockState(coordinate).getBlockHardness(world, coordinate) == 0f) { + SurvivalHelper.breakBlock(world, player, coordinate, false); + } } } + + //find actual new blockstates for undo + for (BlockPos coordinate : coordinates) { + newBlockStates.add(world.getBlockState(coordinate)); + } } + + //add to undo stack + BlockPos firstPos = startCoordinates.get(0); + BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1); + Vec3d hitVec = new Vec3d(0.5, 0.5, 0.5); + UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos)); + } public static List findCoordinates(EntityPlayer player, List posList) { diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/UndoRedo.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/UndoRedo.java index ea585c3..0eb21ce 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/UndoRedo.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/UndoRedo.java @@ -1,12 +1,16 @@ package nl.requios.effortlessbuilding.buildmodifier; +import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.helper.FixedStack; import nl.requios.effortlessbuilding.helper.InventoryHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper; @@ -16,6 +20,7 @@ import java.util.*; public class UndoRedo { + //Undo and redo stacks per player //Gets added to twice in singleplayer (server and client) if not careful. So separate stacks. private static Map> undoStacksClient = new HashMap<>(); private static Map> undoStacksServer = new HashMap<>(); @@ -56,19 +61,39 @@ public class UndoRedo { BlockSet blockSet = undoStack.pop(); List coordinates = blockSet.getCoordinates(); - List blockStates = blockSet.getBlockStates(); + List previousBlockStates = blockSet.getPreviousBlockStates(); + List newBlockStates = blockSet.getNewBlockStates(); + Vec3d hitVec = blockSet.getHitVec(); //Find up to date itemstacks in player inventory - List itemStacks = findItemStacksInInventory(player, blockStates); + List itemStacks = findItemStacksInInventory(player, previousBlockStates); if (player.world.isRemote) { - BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, blockStates, blockSet.getSecondPos(), blockSet.getFirstPos()); + BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos()); } else { - //break all those blocks + //break all those blocks, reset to what they were for (int i = 0; i < coordinates.size(); i++) { BlockPos coordinate = coordinates.get(i); - if (player.world.isBlockLoaded(coordinate, false)) { - SurvivalHelper.breakBlock(player.world, player, coordinate); + ItemStack itemStack = itemStacks.get(i); + + //get blockstate from itemstack + IBlockState previousBlockState = Block.getBlockById(0).getDefaultState(); + if (itemStack.getItem() instanceof ItemBlock) { + previousBlockState = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState(); + } + + if (player.world.isBlockLoaded(coordinate, true)) { + //check itemstack empty + if (itemStack.isEmpty()) { + itemStack = findItemStackInInventory(player, previousBlockStates.get(i)); + //get blockstate from new itemstack + if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) { + previousBlockState = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState(); + } + } + if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true); + //if previousBlockState is air, placeBlock will set it to air + SurvivalHelper.placeBlock(player.world, player, coordinate, previousBlockState, itemStack, EnumFacing.UP, hitVec, true, false, false); } } } @@ -90,25 +115,32 @@ public class UndoRedo { BlockSet blockSet = redoStack.pop(); List coordinates = blockSet.getCoordinates(); - List blockStates = blockSet.getBlockStates(); + List newBlockStates = blockSet.getNewBlockStates(); Vec3d hitVec = blockSet.getHitVec(); //Find up to date itemstacks in player inventory - List itemStacks = findItemStacksInInventory(player, blockStates); + List itemStacks = findItemStacksInInventory(player, newBlockStates); if (player.world.isRemote) { - BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, blockStates, blockSet.getFirstPos(), blockSet.getSecondPos()); + BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos()); } else { //place blocks for (int i = 0; i < coordinates.size(); i++) { - BlockPos blockPos = coordinates.get(i); - IBlockState blockState = blockStates.get(i); + BlockPos coordinate = coordinates.get(i); + IBlockState newBlockState = newBlockStates.get(i); ItemStack itemStack = itemStacks.get(i); - if (player.world.isBlockLoaded(blockPos, true)) { + if (player.world.isBlockLoaded(coordinate, true)) { //check itemstack empty - if (itemStack.isEmpty()) continue; - SurvivalHelper.placeBlock(player.world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false); + if (itemStack.isEmpty()) { + itemStack = findItemStackInInventory(player, newBlockStates.get(i)); + //get blockstate from new itemstack + if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) { + newBlockState = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState(); + } + } + if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true); + SurvivalHelper.placeBlock(player.world, player, coordinate, newBlockState, itemStack, EnumFacing.UP, hitVec, true, false, false); } } } @@ -133,8 +165,29 @@ public class UndoRedo { private static List findItemStacksInInventory(EntityPlayer player, List blockStates) { List itemStacks = new ArrayList<>(blockStates.size()); for (IBlockState blockState : blockStates) { - itemStacks.add(InventoryHelper.findItemStackInInventory(player, blockState)); + itemStacks.add(findItemStackInInventory(player, blockState)); } return itemStacks; } + + private static ItemStack findItemStackInInventory(EntityPlayer player, IBlockState blockState) { + ItemStack itemStack = ItemStack.EMPTY; + + //First try previousBlockStates + itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock()); + + //then anything it drops + if (itemStack.isEmpty()) { + Item itemDropped = blockState.getBlock().getItemDropped(blockState, player.world.rand, 10); + if (itemDropped instanceof ItemBlock) { + Block block = ((ItemBlock) itemDropped).getBlock(); + itemStack = InventoryHelper.findItemStackInInventory(player, block); + } + } + + //then air + //(already empty) + + return itemStack; + } } diff --git a/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java b/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java index af093ac..bb59b6f 100644 --- a/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java @@ -46,20 +46,28 @@ public class CompatHelper { // Get the block to be placed by this proxy. For the /dank/null, it's the slot stack // pointed to by nbt integer selectedIndex. - public static ItemStack getItemBlockFromStack(ItemStack stack) { - Item item = stack.getItem(); + public static ItemStack getItemBlockFromStack(ItemStack proxy) { + Item proxyItem = proxy.getItem(); - if (item instanceof ItemBlock) - return stack; + if (proxyItem instanceof ItemBlock) + return proxy; - if (item instanceof ItemRandomizerBag) - return ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(stack)); + //Randomizer Bag + if (proxyItem instanceof ItemRandomizerBag) { + ItemStack itemStack = proxy; + while (!(itemStack.getItem() instanceof ItemBlock || itemStack.isEmpty())) { + if (itemStack.getItem() instanceof ItemRandomizerBag) + itemStack = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack)); + } + return itemStack; + } - if(item == dankNullItem) { + //Dank Null + if(proxyItem == dankNullItem) { int index = 0; - if(stack.hasTagCompound() && stack.getTagCompound().hasKey("selectedIndex")) - index = stack.getTagCompound().getInteger("selectedIndex"); - return stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index); + if(proxy.hasTagCompound() && proxy.getTagCompound().hasKey("selectedIndex")) + index = proxy.getTagCompound().getInteger("selectedIndex"); + return proxy.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index); } return ItemStack.EMPTY; diff --git a/src/main/java/nl/requios/effortlessbuilding/gui/RandomizerBagContainer.java b/src/main/java/nl/requios/effortlessbuilding/gui/RandomizerBagContainer.java index 7dec5ae..cbb5859 100644 --- a/src/main/java/nl/requios/effortlessbuilding/gui/RandomizerBagContainer.java +++ b/src/main/java/nl/requios/effortlessbuilding/gui/RandomizerBagContainer.java @@ -109,11 +109,10 @@ public class RandomizerBagContainer extends Container { @Override public ItemStack slotClick(int slot, int dragType, ClickType clickTypeIn, EntityPlayer player) { // this will prevent the player from interacting with the item that opened the inventory: - ItemStack clickItemStack = super.slotClick(slot, dragType, clickTypeIn, player); - if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getStack() == player.getHeldItem(EnumHand.MAIN_HAND)) { + if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getStack().equals(player.getHeldItem(EnumHand.MAIN_HAND))) { return ItemStack.EMPTY; } - return clickItemStack; + return super.slotClick(slot, dragType, clickTypeIn, player); } /** diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/InventoryHelper.java b/src/main/java/nl/requios/effortlessbuilding/helper/InventoryHelper.java index 4471647..35eb686 100644 --- a/src/main/java/nl/requios/effortlessbuilding/helper/InventoryHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/helper/InventoryHelper.java @@ -1,5 +1,6 @@ package nl.requios.effortlessbuilding.helper; +import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemBlock; @@ -7,21 +8,21 @@ import net.minecraft.item.ItemStack; public class InventoryHelper { - public static ItemStack findItemStackInInventory(EntityPlayer player, IBlockState blockState) { + public static ItemStack findItemStackInInventory(EntityPlayer player, Block block) { for (ItemStack invStack : player.inventory.mainInventory) { if (!invStack.isEmpty() && invStack.getItem() instanceof ItemBlock && - ((ItemBlock) invStack.getItem()).getBlock().equals(blockState.getBlock())) { + ((ItemBlock) invStack.getItem()).getBlock().equals(block)) { return invStack; } } return ItemStack.EMPTY; } - public static int findTotalBlocksInInventory(EntityPlayer player, IBlockState blockState) { + public static int findTotalBlocksInInventory(EntityPlayer player, Block block) { int total = 0; for (ItemStack invStack : player.inventory.mainInventory) { if (!invStack.isEmpty() && invStack.getItem() instanceof ItemBlock && - ((ItemBlock) invStack.getItem()).getBlock().equals(blockState.getBlock())) { + ((ItemBlock) invStack.getItem()).getBlock().equals(block)) { total += invStack.getCount(); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java b/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java index d64fca8..717c6d7 100644 --- a/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java @@ -7,17 +7,12 @@ import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; -import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; -import net.minecraft.init.Enchantments; -import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemSlab; import net.minecraft.item.ItemStack; -import net.minecraft.stats.StatList; -import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.SoundCategory; @@ -26,17 +21,11 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.items.ItemHandlerHelper; -import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.compatibility.CompatHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; public class SurvivalHelper { @@ -44,10 +33,17 @@ public class SurvivalHelper { //Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack. //Based on ItemBlock#onItemUse public static boolean placeBlock(World world, EntityPlayer player, BlockPos pos, IBlockState blockState, - ItemStack origstack, EnumFacing facing, Vec3d hitVec, boolean skipCollisionCheck, boolean playSound) { + ItemStack origstack, EnumFacing facing, Vec3d hitVec, boolean skipPlaceCheck, + boolean skipCollisionCheck, boolean playSound) { if (!world.isBlockLoaded(pos, true)) return false; ItemStack itemstack = origstack; + if (blockState.getBlock().isAir(blockState, world, pos) || itemstack.isEmpty()) { + dropBlock(world, player, pos); + world.setBlockToAir(pos); + return true; + } + //Randomizer bag, other proxy item synergy //Preliminary compatibility code for other items that hold blocks if (CompatHelper.isItemBlockProxy(itemstack)) @@ -59,7 +55,7 @@ public class SurvivalHelper { //More manual with ItemBlock#placeBlockAt - if (canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) { + if (skipPlaceCheck || canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) { //Drop existing block dropBlock(world, player, pos); @@ -108,13 +104,12 @@ public class SurvivalHelper { //Used for all breaking of blocks in this mod. //Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory - public static boolean breakBlock(World world, EntityPlayer player, BlockPos pos) { + public static boolean breakBlock(World world, EntityPlayer player, BlockPos pos, boolean skipChecks) { if (!world.isBlockLoaded(pos, false)) return false; //Check if can break - if (canBreak(world, player, pos)) - { -// player.addStat(StatList.getBlockStats(world.getBlockState(pos).getBlock())); + if (skipChecks || canBreak(world, player, pos)) { +// player.addStat(StatList.getBlockStats(world.getNewBlockState(pos).getBlock())); // player.addExhaustion(0.005F); //Drop existing block diff --git a/src/main/java/nl/requios/effortlessbuilding/item/ItemRandomizerBag.java b/src/main/java/nl/requios/effortlessbuilding/item/ItemRandomizerBag.java index 03357c1..ae83076 100644 --- a/src/main/java/nl/requios/effortlessbuilding/item/ItemRandomizerBag.java +++ b/src/main/java/nl/requios/effortlessbuilding/item/ItemRandomizerBag.java @@ -73,7 +73,7 @@ public class ItemRandomizerBag extends Item { IBlockState blockState = Block.getBlockFromItem(toPlace.getItem()).getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, toPlace.getMetadata(), player, hand); - SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, new Vec3d(hitX, hitY, hitZ), false, true); + SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, new Vec3d(hitX, hitY, hitZ), false, false, true); //Synergy //Works without calling diff --git a/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java index 223fe2d..372d11f 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java @@ -3,7 +3,6 @@ package nl.requios.effortlessbuilding.network; import io.netty.buffer.ByteBuf; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -24,24 +23,31 @@ import java.util.ArrayList; */ public class RequestLookAtMessage implements IMessage { private BlockPos coordinate; - private IBlockState blockState; + private IBlockState previousBlockState; + private IBlockState newBlockState; public RequestLookAtMessage() { coordinate = BlockPos.ORIGIN; - blockState = null; + previousBlockState = null; + newBlockState = null; } - public RequestLookAtMessage(BlockPos coordinate, IBlockState blockState) { + public RequestLookAtMessage(BlockPos coordinate, IBlockState previousBlockState, IBlockState newBlockState) { this.coordinate = coordinate; - this.blockState = blockState; + this.previousBlockState = previousBlockState; + this.newBlockState = newBlockState; } public BlockPos getCoordinate() { return coordinate; } - public IBlockState getBlockState() { - return blockState; + public IBlockState getPreviousBlockState() { + return previousBlockState; + } + + public IBlockState getNewBlockState() { + return newBlockState; } @Override @@ -49,13 +55,15 @@ public class RequestLookAtMessage implements IMessage { buf.writeInt(this.coordinate.getX()); buf.writeInt(this.coordinate.getY()); buf.writeInt(this.coordinate.getZ()); - buf.writeInt(Block.getStateId(this.blockState)); + buf.writeInt(Block.getStateId(this.previousBlockState)); + buf.writeInt(Block.getStateId(this.newBlockState)); } @Override public void fromBytes(ByteBuf buf) { coordinate = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); - blockState = Block.getStateById(buf.readInt()); + previousBlockState = Block.getStateById(buf.readInt()); + newBlockState = Block.getStateById(buf.readInt()); } // The params of the IMessageHandler are @@ -76,7 +84,8 @@ public class RequestLookAtMessage implements IMessage { //Add to undo stack clientside UndoRedo.addUndo(player, new BlockSet( new ArrayList() {{add(message.getCoordinate());}}, - new ArrayList() {{add(message.getBlockState());}}, + new ArrayList() {{add(message.getPreviousBlockState());}}, + new ArrayList() {{add(message.getNewBlockState());}}, new Vec3d(0,0,0), message.getCoordinate(), message.getCoordinate())); }); diff --git a/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java b/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java index 6177a34..95ae1fc 100644 --- a/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java +++ b/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java @@ -226,6 +226,7 @@ public class ClientProxy implements IProxy { ItemStack currentItemStack = player.getHeldItem(EnumHand.MAIN_HAND); if (currentItemStack.getItem() instanceof ItemBlock || (CompatHelper.isItemBlockProxy(currentItemStack) && !player.isSneaking())) { + ItemStack itemStack = CompatHelper.getItemBlockFromStack(currentItemStack); //find position in distance @@ -235,7 +236,8 @@ public class ClientProxy implements IProxy { //play sound if further than normal if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK && - (lookingAt.hitVec.subtract(player.getPositionEyes(1f))).lengthSquared() > 25f) { + (lookingAt.hitVec.subtract(player.getPositionEyes(1f))).lengthSquared() > 25f && + itemStack.getItem() instanceof ItemBlock) { IBlockState state = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState(); BlockPos blockPos = lookingAt.getBlockPos(); diff --git a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java index ad6233e..d7b1819 100644 --- a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java +++ b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java @@ -304,7 +304,7 @@ public class BlockPreviewRenderer { //Check if can place //If check is turned off, check if blockstate is the same (for dissolve effect) - if ((!checkCanPlace /*&& player.world.getBlockState(blockPos) == blockState*/) || //TODO enable (breaks breaking shader) + if ((!checkCanPlace /*&& player.world.getNewBlockState(blockPos) == blockState*/) || //TODO enable (breaks breaking shader) SurvivalHelper.canPlace(player.world, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), EnumFacing.UP)) { ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve, diff --git a/src/main/resources/assets/effortlessbuilding/lang/en_us.lang b/src/main/resources/assets/effortlessbuilding/lang/en_us.lang index 46ff8a1..0617f1d 100644 --- a/src/main/resources/assets/effortlessbuilding/lang/en_us.lang +++ b/src/main/resources/assets/effortlessbuilding/lang/en_us.lang @@ -16,10 +16,10 @@ effortlessbuilding.mode.normal_plus=Normal+ effortlessbuilding.mode.line=Line effortlessbuilding.mode.wall=Wall effortlessbuilding.mode.floor=Floor -effortlessbuilding.mode.diagonal_line=Diagonal Line (WIP) -effortlessbuilding.mode.diagonal_wall=Diagonal Wall (WIP) -effortlessbuilding.mode.slope_floor=Slope Floor (WIP) -effortlessbuilding.mode.cube=Cube (WIP) +effortlessbuilding.mode.diagonal_line=Diagonal Line +effortlessbuilding.mode.diagonal_wall=Diagonal Wall +effortlessbuilding.mode.slope_floor=Slope Floor +effortlessbuilding.mode.cube=Cube effortlessbuilding.action.undo=Undo effortlessbuilding.action.redo=Redo diff --git a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag index 7f86883..7377da6 100644 --- a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag +++ b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag @@ -102,5 +102,5 @@ void main() { if (maskgs * 0.3 + place * 0.7 <= dissolve) gl_FragColor = vec4(texcolor.rgb, 0.0); - else gl_FragColor = vec4(color.rgb, 0.85); + else gl_FragColor = color; } \ No newline at end of file