From 009f385054b7fc1e88d09ae1a4a9eb947565c5be Mon Sep 17 00:00:00 2001 From: Christian Knaapen Date: Fri, 8 Feb 2019 03:26:41 +0100 Subject: [PATCH] Added shader on placement. Added sound on drag (block placement sound). Added line. Highlight currently selected in radial menu (with colors). Fixed scaling of icons. Refactored RenderHandler into 3 classes and SurvivalHelper. Added classes and icons for diagonal line, diagonal wall, slope floor and cube. --- .../effortlessbuilding/BuildConfig.java | 3 + .../EffortlessBuilding.java | 15 + .../effortlessbuilding/EventHandler.java | 10 +- .../buildmode/BuildModes.java | 14 +- .../effortlessbuilding/buildmode/Cube.java | 36 ++ .../buildmode/DiagonalLine.java | 36 ++ .../buildmode/DiagonalWall.java | 36 ++ .../effortlessbuilding/buildmode/Floor.java | 2 +- .../effortlessbuilding/buildmode/Line.java | 188 +++++- .../buildmode/SlopeFloor.java | 36 ++ .../effortlessbuilding/buildmode/Wall.java | 17 +- .../buildmodifier/BuildModifiers.java | 9 +- .../gui/buildmode/RadialMenu.java | 387 ++++++------- .../helper/RenderHelper.java | 544 ------------------ .../helper/SurvivalHelper.java | 184 +++--- .../network/BlockBrokenMessage.java | 3 + .../network/BlockPlacedMessage.java | 12 +- .../network/CancelModeMessage.java | 3 + .../network/ModeSettingsMessage.java | 5 +- .../network/ModifierSettingsMessage.java | 3 + .../network/RequestLookAtMessage.java | 50 ++ .../effortlessbuilding/proxy/ClientProxy.java | 78 +-- .../render/BlockPreviewRenderer.java | 285 +++++++++ .../render/ModifierRenderer.java | 175 ++++++ .../render/RenderHandler.java | 213 +++++++ .../ShaderHandler.java} | 11 +- .../assets/effortlessbuilding/lang/en_us.lang | 4 +- .../effortlessbuilding/shaders/dissolve.frag | 41 +- .../effortlessbuilding/shaders/dissolve.vert | 4 +- .../assets/effortlessbuilding/sounds.json | 11 + .../effortlessbuilding/sounds/build_click.ogg | Bin 0 -> 4372 bytes .../textures/icons/cube.png | Bin 0 -> 319 bytes .../textures/icons/diagonalline.png | Bin 0 -> 370 bytes .../textures/icons/diagonalwall.png | Bin 0 -> 264 bytes .../textures/icons/floor.png | Bin 288 -> 331 bytes .../textures/icons/line.png | Bin 227 -> 246 bytes .../textures/icons/normal.png | Bin 292 -> 317 bytes .../textures/icons/normalplus.png | Bin 259 -> 355 bytes .../textures/icons/slopefloor.png | Bin 0 -> 310 bytes .../textures/icons/wall.png | Bin 296 -> 309 bytes 40 files changed, 1440 insertions(+), 975 deletions(-) create mode 100644 src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java create mode 100644 src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java create mode 100644 src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java create mode 100644 src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java delete mode 100644 src/main/java/nl/requios/effortlessbuilding/helper/RenderHelper.java create mode 100644 src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java create mode 100644 src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java create mode 100644 src/main/java/nl/requios/effortlessbuilding/render/ModifierRenderer.java create mode 100644 src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java rename src/main/java/nl/requios/effortlessbuilding/{helper/ShaderHelper.java => render/ShaderHandler.java} (94%) create mode 100644 src/main/resources/assets/effortlessbuilding/sounds.json create mode 100644 src/main/resources/assets/effortlessbuilding/sounds/build_click.ogg create mode 100644 src/main/resources/assets/effortlessbuilding/textures/icons/cube.png create mode 100644 src/main/resources/assets/effortlessbuilding/textures/icons/diagonalline.png create mode 100644 src/main/resources/assets/effortlessbuilding/textures/icons/diagonalwall.png create mode 100644 src/main/resources/assets/effortlessbuilding/textures/icons/slopefloor.png diff --git a/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java b/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java index a02c859..5ea8858 100644 --- a/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java +++ b/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java @@ -60,5 +60,8 @@ public class BuildConfig { @Comment({"Use fancy shaders while placing blocks"}) public boolean useShaders = true; + + @Comment({"How long the dissolve effect takes when placing blocks, in ticks."}) + public int dissolveTime = 60; } } diff --git a/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java b/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java index c6abd20..2231202 100644 --- a/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java +++ b/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java @@ -3,6 +3,8 @@ package nl.requios.effortlessbuilding; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; import net.minecraft.util.text.TextComponentString; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.config.Config; @@ -55,6 +57,8 @@ public class EffortlessBuilding public static final ItemReachUpgrade2 ITEM_REACH_UPGRADE_2 = new ItemReachUpgrade2(); public static final ItemReachUpgrade3 ITEM_REACH_UPGRADE_3 = new ItemReachUpgrade3(); + public static final SoundEvent SOUND_BUILD_CLICK = createSoundEvent("build_click"); + public static final Block[] BLOCKS = { }; @@ -65,6 +69,10 @@ public class EffortlessBuilding ITEM_REACH_UPGRADE_3 }; + public static final SoundEvent[] SOUND_EVENTS = { + SOUND_BUILD_CLICK + }; + public static final int RANDOMIZER_BAG_GUI = 0; @EventHandler @@ -89,6 +97,8 @@ public class EffortlessBuilding EffortlessBuilding.packetHandler.registerMessage(CancelModeMessage.MessageHandler.class, CancelModeMessage.class, 4, Side.SERVER); + EffortlessBuilding.packetHandler.registerMessage(RequestLookAtMessage.MessageHandler.class, RequestLookAtMessage.class, 5, Side.CLIENT); + proxy.preInit(event); } @@ -128,4 +138,9 @@ public class EffortlessBuilding public static void log(EntityPlayer player, String msg, boolean actionBar){ player.sendStatusMessage(new TextComponentString(msg), actionBar); } + + private static SoundEvent createSoundEvent(String soundName) { + final ResourceLocation soundID = new ResourceLocation(EffortlessBuilding.MODID, soundName); + return new SoundEvent(soundID).setRegistryName(soundID); + } } diff --git a/src/main/java/nl/requios/effortlessbuilding/EventHandler.java b/src/main/java/nl/requios/effortlessbuilding/EventHandler.java index dcdce43..055bdc5 100644 --- a/src/main/java/nl/requios/effortlessbuilding/EventHandler.java +++ b/src/main/java/nl/requios/effortlessbuilding/EventHandler.java @@ -8,6 +8,7 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.config.Config; @@ -26,6 +27,7 @@ import nl.requios.effortlessbuilding.capability.ModeCapabilityManager; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.network.BlockPlacedMessage; +import nl.requios.effortlessbuilding.network.RequestLookAtMessage; import java.util.List; @@ -50,6 +52,12 @@ public class EventHandler } } + @SubscribeEvent + public static void registerSounds(RegistryEvent.Register event) { + EffortlessBuilding.log("testing"); + event.getRegistry().registerAll(EffortlessBuilding.SOUND_EVENTS); + } + @SubscribeEvent public static void attachCapabilities(AttachCapabilitiesEvent event) { if (event.getObject() instanceof EntityPlayer) { @@ -81,7 +89,7 @@ public class EventHandler event.setCanceled(true); } else { //Send message to client, which sends message back with raytrace info - EffortlessBuilding.packetHandler.sendTo(new BlockPlacedMessage(), (EntityPlayerMP) event.getPlayer()); + EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(), (EntityPlayerMP) event.getPlayer()); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java index dbb063b..bcd306c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java @@ -24,16 +24,10 @@ public class BuildModes { Line ("Line", new Line()), Wall ("Wall", new Wall()), Floor ("Floor", new Floor()), - Normal2 ("Normal", new Normal()), - NormalPlus2 ("Normal+", new NormalPlus()), - Line2 ("Line", new Line()), - Wall2 ("Wall", new Wall()), - Floor2 ("Floor", new Floor()) - ; -// DiagonalLine, -// DiagonalWall, -// SlopedFloor, -// Cube; + DiagonalLine ("Diagonal Line", new DiagonalLine()), + DiagonalWall ("Diagonal Wall", new DiagonalWall()), + SlopeFloor ("Slope Floor", new SlopeFloor()), + Cube ("Cube", new Cube()); public String name; public final IBuildMode instance; diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java new file mode 100644 index 0000000..0719dcc --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java @@ -0,0 +1,36 @@ +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.Vec3d; + +import java.util.ArrayList; +import java.util.List; + +public class Cube implements IBuildMode { + @Override + public void initialize(EntityPlayer player) { + + } + + @Override + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + return new ArrayList<>(); + } + + @Override + public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + return new ArrayList<>(); + } + + @Override + public EnumFacing getSideHit(EntityPlayer player) { + return null; + } + + @Override + public Vec3d getHitVec(EntityPlayer player) { + return null; + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java new file mode 100644 index 0000000..c830c83 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java @@ -0,0 +1,36 @@ +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.Vec3d; + +import java.util.ArrayList; +import java.util.List; + +public class DiagonalLine implements IBuildMode { + @Override + public void initialize(EntityPlayer player) { + + } + + @Override + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + return new ArrayList<>(); + } + + @Override + public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + return new ArrayList<>(); + } + + @Override + public EnumFacing getSideHit(EntityPlayer player) { + return null; + } + + @Override + public Vec3d getHitVec(EntityPlayer player) { + return null; + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java new file mode 100644 index 0000000..aa9f6eb --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java @@ -0,0 +1,36 @@ +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.Vec3d; + +import java.util.ArrayList; +import java.util.List; + +public class DiagonalWall implements IBuildMode { + @Override + public void initialize(EntityPlayer player) { + + } + + @Override + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + return new ArrayList<>(); + } + + @Override + public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + return new ArrayList<>(); + } + + @Override + public EnumFacing getSideHit(EntityPlayer player) { + return null; + } + + @Override + public Vec3d getHitVec(EntityPlayer player) { + return null; + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java index 584e1b1..0442966 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java @@ -79,7 +79,7 @@ public class Floor implements IBuildMode { double yDistSquared = yBound.subtract(start).lengthSquared(); - int reach = ReachHelper.getMaxReach(player); //4 times as much as normal placement reach + int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach //check if its not behind the player and its not too close and not too far boolean yValid = yBound.subtract(start).dotProduct(look) > 0 && diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java index 759eb8a..65a62aa 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java @@ -3,34 +3,208 @@ 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 net.minecraft.util.math.Vec3i; +import nl.requios.effortlessbuilding.helper.ReachHelper; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class Line implements IBuildMode { + Dictionary rightClickNrTable = new Hashtable<>(); + Dictionary firstPosTable = new Hashtable<>(); + Dictionary sideHitTable = new Hashtable<>(); + Dictionary hitVecTable = new Hashtable<>(); + @Override public void initialize(EntityPlayer player) { - + rightClickNrTable.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) { - return new ArrayList<>(); + List list = new ArrayList<>(); + + int rightClickNr = rightClickNrTable.get(player.getUniqueID()); + rightClickNr++; + rightClickNrTable.put(player.getUniqueID(), rightClickNr); + + if (rightClickNr == 1) { + //If clicking in air, reset and try again + if (blockPos == null) { + rightClickNrTable.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 { + //Second click, place wall + + list = findCoordinates(player, blockPos); + rightClickNrTable.put(player.getUniqueID(), 0); + } + + return list; } @Override public List findCoordinates(EntityPlayer player, BlockPos blockPos) { - return new ArrayList<>(); + List list = new ArrayList<>(); + int rightClickNr = rightClickNrTable.get(player.getUniqueID()); + BlockPos firstPos = firstPosTable.get(player.getUniqueID()); + + if (rightClickNr == 0) { + if (blockPos != null) + list.add(blockPos); + } else { + Vec3d look = player.getLookVec(); + Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ); + + + + //try on x axis + double x = firstPos.getX(); + + //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; + + Vec3d xBound = new Vec3d(x, y, z); + Vec3d xBoundLine = toLongestLine(xBound, firstPos); + double xDistToLine = xBoundLine.subtract(xBound).lengthSquared(); + + //distance to player + double xDistSquared = xBound.subtract(start).lengthSquared(); + + + + //try on y axis + y = firstPos.getY(); + + //then x and z are + x = (y - start.y) / look.y * look.x + start.x; + z = (y - start.y) / look.y * look.z + start.z; + + Vec3d yBound = new Vec3d(x, y, z); + Vec3d yBoundLine = toLongestLine(yBound, firstPos); + double yDistToLine = yBoundLine.subtract(yBound).lengthSquared(); + + //distance to player + double yDistSquared = yBound.subtract(start).lengthSquared(); + + + + //try on z axis + z = firstPos.getZ(); + + //then x and y are + x = (z - start.z) / look.z * look.x + start.x; + y = (z - start.z) / look.z * look.y + start.y; + + Vec3d zBound = new Vec3d(x, y, z); + Vec3d zBoundLine = toLongestLine(zBound, firstPos); + double zDistToLine = zBoundLine.subtract(zBound).lengthSquared(); + + //distance to player + double zDistSquared = zBound.subtract(start).lengthSquared(); + + + + int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach + + //check if its not behind the player and its not too close and not too far + boolean xValid = xBound.subtract(start).dotProduct(look) > 0 && + xDistSquared > 4 && xDistSquared < reach * reach; + + boolean yValid = yBound.subtract(start).dotProduct(look) > 0 && + yDistSquared > 4 && yDistSquared < reach * reach; + + boolean zValid = zBound.subtract(start).dotProduct(look) > 0 && + zDistSquared > 4 && zDistSquared < reach * reach; + + //select the one that is closest (from wall position to its line counterpart) and is valid + Vec3d selected = null; + double selectedDistToLine = 0; + + if (xValid) { + selected = xBoundLine; + selectedDistToLine = xDistToLine; + } else if (yValid) { + selected = yBoundLine; + selectedDistToLine = yDistToLine; + } else if (zValid) { + selected = zBoundLine; + selectedDistToLine = yDistToLine; + } + + if (yValid && yDistToLine < selectedDistToLine) selected = yBoundLine; + if (zValid && zDistToLine < selectedDistToLine) selected = zBoundLine; + + if (selected == null) return list; + + //TODO check if it doesnt go through blocks + RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, false, false); + if (rayTraceResult != null && rayTraceResult.typeOfHit != RayTraceResult.Type.BLOCK) { + //return empty list + return list; + } + + BlockPos secondPos = new BlockPos(selected); + + //Add whole line + + 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) { + + for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { + list.add(new BlockPos(l, m, n)); + } + } + } + } + + return list; + } + + //Make it into a line + //Select the axis that is longest + private Vec3d toLongestLine(Vec3d boundVec, BlockPos firstPos) { + BlockPos bound = new BlockPos(boundVec); + + BlockPos firstToSecond = bound.subtract(firstPos); + firstToSecond = new BlockPos(Math.abs(firstToSecond.getX()), Math.abs(firstToSecond.getY()), Math.abs(firstToSecond.getZ())); + int longest = Math.max(firstToSecond.getX(), Math.max(firstToSecond.getY(), firstToSecond.getZ())); + if (longest == firstToSecond.getX()) { + return new Vec3d(bound.getX(), firstPos.getY(), firstPos.getZ()); + } + if (longest == firstToSecond.getY()) { + return new Vec3d(firstPos.getX(), bound.getY(), firstPos.getZ()); + } + if (longest == firstToSecond.getZ()) { + return new Vec3d(firstPos.getX(), firstPos.getY(), bound.getZ()); + } + return null; } @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()); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java new file mode 100644 index 0000000..77f93e3 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java @@ -0,0 +1,36 @@ +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.Vec3d; + +import java.util.ArrayList; +import java.util.List; + +public class SlopeFloor implements IBuildMode { + @Override + public void initialize(EntityPlayer player) { + + } + + @Override + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + return new ArrayList<>(); + } + + @Override + public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + return new ArrayList<>(); + } + + @Override + public EnumFacing getSideHit(EntityPlayer player) { + return null; + } + + @Override + public Vec3d getHitVec(EntityPlayer player) { + return null; + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java index 88bc93f..62000ac 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java @@ -78,6 +78,9 @@ public class Wall implements IBuildMode { //distance to player double xDistSquared = xBound.subtract(start).lengthSquared(); + //angle to look + //double xAngle = xBound.subtract(new Vec3d(firstPos)).normalize().dotProduct(look); + //try on z axis z = firstPos.getZ(); @@ -90,7 +93,10 @@ public class Wall implements IBuildMode { //distance to player double zDistSquared = zBound.subtract(start).lengthSquared(); - int reach = ReachHelper.getMaxReach(player); //4 times as much as normal placement reach + //angle to look + //double zAngle = zBound.subtract(new Vec3d(firstPos)).normalize().dotProduct(look); + + int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach //check if its not behind the player and its not too close and not too far boolean xValid = xBound.subtract(start).dotProduct(look) > 0 && @@ -99,10 +105,13 @@ public class Wall implements IBuildMode { boolean zValid = zBound.subtract(start).dotProduct(look) > 0 && zDistSquared > 4 && zDistSquared < reach * reach; - //select the one that is closest to the player and is valid + //select the one that is closest and is valid Vec3d selected = null; - if (xValid) selected = xBound; - if (zValid && zDistSquared < xDistSquared) selected = zBound; + if (xValid) + selected = xBound; + else if (zValid) + selected = zBound; + if (zValid && zDistSquared < xDistSquared/*Math.abs(zAngle) < Math.abs(xAngle)*/) selected = zBound; if (selected == null) return list; diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java index 4fbf099..7b3811b 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java @@ -2,6 +2,7 @@ package nl.requios.effortlessbuilding.buildmodifier; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemBlock; @@ -18,6 +19,7 @@ import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.network.BlockBrokenMessage; +import nl.requios.effortlessbuilding.network.BlockPlacedMessage; import java.util.ArrayList; import java.util.Arrays; @@ -53,6 +55,9 @@ public class BuildModifiers { SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, true, false); } } + + EffortlessBuilding.packetHandler.sendTo(new BlockPlacedMessage(), ((EntityPlayerMP) player)); + } public static void onBlockBroken(EntityPlayer player, List posList) { @@ -117,13 +122,13 @@ public class BuildModifiers { ItemStack itemBlock = ItemStack.EMPTY; if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack; ItemRandomizerBag.resetRandomness(); - if (itemStack.getItem() instanceof ItemRandomizerBag) itemBlock = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack)); //Add blocks in posList first for (BlockPos blockPos : posList) { + if (itemStack.getItem() instanceof ItemRandomizerBag) itemBlock = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack)); IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND); blockStates.add(blockState); - itemStacks.add(itemStack); + itemStacks.add(itemBlock); } for (BlockPos blockPos : posList) { diff --git a/src/main/java/nl/requios/effortlessbuilding/gui/buildmode/RadialMenu.java b/src/main/java/nl/requios/effortlessbuilding/gui/buildmode/RadialMenu.java index 7fbc1c5..66e1d69 100644 --- a/src/main/java/nl/requios/effortlessbuilding/gui/buildmode/RadialMenu.java +++ b/src/main/java/nl/requios/effortlessbuilding/gui/buildmode/RadialMenu.java @@ -1,9 +1,9 @@ package nl.requios.effortlessbuilding.gui.buildmode; -import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.TimeUnit; +import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.proxy.ClientProxy; import org.lwjgl.opengl.GL11; @@ -25,8 +25,7 @@ import static nl.requios.effortlessbuilding.buildmode.BuildModes.*; * From Chisels and Bits by AlgorithmX2 * https://github.com/AlgorithmX2/Chisels-and-Bits/blob/1.12/src/main/java/mod/chiselsandbits/client/gui/ChiselsAndBitsMenu.java */ -public class RadialMenu extends GuiScreen -{ +public class RadialMenu extends GuiScreen { private final float TIME_SCALE = 0.01f; public static final RadialMenu instance = new RadialMenu(); @@ -37,41 +36,32 @@ public class RadialMenu extends GuiScreen //public ButtonAction doAction = null; public boolean actionUsed = false; - private float clampVis( - final float f ) - { + private float clampVis(final float f) { return Math.max( 0.0f, Math.min( 1.0f, f ) ); } - public void raiseVisibility() - { + public void raiseVisibility() { visibility = clampVis( visibility + lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE ); lastChange = Stopwatch.createStarted(); } - public void decreaseVisibility() - { + public void decreaseVisibility() { visibility = clampVis( visibility - lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE ); lastChange = Stopwatch.createStarted(); } - public boolean isVisible() - { + public boolean isVisible() { return visibility > 0.001; } - public void configure( - final int scaledWidth, - final int scaledHeight ) - { + public void configure(final int scaledWidth, final int scaledHeight ) { mc = Minecraft.getMinecraft(); fontRenderer = mc.fontRenderer; width = scaledWidth; height = scaledHeight; } - private static class MenuButton - { + private static class MenuButton { public double x1, x2; public double y1, y2; @@ -83,14 +73,8 @@ public class RadialMenu extends GuiScreen public String name; public EnumFacing textSide; - public MenuButton( - final String name, - //final ButtonAction action, - final double x, - final double y, - final TextureAtlasSprite ico, - final EnumFacing textSide ) - { + public MenuButton(final String name, /*final ButtonAction action,*/ final double x, final double y, + final TextureAtlasSprite ico, final EnumFacing textSide) { this.name = name; //this.action = action; x1 = x; @@ -102,14 +86,8 @@ public class RadialMenu extends GuiScreen this.textSide = textSide; } - public MenuButton( - final String name, - //final ButtonAction action, - final double x, - final double y, - final int col, - final EnumFacing textSide ) - { + public MenuButton(final String name, /*final ButtonAction action,*/ final double x, final double y, + final int col, final EnumFacing textSide) { this.name = name; //this.action = action; x1 = x; @@ -122,38 +100,21 @@ public class RadialMenu extends GuiScreen } - static class MenuRegion - { + static class MenuRegion { public final BuildModeEnum mode; public double x1, x2; public double y1, y2; public boolean highlighted; - public MenuRegion( - final BuildModeEnum mode ) - { + public MenuRegion(final BuildModeEnum mode) { this.mode = mode; } } - public static class SpriteIconPositioning - { - public TextureAtlasSprite sprite; - - public double left; - public double top; - public double width; - public double height; - } - @Override - public void drawScreen( - final int mouseX, - final int mouseY, - final float partialTicks ) - { + public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { //TODO chisels compat // final ChiselToolType tool = ClientSide.instance.getHeldToolType( EnumHand.MAIN_HAND ); // @@ -165,172 +126,173 @@ public class RadialMenu extends GuiScreen GlStateManager.pushMatrix(); GlStateManager.translate( 0.0F, 0.0F, 200.0F ); - final int start = (int) ( visibility * 98 ) << 24; - final int end = (int) ( visibility * 128 ) << 24; + final int startColor = (int) ( visibility * 98 ) << 24; + final int endColor = (int) ( visibility * 128 ) << 24; - drawGradientRect( 0, 0, width, height, start, end ); + drawGradientRect(0, 0, width, height, startColor, endColor); GlStateManager.disableTexture2D(); GlStateManager.enableBlend(); GlStateManager.disableAlpha(); - GlStateManager.tryBlendFuncSeparate( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0 ); - GlStateManager.shadeModel( GL11.GL_SMOOTH ); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); + GlStateManager.shadeModel(GL11.GL_SMOOTH); final Tessellator tessellator = Tessellator.getInstance(); final BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR ); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); - final double vecX = mouseX - width / 2; - final double vecY = mouseY - height / 2; - double radians = Math.atan2( vecY, vecX ); + final double middleX = width / 2.0; + final double middleY = height / 2.0; - final double ring_inner_edge = 20; - final double ring_outer_edge = 50; - final double text_distnace = 65; + final double mouseXCenter = mouseX - middleX; + final double mouseYCenter = mouseY - middleY; + double mouseRadians = Math.atan2(mouseYCenter, mouseXCenter); + + final double ringInnerEdge = 20; + final double ringOuterEdge = 50; + final double textDistance = 65; final double quarterCircle = Math.PI / 2.0; - if ( radians < -quarterCircle ) - { - radians = radians + Math.PI * 2; + if ( mouseRadians < -quarterCircle ) { + mouseRadians = mouseRadians + Math.PI * 2; } - final double middle_x = width / 2; - final double middle_y = height / 2; - final ArrayList modes = new ArrayList(); - final ArrayList btns = new ArrayList(); + final ArrayList buttons = new ArrayList(); -// btns.add( new MenuButton( "mod.chiselsandbits.other.undo", ButtonAction.UNDO, text_distnace, -20, ClientSide.undoIcon, EnumFacing.EAST ) ); -// btns.add( new MenuButton( "mod.chiselsandbits.other.redo", ButtonAction.REDO, text_distnace, 4, ClientSide.redoIcon, EnumFacing.EAST ) ); +// buttons.add( new MenuButton( "mod.chiselsandbits.other.undo", ButtonAction.UNDO, textDistance, -20, ClientSide.undoIcon, EnumFacing.EAST ) ); +// buttons.add( new MenuButton( "mod.chiselsandbits.other.redo", ButtonAction.REDO, textDistance, 4, ClientSide.redoIcon, EnumFacing.EAST ) ); - for ( final BuildModeEnum mode : BuildModeEnum.values() ) - { - modes.add( new MenuRegion( mode ) ); + for (final BuildModeEnum mode : BuildModeEnum.values()) { + modes.add(new MenuRegion(mode)); } switchTo = null; //doAction = null; - if ( !modes.isEmpty() ) - { + if (!modes.isEmpty()) { final int totalModes = Math.max( 3, modes.size() ); int currentMode = 0; final double fragment = Math.PI * 0.005; final double fragment2 = Math.PI * 0.0025; final double perObject = 2.0 * Math.PI / totalModes; - for ( final MenuRegion mnuRgn : modes ) - { - final double begin_rad = currentMode * perObject - quarterCircle; - final double end_rad = ( currentMode + 1 ) * perObject - quarterCircle; + for (int i = 0; i < modes.size(); i++) { + MenuRegion menuRegion = modes.get(i); + final double beginRadians = currentMode * perObject - quarterCircle; + final double endRadians = (currentMode + 1) * perObject - quarterCircle; - mnuRgn.x1 = Math.cos( begin_rad ); - mnuRgn.x2 = Math.cos( end_rad ); - mnuRgn.y1 = Math.sin( begin_rad ); - mnuRgn.y2 = Math.sin( end_rad ); + menuRegion.x1 = Math.cos(beginRadians); + menuRegion.x2 = Math.cos(endRadians); + menuRegion.y1 = Math.sin(beginRadians); + menuRegion.y2 = Math.sin(endRadians); - final double x1m1 = Math.cos( begin_rad + fragment ) * ring_inner_edge; - final double x2m1 = Math.cos( end_rad - fragment ) * ring_inner_edge; - final double y1m1 = Math.sin( begin_rad + fragment ) * ring_inner_edge; - final double y2m1 = Math.sin( end_rad - fragment ) * ring_inner_edge; + final double x1m1 = Math.cos(beginRadians + fragment) * ringInnerEdge; + final double x2m1 = Math.cos(endRadians - fragment) * ringInnerEdge; + final double y1m1 = Math.sin(beginRadians + fragment) * ringInnerEdge; + final double y2m1 = Math.sin(endRadians - fragment) * ringInnerEdge; - final double x1m2 = Math.cos( begin_rad + fragment2 ) * ring_outer_edge; - final double x2m2 = Math.cos( end_rad - fragment2 ) * ring_outer_edge; - final double y1m2 = Math.sin( begin_rad + fragment2 ) * ring_outer_edge; - final double y2m2 = Math.sin( end_rad - fragment2 ) * ring_outer_edge; + final double x1m2 = Math.cos(beginRadians + fragment2) * ringOuterEdge; + final double x2m2 = Math.cos(endRadians - fragment2) * ringOuterEdge; + final double y1m2 = Math.sin(beginRadians + fragment2) * ringOuterEdge; + final double y2m2 = Math.sin(endRadians - fragment2) * ringOuterEdge; - final float a = 0.5f; - float f = 0f; + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + float a = 0.5f; - final boolean quad = inTriangle( - x1m1, y1m1, - x2m2, y2m2, - x2m1, y2m1, - vecX, vecY ) || inTriangle( - x1m1, y1m1, - x1m2, y1m2, - x2m2, y2m2, - vecX, vecY ); - - if ( begin_rad <= radians && radians <= end_rad && quad ) - { - f = 1; - mnuRgn.highlighted = true; - switchTo = mnuRgn.mode; + //check if current mode + int buildMode = ModeSettingsManager.getModeSettings(Minecraft.getMinecraft().player).getBuildMode().ordinal(); + if (buildMode == i) { + r = 0f; + g = 0.5f; + b = 1f; + a = 0.5f; + //menuRegion.highlighted = true; //draw text } - buffer.pos( middle_x + x1m1, middle_y + y1m1, zLevel ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + x2m1, middle_y + y2m1, zLevel ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + x2m2, middle_y + y2m2, zLevel ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + x1m2, middle_y + y1m2, zLevel ).color( f, f, f, a ).endVertex(); + //check if mouse is over this region + final boolean isMouseInQuad = inTriangle(x1m1, y1m1, x2m2, y2m2, x2m1, y2m1, mouseXCenter, mouseYCenter) + || inTriangle(x1m1, y1m1, x1m2, y1m2, x2m2, y2m2, mouseXCenter, mouseYCenter); + + if (beginRadians <= mouseRadians && mouseRadians <= endRadians && isMouseInQuad) { + r = 0.6f;//0.6f; + g = 0.8f;//0.3f; + b = 1f;//0.0f; + a = 0.6f; + menuRegion.highlighted = true; + switchTo = menuRegion.mode; + } + + buffer.pos(middleX + x1m1, middleY + y1m1, zLevel).color(r, g, b, a).endVertex(); + buffer.pos(middleX + x2m1, middleY + y2m1, zLevel).color(r, g, b, a).endVertex(); + buffer.pos(middleX + x2m2, middleY + y2m2, zLevel).color(r, g, b, a).endVertex(); + buffer.pos(middleX + x1m2, middleY + y1m2, zLevel).color(r, g, b, a).endVertex(); currentMode++; } } - for ( final MenuButton btn : btns ) - { + for (final MenuButton btn : buttons) { final float a = 0.5f; float f = 0f; - if ( btn.x1 <= vecX && btn.x2 >= vecX && btn.y1 <= vecY && btn.y2 >= vecY ) - { + if (btn.x1 <= mouseXCenter && btn.x2 >= mouseXCenter && btn.y1 <= mouseYCenter && btn.y2 >= mouseYCenter) { f = 1; btn.highlighted = true; //doAction = btn.action; } - buffer.pos( middle_x + btn.x1, middle_y + btn.y1, zLevel ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + btn.x1, middle_y + btn.y2, zLevel ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + btn.x2, middle_y + btn.y2, zLevel ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + btn.x2, middle_y + btn.y1, zLevel ).color( f, f, f, a ).endVertex(); + buffer.pos(middleX + btn.x1, middleY + btn.y1, zLevel).color(f, f, f, a).endVertex(); + buffer.pos(middleX + btn.x1, middleY + btn.y2, zLevel).color(f, f, f, a).endVertex(); + buffer.pos(middleX + btn.x2, middleY + btn.y2, zLevel).color(f, f, f, a).endVertex(); + buffer.pos(middleX + btn.x2, middleY + btn.y1, zLevel).color(f, f, f, a).endVertex(); } tessellator.draw(); - GlStateManager.shadeModel( GL11.GL_FLAT ); + GlStateManager.shadeModel(GL11.GL_FLAT); - GlStateManager.translate( 0.0F, 0.0F, 5.0F ); + GlStateManager.translate(0f, 0f, 5f); GlStateManager.enableTexture2D(); - GlStateManager.color( 1, 1, 1, 1.0f ); + GlStateManager.color(1f, 1f, 1f, 1f); GlStateManager.disableBlend(); GlStateManager.enableAlpha(); - GlStateManager.bindTexture( Minecraft.getMinecraft().getTextureMapBlocks().getGlTextureId() ); + GlStateManager.bindTexture(Minecraft.getMinecraft().getTextureMapBlocks().getGlTextureId()); - buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR ); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR); - for ( final MenuRegion mnuRgn : modes ) - { - final double x = ( mnuRgn.x1 + mnuRgn.x2 ) * 0.5 * ( ring_outer_edge * 0.6 + 0.4 * ring_inner_edge ); - final double y = ( mnuRgn.y1 + mnuRgn.y2 ) * 0.5 * ( ring_outer_edge * 0.6 + 0.4 * ring_inner_edge ); + for (final MenuRegion mnuRgn : modes) { - final SpriteIconPositioning sip = ClientProxy.getBuildModeIcon(mnuRgn.mode); + final double x = (mnuRgn.x1 + mnuRgn.x2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge); + final double y = (mnuRgn.y1 + mnuRgn.y2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge); - final double scalex = 15 * sip.width * 0.5; - final double scaley = 15 * sip.height * 0.5; + final TextureAtlasSprite sprite = ClientProxy.getBuildModeIcon(mnuRgn.mode); + + final double scalex = 16 * 0.5; + final double scaley = 16 * 0.5; final double x1 = x - scalex; final double x2 = x + scalex; final double y1 = y - scaley; final double y2 = y + scaley; - final TextureAtlasSprite sprite = sip.sprite; + final float f = 1f; + final float a = 1f; - final float f = 1.0f; - final float a = 1.0f; + final double u1 = 0f; + final double u2 = 16f; + final double v1 = 0f; + final double v2 = 16f; - final double u1 = sip.left * 16.0; - final double u2 = ( sip.left + sip.width ) * 16.0; - final double v1 = sip.top * 16.0; - final double v2 = ( sip.top + sip.height ) * 16.0; - - buffer.pos( middle_x + x1, middle_y + y1, zLevel ).tex( sprite.getInterpolatedU( u1 ), sprite.getInterpolatedV( v1 ) ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + x1, middle_y + y2, zLevel ).tex( sprite.getInterpolatedU( u1 ), sprite.getInterpolatedV( v2 ) ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + x2, middle_y + y2, zLevel ).tex( sprite.getInterpolatedU( u2 ), sprite.getInterpolatedV( v2 ) ).color( f, f, f, a ).endVertex(); - buffer.pos( middle_x + x2, middle_y + y1, zLevel ).tex( sprite.getInterpolatedU( u2 ), sprite.getInterpolatedV( v1 ) ).color( f, f, f, a ).endVertex(); + buffer.pos(middleX + x1, middleY + y1, zLevel).tex( sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex(); + buffer.pos(middleX + x1, middleY + y2, zLevel).tex( sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex(); + buffer.pos(middleX + x2, middleY + y2, zLevel).tex( sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex(); + buffer.pos(middleX + x2, middleY + y1, zLevel).tex( sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex(); } - for ( final MenuButton btn : btns ) - { + for (final MenuButton btn : buttons) { + final float f = switchTo == null ? 1.0f : 0.5f; final float a = 1.0f; @@ -339,70 +301,69 @@ public class RadialMenu extends GuiScreen final double v1 = 0; final double v2 = 16; - final TextureAtlasSprite sprite = btn.icon == null ? Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite( ModelLoader.White.LOCATION.toString() ) : btn.icon; + final TextureAtlasSprite sprite = btn.icon == null ? Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(ModelLoader.White.LOCATION.toString()) : btn.icon; final double btnx1 = btn.x1 + 1; final double btnx2 = btn.x2 - 1; final double btny1 = btn.y1 + 1; final double btny2 = btn.y2 - 1; - final float red = f * ( ( btn.color >> 16 & 0xff ) / 255.0f ); - final float green = f * ( ( btn.color >> 8 & 0xff ) / 255.0f ); - final float blue = f * ( ( btn.color & 0xff ) / 255.0f ); + final float red = f * ((btn.color >> 16 & 0xff) / 255.0f); + final float green = f * ((btn.color >> 8 & 0xff) / 255.0f); + final float blue = f * ((btn.color & 0xff) / 255.0f); - buffer.pos( middle_x + btnx1, middle_y + btny1, zLevel ).tex( sprite.getInterpolatedU( u1 ), sprite.getInterpolatedV( v1 ) ).color( red, green, blue, a ).endVertex(); - buffer.pos( middle_x + btnx1, middle_y + btny2, zLevel ).tex( sprite.getInterpolatedU( u1 ), sprite.getInterpolatedV( v2 ) ).color( red, green, blue, a ).endVertex(); - buffer.pos( middle_x + btnx2, middle_y + btny2, zLevel ).tex( sprite.getInterpolatedU( u2 ), sprite.getInterpolatedV( v2 ) ).color( red, green, blue, a ).endVertex(); - buffer.pos( middle_x + btnx2, middle_y + btny1, zLevel ).tex( sprite.getInterpolatedU( u2 ), sprite.getInterpolatedV( v1 ) ).color( red, green, blue, a ).endVertex(); + buffer.pos(middleX + btnx1, middleY + btny1, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(red, green, blue, a).endVertex(); + buffer.pos(middleX + btnx1, middleY + btny2, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(red, green, blue, a).endVertex(); + buffer.pos(middleX + btnx2, middleY + btny2, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(red, green, blue, a).endVertex(); + buffer.pos(middleX + btnx2, middleY + btny1, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(red, green, blue, a).endVertex(); } tessellator.draw(); - for ( final MenuRegion mnuRgn : modes ) - { - if ( mnuRgn.highlighted ) - { - final double x = ( mnuRgn.x1 + mnuRgn.x2 ) * 0.5; - final double y = ( mnuRgn.y1 + mnuRgn.y2 ) * 0.5; + for (final MenuRegion mnuRgn : modes) { - int fixed_x = (int) ( x * text_distnace ); - final int fixed_y = (int) ( y * text_distnace ); + if (mnuRgn.highlighted) { + final double x = (mnuRgn.x1 + mnuRgn.x2) * 0.5; + final double y = (mnuRgn.y1 + mnuRgn.y2) * 0.5; + + int fixed_x = (int) (x * textDistance); + final int fixed_y = (int) (y * textDistance); final String text = mnuRgn.mode.name; - if ( x <= -0.2 ) - { - fixed_x -= fontRenderer.getStringWidth( text ); - } - else if ( -0.2 <= x && x <= 0.2 ) - { - fixed_x -= fontRenderer.getStringWidth( text ) / 2; + if ( x <= -0.2 ) { + fixed_x -= fontRenderer.getStringWidth(text); + } else if ( -0.2 <= x && x <= 0.2 ) { + fixed_x -= fontRenderer.getStringWidth(text) / 2; } - fontRenderer.drawStringWithShadow( text, (int) middle_x + fixed_x, (int) middle_y + fixed_y, 0xffffffff ); + fontRenderer.drawStringWithShadow(text, (int) middleX + fixed_x, (int) middleY + fixed_y, 0xffffffff); } } - for ( final MenuButton btn : btns ) - { - if ( btn.highlighted ) - { + for (final MenuButton btn : buttons) { + if (btn.highlighted) { final String text = btn.name; - if ( btn.textSide == EnumFacing.WEST ) - { - fontRenderer.drawStringWithShadow( text, (int) ( middle_x + btn.x1 - 8 ) - fontRenderer.getStringWidth( text ), (int) ( middle_y + btn.y1 + 6 ), 0xffffffff ); - } - else if ( btn.textSide == EnumFacing.EAST ) - { - fontRenderer.drawStringWithShadow( text, (int) ( middle_x + btn.x2 + 8 ), (int) ( middle_y + btn.y1 + 6 ), 0xffffffff ); - } - else if ( btn.textSide == EnumFacing.UP ) - { - fontRenderer.drawStringWithShadow( text, (int) ( middle_x + ( btn.x1 + btn.x2 ) * 0.5 - fontRenderer.getStringWidth( text ) * 0.5 ), (int) ( middle_y + btn.y1 - 14 ), 0xffffffff ); - } - else if ( btn.textSide == EnumFacing.DOWN ) - { - fontRenderer.drawStringWithShadow( text, (int) ( middle_x + ( btn.x1 + btn.x2 ) * 0.5 - fontRenderer.getStringWidth( text ) * 0.5 ), (int) ( middle_y + btn.y1 + 24 ), 0xffffffff ); + if (btn.textSide == EnumFacing.WEST) { + + fontRenderer.drawStringWithShadow( text, (int) ( middleX + btn.x1 - 8 ) - fontRenderer.getStringWidth( text ), + (int) ( middleY + btn.y1 + 6 ), 0xffffffff ); + + } else if (btn.textSide == EnumFacing.EAST) { + + fontRenderer.drawStringWithShadow( text, (int) ( middleX + btn.x2 + 8 ), + (int) ( middleY + btn.y1 + 6 ), 0xffffffff ); + + } else if (btn.textSide == EnumFacing.UP) { + + fontRenderer.drawStringWithShadow( text, (int) ( middleX + ( btn.x1 + btn.x2 ) * 0.5 - fontRenderer.getStringWidth( text ) * 0.5 ), + (int) ( middleY + btn.y1 - 14 ), 0xffffffff ); + + } else if (btn.textSide == EnumFacing.DOWN) { + + fontRenderer.drawStringWithShadow( text, (int) ( middleX + ( btn.x1 + btn.x2 ) * 0.5 - fontRenderer.getStringWidth( text ) * 0.5 ), + (int) ( middleY + btn.y1 + 24 ), 0xffffffff ); + } } @@ -411,42 +372,26 @@ public class RadialMenu extends GuiScreen GlStateManager.popMatrix(); } - private boolean inTriangle( - final double x1, - final double y1, - final double x2, - final double y2, - final double x3, - final double y3, - final double x, - final double y ) - { - final double ab = ( x1 - x ) * ( y2 - y ) - ( x2 - x ) * ( y1 - y ); - final double bc = ( x2 - x ) * ( y3 - y ) - ( x3 - x ) * ( y2 - y ); - final double ca = ( x3 - x ) * ( y1 - y ) - ( x1 - x ) * ( y3 - y ); - return sign( ab ) == sign( bc ) && sign( bc ) == sign( ca ); + private boolean inTriangle(final double x1, final double y1, final double x2, final double y2, + final double x3, final double y3, final double x, final double y ) { + final double ab = (x1 - x) * (y2 - y) - (x2 - x) * (y1 - y); + final double bc = (x2 - x) * (y3 - y) - (x3 - x) * (y2 - y); + final double ca = (x3 - x) * (y1 - y) - (x1 - x) * (y3 - y); + return sign(ab) == sign(bc) && sign(bc) == sign(ca); } - private int sign( - final double n ) - { + private int sign(final double n) { return n > 0 ? 1 : -1; } /** * Called when the mouse is clicked. Args : mouseX, mouseY, clickedButton */ - protected void mouseClicked( - int mouseX, - int mouseY, - int mouseButton ) throws IOException - { - if ( mouseButton == 0 ) - { - this.mc.displayGuiScreen( (GuiScreen) null ); + protected void mouseClicked(int mouseX, int mouseY, int mouseButton ) { + if (mouseButton == 0) { + this.mc.displayGuiScreen(null); - if ( this.mc.currentScreen == null ) - { + if (this.mc.currentScreen == null) { this.mc.setIngameFocus(); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/RenderHelper.java b/src/main/java/nl/requios/effortlessbuilding/helper/RenderHelper.java deleted file mode 100644 index a4741cd..0000000 --- a/src/main/java/nl/requios/effortlessbuilding/helper/RenderHelper.java +++ /dev/null @@ -1,544 +0,0 @@ -package nl.requios.effortlessbuilding.helper; - -import net.minecraft.block.Block; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.*; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvent; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.IWorldEventListener; -import net.minecraft.world.World; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.relauncher.Side; -import nl.requios.effortlessbuilding.BuildConfig; -import nl.requios.effortlessbuilding.EffortlessBuilding; -import nl.requios.effortlessbuilding.buildmode.BuildModes; -import nl.requios.effortlessbuilding.buildmode.IBuildMode; -import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; -import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; -import nl.requios.effortlessbuilding.buildmodifier.Mirror; -import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; -import nl.requios.effortlessbuilding.buildmodifier.RadialMirror; -import nl.requios.effortlessbuilding.item.ItemRandomizerBag; -import nl.requios.effortlessbuilding.proxy.ClientProxy; -import org.lwjgl.opengl.ARBMultitexture; -import org.lwjgl.opengl.ARBShaderObjects; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL14; -import org.lwjgl.util.Color; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; - -@Mod.EventBusSubscriber(Side.CLIENT) -public class RenderHelper implements IWorldEventListener { - - private static final Color colorX = new Color(255, 72, 52); - private static final Color colorY = new Color(67, 204, 51); - private static final Color colorZ = new Color(52, 247, 255); - private static final Color colorRadial = new Color(52, 247, 255); - private static final int lineAlpha = 200; - private static final int planeAlpha = 75; - private static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting - - private static List previousCoordinates; - - private static final int secondaryTextureUnit = 7; - - private static void begin(float partialTicks) { - EntityPlayer player = Minecraft.getMinecraft().player; - double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks; - double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks; - double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks; - Vec3d playerPos = new Vec3d(playerX, playerY, playerZ); - - GL11.glPushMatrix(); - GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z); - - GL11.glDepthMask(false); - } - - private static void beginLines() { - GL11.glPushAttrib(GL11.GL_ENABLE_BIT); - GL11.glDisable(GL11.GL_CULL_FACE); - GL11.glDisable(GL11.GL_LIGHTING); - GL11.glDisable(GL11.GL_TEXTURE_2D); - - GL11.glEnable(GL11.GL_BLEND); - GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - - GL11.glLineWidth(2); - } - - private static void endLines() { - GL11.glPopAttrib(); - } - - private static void beginBlockPreviews() { - GL11.glPushAttrib(GL11.GL_ENABLE_BIT); - GL11.glEnable(GL11.GL_CULL_FACE); - GL11.glEnable(GL11.GL_TEXTURE_2D); - Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_color.png")); - Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png")); - - Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL14.glBlendColor(1F, 1F, 1F, 0.8f); - } - - private static void endBlockPreviews() { - ShaderHelper.releaseShader(); - GlStateManager.disableBlend(); - GL11.glPopAttrib(); - } - - private static void end() { - GL11.glDepthMask(true); - GL11.glPopMatrix(); - } - - private static void renderBlockPreview(BlockRendererDispatcher dispatcher, BlockPos blockPos, IBlockState blockState) { - GlStateManager.pushMatrix(); - GlStateManager.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); - GlStateManager.translate(-0.005f, -0.005f, 0.005f); - GlStateManager.scale(1.01f, 1.01f, 1.01f); - dispatcher.renderBlockBrightness(blockState, 0.85f); - GlStateManager.popMatrix(); - } - - public static void renderBlockOutline(BlockPos pos) { - renderBlockOutline(pos, pos); - } - - //Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z - public static void renderBlockOutline(BlockPos pos1, BlockPos pos2) { - GL11.glLineWidth(2); - - AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026); - - RenderGlobal.drawSelectionBoundingBox(aabb, 0f, 0f, 0f, 0.4f); - } - - @SubscribeEvent - public static void onRender(RenderWorldLastEvent event) { - EntityPlayer player = Minecraft.getMinecraft().player; - ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); - ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); - - begin(event.getPartialTicks()); - - beginLines(); - //Mirror lines and areas - Mirror.MirrorSettings m = modifierSettings.getMirrorSettings(); - if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ)) - { - Vec3d pos = m.position.add(epsilon); - int radius = m.radius; - - if (m.mirrorX) - { - Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius); - Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius); - - drawMirrorPlane(posA, posB, colorX, m.drawLines, m.drawPlanes, true); - } - if (m.mirrorY) - { - Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius); - Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius); - - drawMirrorPlaneY(posA, posB, colorY, m.drawLines, m.drawPlanes); - } - if (m.mirrorZ) - { - Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z); - Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z); - - drawMirrorPlane(posA, posB, colorZ, m.drawLines, m.drawPlanes, true); - } - - //Draw axis coordinated colors if two or more axes are enabled - //(If only one is enabled the lines are that planes color) - if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ))) - { - drawMirrorLines(m); - } - } - - //Radial mirror lines and areas - RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings(); - if (r != null && r.enabled) - { - Vec3d pos = r.position.add(epsilon); - int radius = r.radius; - - float angle = 2f * ((float) Math.PI) / r.slices; - Vec3d relStartVec = new Vec3d(radius, 0, 0); - if (r.slices%4 == 2) relStartVec = relStartVec.rotateYaw(angle / 2f); - - for (int i = 0; i < r.slices; i++) { - Vec3d relNewVec = relStartVec.rotateYaw(angle * i); - Vec3d newVec = pos.add(relNewVec); - - Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z); - Vec3d posB = new Vec3d(newVec.x, pos.y + radius, newVec.z); - drawMirrorPlane(posA, posB, colorRadial, r.drawLines, r.drawPlanes, false); - } - } - endLines(); - - //Render block previews - RayTraceResult lookingAt = ClientProxy.getLookingAt(player); - if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.Normal) lookingAt = Minecraft.getMinecraft().objectMouseOver; - - ItemStack mainhand = player.getHeldItemMainhand(); - boolean toolInHand = !(!mainhand.isEmpty() && (mainhand.getItem() instanceof ItemBlock || mainhand.getItem() instanceof ItemRandomizerBag)); - - BlockPos startPos = null; - EnumFacing sideHit = null; - Vec3d hitVec = null; - - //Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS) - if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) { - startPos = lookingAt.getBlockPos(); - - //Check if tool (or none) in hand - boolean replaceable = player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos); - if (!modifierSettings.doQuickReplace() && !toolInHand && !replaceable) { - startPos = startPos.offset(lookingAt.sideHit); - } - - //Get under tall grass and other replaceable blocks - if (modifierSettings.doQuickReplace() && !toolInHand && replaceable) { - startPos = startPos.down(); - } - - sideHit = lookingAt.sideHit; - hitVec = lookingAt.hitVec; - } - - //Dont render if in normal mode and modifiers are disabled - //Unless alwaysShowBlockPreview is true in config - if (modeSettings.getBuildMode() != BuildModes.BuildModeEnum.Normal || - (startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) || - BuildConfig.visuals.alwaysShowBlockPreview) { - - beginBlockPreviews(); - - IBuildMode buildModeInstance = modeSettings.getBuildMode().instance; - if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player); - if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player); - - if (sideHit != null) { - BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); - float percentile = ClientProxy.ticksInGame / 50f % 1f; - //TODO test - percentile = 1f; - - //get coordinates - List startCoordinates = BuildModes.findCoordinates(player, startPos); - - BlockPos firstPos = BlockPos.ORIGIN, secondPos = BlockPos.ORIGIN; - //remember first and last pos for highlighting - if (!startCoordinates.isEmpty()) { - firstPos = startCoordinates.get(0); - secondPos = startCoordinates.get(startCoordinates.size() - 1); - } - - //Limit number of blocks you can place - int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); - if (startCoordinates.size() > limit) { - startCoordinates = startCoordinates.subList(0, limit); - } - - List newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates); - - Collections.sort(newCoordinates, (lhs, rhs) -> { - // -1 - less than, 1 - greater than, 0 - equal - double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getPositionEyes(1f)).lengthSquared(); - double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getPositionEyes(1f)).lengthSquared(); - return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer); - }); - - //check if they are different from previous - if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) { - previousCoordinates = newCoordinates; - //if so, renew randomness of randomizer bag - ItemRandomizerBag.renewRandomness(); - } - - hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), - Math.abs(hitVec.z - ((int) hitVec.z))); - List itemStacks = new ArrayList<>(); - List blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, lookingAt.sideHit, itemStacks); - - //check if valid blockstates - if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) { - for (int i = newCoordinates.size() - 1; i >= 0; i--) { - BlockPos blockPos = newCoordinates.get(i); - IBlockState blockState = blockStates.get(i); - ItemStack itemstack = itemStacks.get(i); - //Check if can place - if (!itemstack.isEmpty() && SurvivalHelper.canPlayerEdit(player, player.world, blockPos, itemstack) && - SurvivalHelper.mayPlace(player.world, Block.getBlockFromItem(itemstack.getItem()), blockState, blockPos, true, EnumFacing.UP, player) && - SurvivalHelper.canReplace(player.world, player, blockPos)) { - - ShaderHelper.useShader(ShaderHelper.dissolve, generateShaderCallback(percentile, - new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos), - /*blockPos == firstPos ||*/ blockPos == secondPos)); - renderBlockPreview(dispatcher, blockPos, blockState); - } - } - } - } - endBlockPreviews(); - - beginLines(); - //Draw outlines if tool in hand - //Find proper raytrace: either normal range or increased range depending on canBreakFar - RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver; - RayTraceResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver; - if (toolInHand && breakingRaytrace != null && breakingRaytrace.typeOfHit == RayTraceResult.Type.BLOCK) { - List breakCoordinates = BuildModifiers.findCoordinates(player, breakingRaytrace.getBlockPos()); - - //Only render first outline if further than normal reach - boolean excludeFirst = objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK; - for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) { - BlockPos coordinate = breakCoordinates.get(i); - - IBlockState blockState = player.world.getBlockState(coordinate); - if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) { - if (SurvivalHelper.canBreak(player.world, player, coordinate) || i == 0) { - renderBlockOutline(coordinate); - } - } - } - } - endLines(); - } - - end(); - } - - - //----Mirror---- - - public static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) { - - GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuffer(); - - if (drawPlanes) { - bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR); - - bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); - bufferBuilder.pos(posA.x, posB.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); - bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); - bufferBuilder.pos(posB.x, posB.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); - - tessellator.draw(); - } - - if (drawLines) { - Vec3d middle = posA.add(posB).scale(0.5); - bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); - - bufferBuilder.pos(posA.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(posB.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); - if (drawVerticalLines) { - bufferBuilder.pos(middle.x, posA.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(middle.x, posB.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); - } - - tessellator.draw(); - } - } - - public static void drawMirrorPlaneY(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) { - - GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuffer(); - - if (drawPlanes) { - bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR); - - bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); - bufferBuilder.pos(posA.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); - bufferBuilder.pos(posB.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); - bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); - - tessellator.draw(); - } - - if (drawLines) { - Vec3d middle = posA.add(posB).scale(0.5); - bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); - - bufferBuilder.pos(middle.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(middle.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(posA.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(posB.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); - - tessellator.draw(); - } - } - - public static void drawMirrorLines(Mirror.MirrorSettings m) { - - Vec3d pos = m.position.add(epsilon); - - GL11.glColor4d(100, 100, 100, 255); - GL11.glLineWidth(2); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuffer(); - - bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); - - bufferBuilder.pos(pos.x - m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(pos.x + m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(pos.x, pos.y - m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(pos.x, pos.y + m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(pos.x, pos.y, pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex(); - bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex(); - - tessellator.draw(); - } - - private static Consumer generateShaderCallback(final float percentile, final Vec3d blockpos, final Vec3d firstpos, final Vec3d secondpos, final boolean highlight) { - Minecraft mc = Minecraft.getMinecraft(); - return (Integer shader) -> { - int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "percentile"); - int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight"); - int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos"); - int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos"); - int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos"); - int imageUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "image"); - int maskUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "mask"); - - //image - OpenGlHelper.setActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.renderEngine.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).getGlTextureId()); - ARBShaderObjects.glUniform1iARB(imageUniform, 0); - - OpenGlHelper.setActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit); - - GlStateManager.enableTexture2D(); - GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D); - - //mask - GL11.glBindTexture(GL11.GL_TEXTURE_2D, - mc.renderEngine.getTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png")).getGlTextureId()); - ARBShaderObjects.glUniform1iARB(maskUniform, secondaryTextureUnit); - - //blockpos - ARBShaderObjects.glUniform3fARB(blockposUniform, (float) blockpos.x, (float) blockpos.y, (float) blockpos.z); - ARBShaderObjects.glUniform3fARB(firstposUniform, (float) firstpos.x, (float) firstpos.y, (float) firstpos.z); - ARBShaderObjects.glUniform3fARB(secondposUniform, (float) secondpos.x, (float) secondpos.y, (float) secondpos.z); - - //percentile - ARBShaderObjects.glUniform1fARB(percentileUniform, percentile); - //highlight - ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0); - }; - } - - //IWORLDEVENTLISTENER IMPLEMENTATION - @Override - public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) { - - } - - @Override - public void notifyLightSet(BlockPos pos) { - - } - - @Override - public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) { - - } - - @Override - public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category, - double x, double y, double z, float volume, float pitch) { - - } - - @Override - public void playRecord(SoundEvent soundIn, BlockPos pos) { - - } - - @Override - public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord, - double xSpeed, double ySpeed, double zSpeed, int... parameters) { - - } - - @Override - public void spawnParticle(int id, boolean ignoreRange, boolean p_190570_3_, double x, double y, double z, - double xSpeed, double ySpeed, double zSpeed, int... parameters) { - - } - - @Override - public void onEntityAdded(Entity entityIn) { - - } - - @Override - public void onEntityRemoved(Entity entityIn) { - - } - - @Override - public void broadcastSound(int soundID, BlockPos pos, int data) { - - } - - @Override - public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data) { - - } - - //Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken - @Override - public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) { - Minecraft mc = Minecraft.getMinecraft(); - - ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); - if (!BuildModifiers.isEnabled(modifierSettings, pos)) return; - - List coordinates = BuildModifiers.findCoordinates(mc.player, pos); - for (int i = 1; i < coordinates.size(); i++) { - BlockPos coordinate = coordinates.get(i); - if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) { - //Send i as entity id because only one block can be broken per id - //Unless i happens to be the player id, then take something else - int fakeId = mc.player.getEntityId() != i ? i : coordinates.size(); - mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress); - } - } - } -} diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java b/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java index 9f57210..7e08a12 100644 --- a/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java @@ -44,19 +44,9 @@ public class SurvivalHelper { itemstack = ItemRandomizerBag.findStack(bagInventory, Item.getItemFromBlock(blockState.getBlock())); } - //Check if itemstack is correct - if (!(itemstack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemstack.getItem()) != blockState.getBlock()) { - EffortlessBuilding.log(player, "Cannot (re)place block", true); - EffortlessBuilding.log("SurvivalHelper#placeBlock: itemstack " + itemstack.toString() + " does not match blockstate " + blockState.toString()); - return false; - } - Block block = ((ItemBlock) itemstack.getItem()).getBlock(); - if (!itemstack.isEmpty() && canPlayerEdit(player, world, pos, itemstack) && - mayPlace(world, block, blockState, pos, skipCollisionCheck, facing.getOpposite(), player) && - canReplace(world, player, pos)) - { + if (canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) { //Drop existing block //TODO check if can replace dropBlock(world, player, pos); @@ -108,6 +98,107 @@ public class SurvivalHelper { return false; } + //Gives items directly to player + public static void dropBlock(World world, EntityPlayer player, BlockPos pos){ + if (player.isCreative()) return; + + IBlockState blockState = world.getBlockState(pos); + + int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand()); + List drops = blockState.getBlock().getDrops(world, pos, blockState, fortune); + for (ItemStack drop : drops) + { + ItemHandlerHelper.giveItemToPlayer(player, drop); + } + } + + /** + * Check if player can place a block. + * Turn randomizer bag into itemstack inside before. + * @param world + * @param player + * @param pos + * @param newBlockState the blockstate that is going to be placed + * @param itemStack the itemstack used for placing + * @param skipCollisionCheck skips collision check with entities + * @param sidePlacedOn + * @return Whether the player may place the block at pos with itemstack + */ + public static boolean canPlace(World world, EntityPlayer player, BlockPos pos, IBlockState newBlockState, ItemStack itemStack, boolean skipCollisionCheck, EnumFacing sidePlacedOn) { + + //Check if itemstack is correct + if (!(itemStack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemStack.getItem()) != newBlockState.getBlock()) { + EffortlessBuilding.log(player, "Cannot (re)place block", true); + EffortlessBuilding.log("SurvivalHelper#placeBlock: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString()); + return false; + } + + Block block = ((ItemBlock) itemStack.getItem()).getBlock(); + + return !itemStack.isEmpty() && canPlayerEdit(player, world, pos, itemStack) && + mayPlace(world, block, newBlockState, pos, skipCollisionCheck, sidePlacedOn, player) && + canReplace(world, player, pos); + } + + //Can be harvested with hand? (or in creative) + private static boolean canReplace(World world, EntityPlayer player, BlockPos pos){ + if (player.isCreative()) return true; + + IBlockState state = world.getBlockState(pos); + state = state.getBlock().getActualState(state, world, pos); + if (state.getMaterial().isToolNotRequired()) return true; + + return false; + } + + //From EntityPlayer#canPlayerEdit + private static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack) + { + if (player.capabilities.allowEdit) + { + //True in creative and survival mode + return true; + } + else + { + //Adventure mode + Block block = world.getBlockState(pos).getBlock(); + return stack.canPlaceOn(block) || stack.canEditBlocks(); + } + } + + //From World#mayPlace + private static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer) + { + IBlockState iblockstate1 = world.getBlockState(pos); + AxisAlignedBB axisalignedbb = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionBoundingBox(world, pos); + + if (axisalignedbb != Block.NULL_AABB && !world.checkNoEntityCollision(axisalignedbb.offset(pos), placer)) + { + return false; + } + + //Check if same block + //Necessary otherwise extra items will be dropped + if (iblockstate1 == newBlockState) { + return false; + } + + if (iblockstate1.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL) + { + return true; + } + + //Check quickreplace + if (placer instanceof EntityPlayer && ModifierSettingsManager.getModifierSettings(((EntityPlayer) placer)).doQuickReplace()) { + return true; + } + + return iblockstate1.getBlock().isReplaceable(world, pos) && blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn); + } + + + //Can break using held tool? (or in creative) public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) { IBlockState blockState = world.getBlockState(pos); @@ -151,75 +242,4 @@ public class SurvivalHelper { return toolLevel >= block.getHarvestLevel(state); } - - //Can be harvested with hand? (or in creative) - public static boolean canReplace(World world, EntityPlayer player, BlockPos pos){ - if (player.isCreative()) return true; - - IBlockState state = world.getBlockState(pos); - state = state.getBlock().getActualState(state, world, pos); - if (state.getMaterial().isToolNotRequired()) return true; - - return false; - } - - //Gives items directly to player - public static void dropBlock(World world, EntityPlayer player, BlockPos pos){ - if (player.isCreative()) return; - - IBlockState blockState = world.getBlockState(pos); - - int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand()); - List drops = blockState.getBlock().getDrops(world, pos, blockState, fortune); - for (ItemStack drop : drops) - { - ItemHandlerHelper.giveItemToPlayer(player, drop); - } - } - - //From EntityPlayer#canPlayerEdit - public static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack) - { - if (player.capabilities.allowEdit) - { - //True in creative and survival mode - return true; - } - else - { - //Adventure mode - Block block = world.getBlockState(pos).getBlock(); - return stack.canPlaceOn(block) || stack.canEditBlocks(); - } - } - - //From World#mayPlace - public static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer) - { - IBlockState iblockstate1 = world.getBlockState(pos); - AxisAlignedBB axisalignedbb = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionBoundingBox(world, pos); - - if (axisalignedbb != Block.NULL_AABB && !world.checkNoEntityCollision(axisalignedbb.offset(pos), placer)) - { - return false; - } - - //Check if same block - //Necessary otherwise extra items will be dropped - if (iblockstate1 == newBlockState) { - return false; - } - - if (iblockstate1.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL) - { - return true; - } - - //Check quickreplace - if (placer instanceof EntityPlayer && ModifierSettingsManager.getModifierSettings(((EntityPlayer) placer)).doQuickReplace()) { - return true; - } - - return iblockstate1.getBlock().isReplaceable(world, pos) && blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn); - } } diff --git a/src/main/java/nl/requios/effortlessbuilding/network/BlockBrokenMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/BlockBrokenMessage.java index 48144a5..ea2242b 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/BlockBrokenMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/BlockBrokenMessage.java @@ -13,6 +13,9 @@ import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; +/*** + * Sends a message to the server indicating that a player wants to break a block + */ public class BlockBrokenMessage implements IMessage { private boolean blockHit; diff --git a/src/main/java/nl/requios/effortlessbuilding/network/BlockPlacedMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/BlockPlacedMessage.java index 35315cc..3492dd3 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/BlockPlacedMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/BlockPlacedMessage.java @@ -13,7 +13,12 @@ import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; import nl.requios.effortlessbuilding.proxy.ClientProxy; +import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; +/*** + * Sends a message to the server indicating that a player wants to place a block. + * Received clientside: server has placed blocks and its letting the client know. + */ public class BlockPlacedMessage implements IMessage { private boolean blockHit; @@ -81,8 +86,11 @@ public class BlockPlacedMessage implements IMessage { if (ctx.side == Side.CLIENT){ //Received clientside - //Send back your info - return new BlockPlacedMessage(ClientProxy.previousLookAt); + EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> { + //Nod RenderHandler to do the dissolve shader effect + BlockPreviewRenderer.onBlocksPlaced(); + }); + return null; } else { //Received serverside EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> { diff --git a/src/main/java/nl/requios/effortlessbuilding/network/CancelModeMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/CancelModeMessage.java index c3c62d1..9308c43 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/CancelModeMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/CancelModeMessage.java @@ -9,6 +9,9 @@ import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmode.BuildModes; +/** + * Sends a message to the server indicating that a buildmode needs to be canceled for a player + */ public class CancelModeMessage implements IMessage { @Override diff --git a/src/main/java/nl/requios/effortlessbuilding/network/ModeSettingsMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/ModeSettingsMessage.java index 8cb89d7..aaa617c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/ModeSettingsMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/ModeSettingsMessage.java @@ -3,8 +3,6 @@ package nl.requios.effortlessbuilding.network; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.IThreadListener; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; @@ -14,6 +12,9 @@ import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.*; +/** + * Shares mode settings (see ModeSettingsManager) between server and client + */ public class ModeSettingsMessage implements IMessage { private ModeSettings modeSettings; diff --git a/src/main/java/nl/requios/effortlessbuilding/network/ModifierSettingsMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/ModifierSettingsMessage.java index 745ae50..f3aa54e 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/ModifierSettingsMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/ModifierSettingsMessage.java @@ -16,6 +16,9 @@ import nl.requios.effortlessbuilding.buildmodifier.RadialMirror; import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.*; +/** + * Shares modifier settings (see ModifierSettingsManager) between server and client + */ public class ModifierSettingsMessage implements IMessage { private ModifierSettings modifierSettings; diff --git a/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java new file mode 100644 index 0000000..2b0196f --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java @@ -0,0 +1,50 @@ +package nl.requios.effortlessbuilding.network; + +import io.netty.buffer.ByteBuf; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import net.minecraftforge.fml.relauncher.Side; +import nl.requios.effortlessbuilding.EffortlessBuilding; +import nl.requios.effortlessbuilding.buildmode.BuildModes; +import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; +import nl.requios.effortlessbuilding.proxy.ClientProxy; + +/*** + * Sends a message to the client asking for its lookat (objectmouseover) data. + * This is then sent back with a BlockPlacedMessage. + */ +public class RequestLookAtMessage implements IMessage { + + public RequestLookAtMessage() { + } + + @Override + public void toBytes(ByteBuf buf) { + } + + @Override + public void fromBytes(ByteBuf buf) { + } + + // The params of the IMessageHandler are + public static class MessageHandler implements IMessageHandler { + // Do note that the default constructor is required, but implicitly defined in this case + + @Override + public IMessage onMessage(RequestLookAtMessage message, MessageContext ctx) { + //EffortlessBuilding.log("message received on " + ctx.side + " side"); + + if (ctx.side == Side.CLIENT){ + //Received clientside + //Send back your info + return new BlockPlacedMessage(ClientProxy.previousLookAt); + } + return null; + } + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java b/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java index 57bb37d..1033bd2 100644 --- a/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java +++ b/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java @@ -9,6 +9,7 @@ import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.texture.TextureUtil; import net.minecraft.client.resources.IResource; @@ -52,8 +53,8 @@ import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu; import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui; import nl.requios.effortlessbuilding.helper.ReachHelper; -import nl.requios.effortlessbuilding.helper.RenderHelper; -import nl.requios.effortlessbuilding.helper.ShaderHelper; +import nl.requios.effortlessbuilding.render.RenderHandler; +import nl.requios.effortlessbuilding.render.ShaderHandler; import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.network.*; import org.lwjgl.input.Keyboard; @@ -72,11 +73,11 @@ public class ClientProxy implements IProxy { public static int ticksInGame = 0; - private static final HashMap buildModeIcons = new HashMap<>(); + private static final HashMap buildModeIcons = new HashMap<>(); @Override public void preInit(FMLPreInitializationEvent event) { - ShaderHelper.init(); + ShaderHandler.init(); } @Override @@ -131,7 +132,7 @@ public class ClientProxy implements IProxy { @SubscribeEvent public static void onEntityJoinWorld(EntityJoinWorldEvent event) { if (event.getEntity() == Minecraft.getMinecraft().player) { - event.getWorld().addEventListener(new RenderHelper()); + event.getWorld().addEventListener(new RenderHandler()); } } @@ -142,67 +143,12 @@ public class ClientProxy implements IProxy { for ( final BuildModes.BuildModeEnum mode : BuildModes.BuildModeEnum.values() ) { - loadIcon( map, mode ); + final ResourceLocation sprite = new ResourceLocation("effortlessbuilding", "icons/" + mode.name().toLowerCase()); + buildModeIcons.put( mode, map.registerSprite(sprite)); } } - /** - * From Chisels and Bits by AlgorithmX2 - * https://github.com/AlgorithmX2/Chisels-and-Bits/blob/1.12/src/main/java/mod/chiselsandbits/core/ClientSide.java - */ - private static void loadIcon(final TextureMap map, final BuildModes.BuildModeEnum mode) { - final RadialMenu.SpriteIconPositioning sip = new RadialMenu.SpriteIconPositioning(); - - final ResourceLocation sprite = new ResourceLocation( "effortlessbuilding", "icons/" + mode.name().toLowerCase() ); - final ResourceLocation png = new ResourceLocation( "effortlessbuilding", "textures/icons/" + mode.name().toLowerCase() + ".png" ); - - sip.sprite = map.registerSprite( sprite ); - - try - { - final IResource iresource = Minecraft.getMinecraft().getResourceManager().getResource( png ); - final BufferedImage bi = TextureUtil.readBufferedImage( iresource.getInputStream() ); - - int bottom = 0; - int right = 0; - sip.left = bi.getWidth(); - sip.top = bi.getHeight(); - - for ( int x = 0; x < bi.getWidth(); x++ ) - { - for ( int y = 0; y < bi.getHeight(); y++ ) - { - final int color = bi.getRGB( x, y ); - final int a = color >> 24 & 0xff; - if ( a > 0 ) - { - sip.left = Math.min( sip.left, x ); - right = Math.max( right, x ); - - sip.top = Math.min( sip.top, y ); - bottom = Math.max( bottom, y ); - } - } - } - - sip.height = bottom - sip.top + 1; - sip.width = right - sip.left + 1; - - sip.left /= bi.getWidth(); - sip.width /= bi.getWidth(); - sip.top /= bi.getHeight(); - sip.height /= bi.getHeight(); - } catch (final IOException e) { - sip.height = 1; - sip.width = 1; - sip.left = 0; - sip.top = 0; - } - - buildModeIcons.put( mode, sip ); - } - - public static RadialMenu.SpriteIconPositioning getBuildModeIcon(BuildModes.BuildModeEnum mode) { + public static TextureAtlasSprite getBuildModeIcon(BuildModes.BuildModeEnum mode) { return buildModeIcons.get(mode); } @@ -295,8 +241,6 @@ public class ClientProxy implements IProxy { //QuickReplace toggle if (keyBindings[1].isPressed()) { - - ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace()); EffortlessBuilding.log(player, "Set "+ TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + ( @@ -315,8 +259,10 @@ public class ClientProxy implements IProxy { if (keyBindings[4].isPressed()) { //TODO remove - ShaderHelper.init(); + ShaderHandler.init(); EffortlessBuilding.log(player, "Reloaded shaders"); + //player.playSound(SoundEvents.UI_BUTTON_CLICK, 1f, 1f); + player.playSound(EffortlessBuilding.SOUND_BUILD_CLICK, 1f, 1f); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java new file mode 100644 index 0000000..d11bc49 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java @@ -0,0 +1,285 @@ +package nl.requios.effortlessbuilding.render; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.EffortlessBuilding; +import nl.requios.effortlessbuilding.buildmode.BuildModes; +import nl.requios.effortlessbuilding.buildmode.IBuildMode; +import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; +import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; +import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; +import nl.requios.effortlessbuilding.helper.ReachHelper; +import nl.requios.effortlessbuilding.helper.SurvivalHelper; +import nl.requios.effortlessbuilding.item.ItemRandomizerBag; +import nl.requios.effortlessbuilding.proxy.ClientProxy; +import org.lwjgl.opengl.ARBMultitexture; +import org.lwjgl.opengl.ARBShaderObjects; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +@SideOnly(Side.CLIENT) +public class BlockPreviewRenderer { + private static List previousCoordinates; + private static List previousBlockStates; + private static List previousItemStacks; + private static BlockPos previousFirstPos; + private static BlockPos previousSecondPos; + private static int soundTime = 0; + + static class PlacedData { + float time; + List coordinates; + List blockStates; + List itemStacks; + BlockPos firstPos; + BlockPos secondPos; + + public PlacedData(float time, List coordinates, List blockStates, List itemStacks, BlockPos firstPos, BlockPos secondPos) { + this.time = time; + this.coordinates = coordinates; + this.blockStates = blockStates; + this.itemStacks = itemStacks; + this.firstPos = firstPos; + this.secondPos = secondPos; + } + } + + private static List placedDataList = new ArrayList<>(); + + private static final int secondaryTextureUnit = 7; + + public static void render(EntityPlayer player, ModifierSettingsManager.ModifierSettings modifierSettings, ModeSettingsManager.ModeSettings modeSettings) { + + //Render placed blocks with dissolve effect + for (int i = 0; i < placedDataList.size(); i++) { + PlacedData placed = placedDataList.get(i); + if (placed.coordinates != null && !placed.coordinates.isEmpty()) { + + RenderHandler.beginBlockPreviews(); + + float dissolve = (ClientProxy.ticksInGame - placed.time) / (float) BuildConfig.visuals.dissolveTime; + renderBlockPreviews(placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false); + + RenderHandler.endBlockPreviews(); + } + } + //Expire + placedDataList.removeIf(placed -> placed.time + BuildConfig.visuals.dissolveTime < ClientProxy.ticksInGame); + + //Render block previews + RayTraceResult lookingAt = ClientProxy.getLookingAt(player); + if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.Normal) lookingAt = Minecraft.getMinecraft().objectMouseOver; + + ItemStack mainhand = player.getHeldItemMainhand(); + boolean toolInHand = !(!mainhand.isEmpty() && (mainhand.getItem() instanceof ItemBlock || mainhand.getItem() instanceof ItemRandomizerBag)); + + BlockPos startPos = null; + EnumFacing sideHit = null; + Vec3d hitVec = null; + + //Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS) + if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) { + startPos = lookingAt.getBlockPos(); + + //Check if tool (or none) in hand + boolean replaceable = player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos); + if (!modifierSettings.doQuickReplace() && !toolInHand && !replaceable) { + startPos = startPos.offset(lookingAt.sideHit); + } + + //Get under tall grass and other replaceable blocks + if (modifierSettings.doQuickReplace() && !toolInHand && replaceable) { + startPos = startPos.down(); + } + + sideHit = lookingAt.sideHit; + hitVec = lookingAt.hitVec; + } + + //Dont render if in normal mode and modifiers are disabled + //Unless alwaysShowBlockPreview is true in config + if (modeSettings.getBuildMode() != BuildModes.BuildModeEnum.Normal || + (startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) || + BuildConfig.visuals.alwaysShowBlockPreview) { + + RenderHandler.beginBlockPreviews(); + + IBuildMode buildModeInstance = modeSettings.getBuildMode().instance; + if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player); + if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player); + + if (sideHit != null) { + + //get coordinates + List startCoordinates = BuildModes.findCoordinates(player, startPos); + + BlockPos firstPos = BlockPos.ORIGIN, secondPos = BlockPos.ORIGIN; + //Remember first and last pos for the shader + if (!startCoordinates.isEmpty()) { + firstPos = startCoordinates.get(0); + secondPos = startCoordinates.get(startCoordinates.size() - 1); + } + + //Limit number of blocks you can place + int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); + if (startCoordinates.size() > limit) { + startCoordinates = startCoordinates.subList(0, limit); + } + + List newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates); + + Collections.sort(newCoordinates, (lhs, rhs) -> { + // -1 - less than, 1 - greater than, 0 - equal + double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getPositionEyes(1f)).lengthSquared(); + double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getPositionEyes(1f)).lengthSquared(); + return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer); + }); + + hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), + Math.abs(hitVec.z - ((int) hitVec.z))); + List itemStacks = new ArrayList<>(); + List blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); + + //Check if they are different from previous + //TODO fix triggering when moving player + if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) { + previousCoordinates = newCoordinates; + //remember the rest for placed blocks + previousBlockStates = blockStates; + previousItemStacks = itemStacks; + previousFirstPos = firstPos; + previousSecondPos = secondPos; + + //if so, renew randomness of randomizer bag + ItemRandomizerBag.renewRandomness(); + //and play sound (max once every tick) + if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientProxy.ticksInGame - 0) { + soundTime = ClientProxy.ticksInGame; + //player.playSound(EffortlessBuilding.SOUND_BUILD_CLICK, 0.2f, 1f); + player.playSound(blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.world, + newCoordinates.get(0), player).getPlaceSound(), 0.3f, 1f); + } + } + + //Render block previews + if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) { + renderBlockPreviews(newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, true); + } + } + + RenderHandler.endBlockPreviews(); + + RenderHandler.beginLines(); + //Draw outlines if tool in hand + //Find proper raytrace: either normal range or increased range depending on canBreakFar + RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver; + RayTraceResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver; + if (toolInHand && breakingRaytrace != null && breakingRaytrace.typeOfHit == RayTraceResult.Type.BLOCK) { + List breakCoordinates = BuildModifiers.findCoordinates(player, breakingRaytrace.getBlockPos()); + + //Only render first outline if further than normal reach + boolean excludeFirst = objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK; + for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) { + BlockPos coordinate = breakCoordinates.get(i); + + IBlockState blockState = player.world.getBlockState(coordinate); + if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) { + if (SurvivalHelper.canBreak(player.world, player, coordinate) || i == 0) { + RenderHandler.renderBlockOutline(coordinate); + } + } + } + } + RenderHandler.endLines(); + } + } + + protected static void renderBlockPreviews(List coordinates, List blockStates, + List itemStacks, float dissolve, BlockPos firstPos, + BlockPos secondPos, boolean checkCanPlace) { + EntityPlayer player = Minecraft.getMinecraft().player; + BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); + + for (int i = coordinates.size() - 1; i >= 0; i--) { + BlockPos blockPos = coordinates.get(i); + IBlockState blockState = blockStates.get(i); + ItemStack itemstack = itemStacks.get(i); + + //Check if can place + //If check is turned off, check if blockstate is the same (for dissolve effect) + if (SurvivalHelper.canPlace(player.world, player, blockPos, blockState, itemstack, true, EnumFacing.UP) || + (!checkCanPlace && player.world.getBlockState(blockPos) == blockState)) { + + ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve, + new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos), + blockPos == secondPos)); + RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState); + } + } + + } + + public static void onBlocksPlaced() { + //Save current coordinates, blockstates and itemstacks + placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates, + previousItemStacks, previousFirstPos, previousSecondPos)); + + } + + private static Consumer generateShaderCallback(final float dissolve, final Vec3d blockpos, final Vec3d firstpos, final Vec3d secondpos, final boolean highlight) { + Minecraft mc = Minecraft.getMinecraft(); + return (Integer shader) -> { + int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "dissolve"); + int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight"); + int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos"); + int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos"); + int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos"); + int imageUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "image"); + int maskUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "mask"); + + //image + OpenGlHelper.setActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.renderEngine.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).getGlTextureId()); + ARBShaderObjects.glUniform1iARB(imageUniform, 0); + + OpenGlHelper.setActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit); + + GlStateManager.enableTexture2D(); + GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D); + + //mask + GL11.glBindTexture(GL11.GL_TEXTURE_2D, + mc.renderEngine.getTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png")).getGlTextureId()); + ARBShaderObjects.glUniform1iARB(maskUniform, secondaryTextureUnit); + + //blockpos + ARBShaderObjects.glUniform3fARB(blockposUniform, (float) blockpos.x, (float) blockpos.y, (float) blockpos.z); + ARBShaderObjects.glUniform3fARB(firstposUniform, (float) firstpos.x, (float) firstpos.y, (float) firstpos.z); + ARBShaderObjects.glUniform3fARB(secondposUniform, (float) secondpos.x, (float) secondpos.y, (float) secondpos.z); + + //dissolve + ARBShaderObjects.glUniform1fARB(percentileUniform, dissolve); + //highlight + ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0); + }; + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/render/ModifierRenderer.java b/src/main/java/nl/requios/effortlessbuilding/render/ModifierRenderer.java new file mode 100644 index 0000000..7f99656 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/render/ModifierRenderer.java @@ -0,0 +1,175 @@ +package nl.requios.effortlessbuilding.render; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import nl.requios.effortlessbuilding.buildmodifier.Mirror; +import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; +import nl.requios.effortlessbuilding.buildmodifier.RadialMirror; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.Color; + +@SideOnly(Side.CLIENT) +public class ModifierRenderer { + + protected static final Color colorX = new Color(255, 72, 52); + protected static final Color colorY = new Color(67, 204, 51); + protected static final Color colorZ = new Color(52, 247, 255); + protected static final Color colorRadial = new Color(52, 247, 255); + protected static final int lineAlpha = 200; + protected static final int planeAlpha = 75; + protected static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting + + public static void render(ModifierSettingsManager.ModifierSettings modifierSettings) { + RenderHandler.beginLines(); + + //Mirror lines and areas + Mirror.MirrorSettings m = modifierSettings.getMirrorSettings(); + if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ)) + { + Vec3d pos = m.position.add(epsilon); + int radius = m.radius; + + if (m.mirrorX) + { + Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius); + Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius); + + drawMirrorPlane(posA, posB, colorX, m.drawLines, m.drawPlanes, true); + } + if (m.mirrorY) + { + Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius); + Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius); + + drawMirrorPlaneY(posA, posB, colorY, m.drawLines, m.drawPlanes); + } + if (m.mirrorZ) + { + Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z); + Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z); + + drawMirrorPlane(posA, posB, colorZ, m.drawLines, m.drawPlanes, true); + } + + //Draw axis coordinated colors if two or more axes are enabled + //(If only one is enabled the lines are that planes color) + if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ))) + { + drawMirrorLines(m); + } + } + + //Radial mirror lines and areas + RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings(); + if (r != null && r.enabled) + { + Vec3d pos = r.position.add(epsilon); + int radius = r.radius; + + float angle = 2f * ((float) Math.PI) / r.slices; + Vec3d relStartVec = new Vec3d(radius, 0, 0); + if (r.slices%4 == 2) relStartVec = relStartVec.rotateYaw(angle / 2f); + + for (int i = 0; i < r.slices; i++) { + Vec3d relNewVec = relStartVec.rotateYaw(angle * i); + Vec3d newVec = pos.add(relNewVec); + + Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z); + Vec3d posB = new Vec3d(newVec.x, pos.y + radius, newVec.z); + drawMirrorPlane(posA, posB, colorRadial, r.drawLines, r.drawPlanes, false); + } + } + + RenderHandler.endLines(); + } + + + //----Mirror---- + + protected static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) { + + GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + if (drawPlanes) { + bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posA.x, posB.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posB.x, posB.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + + tessellator.draw(); + } + + if (drawLines) { + Vec3d middle = posA.add(posB).scale(0.5); + bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(posA.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(posB.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + if (drawVerticalLines) { + bufferBuilder.pos(middle.x, posA.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(middle.x, posB.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + } + + tessellator.draw(); + } + } + + protected static void drawMirrorPlaneY(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) { + + GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + if (drawPlanes) { + bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posA.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posB.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + + tessellator.draw(); + } + + if (drawLines) { + Vec3d middle = posA.add(posB).scale(0.5); + bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(middle.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(middle.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(posA.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(posB.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + + tessellator.draw(); + } + } + + protected static void drawMirrorLines(Mirror.MirrorSettings m) { + + Vec3d pos = m.position.add(epsilon); + + GL11.glColor4d(100, 100, 100, 255); + GL11.glLineWidth(2); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(pos.x - m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x + m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x, pos.y - m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x, pos.y + m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x, pos.y, pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex(); + + tessellator.draw(); + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java b/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java new file mode 100644 index 0000000..681798c --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java @@ -0,0 +1,213 @@ +package nl.requios.effortlessbuilding.render; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderGlobal; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.IWorldEventListener; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import nl.requios.effortlessbuilding.EffortlessBuilding; +import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; +import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; +import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; +import nl.requios.effortlessbuilding.helper.SurvivalHelper; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import javax.annotation.Nullable; +import java.util.List; + +/*** + * Main render class for Effortless Building + */ +@Mod.EventBusSubscriber(Side.CLIENT) +public class RenderHandler implements IWorldEventListener { + + @SubscribeEvent + public static void onRender(RenderWorldLastEvent event) { + EntityPlayer player = Minecraft.getMinecraft().player; + ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); + ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); + + begin(event.getPartialTicks()); + + //Mirror and radial mirror lines and areas + ModifierRenderer.render(modifierSettings); + + //Render block previews + BlockPreviewRenderer.render(player, modifierSettings, modeSettings); + + end(); + } + + private static void begin(float partialTicks) { + EntityPlayer player = Minecraft.getMinecraft().player; + double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks; + double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks; + double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks; + Vec3d playerPos = new Vec3d(playerX, playerY, playerZ); + + GL11.glPushMatrix(); + GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z); + + GL11.glDepthMask(false); + } + + protected static void beginLines() { + GL11.glPushAttrib(GL11.GL_ENABLE_BIT); + GL11.glDisable(GL11.GL_CULL_FACE); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_TEXTURE_2D); + + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + GL11.glLineWidth(2); + } + + protected static void endLines() { + GL11.glPopAttrib(); + } + + protected static void beginBlockPreviews() { + GL11.glPushAttrib(GL11.GL_ENABLE_BIT); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glEnable(GL11.GL_TEXTURE_2D); + Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_color.png")); + Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png")); + + Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL14.glBlendColor(1F, 1F, 1F, 0.8f); + } + + protected static void endBlockPreviews() { + ShaderHandler.releaseShader(); + GlStateManager.disableBlend(); + GL11.glPopAttrib(); + } + + private static void end() { + GL11.glDepthMask(true); + GL11.glPopMatrix(); + } + + protected static void renderBlockPreview(BlockRendererDispatcher dispatcher, BlockPos blockPos, IBlockState blockState) { + GlStateManager.pushMatrix(); + GlStateManager.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ()); + GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.translate(-0.005f, -0.005f, 0.005f); + GlStateManager.scale(1.01f, 1.01f, 1.01f); + dispatcher.renderBlockBrightness(blockState, 0.85f); + GlStateManager.popMatrix(); + } + + protected static void renderBlockOutline(BlockPos pos) { + renderBlockOutline(pos, pos); + } + + //Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z + protected static void renderBlockOutline(BlockPos pos1, BlockPos pos2) { + GL11.glLineWidth(2); + + AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026); + + RenderGlobal.drawSelectionBoundingBox(aabb, 0f, 0f, 0f, 0.4f); + } + + + + //IWORLDEVENTLISTENER IMPLEMENTATION + @Override + public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) { + + } + + @Override + public void notifyLightSet(BlockPos pos) { + + } + + @Override + public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) { + + } + + @Override + public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category, + double x, double y, double z, float volume, float pitch) { + + } + + @Override + public void playRecord(SoundEvent soundIn, BlockPos pos) { + + } + + @Override + public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord, + double xSpeed, double ySpeed, double zSpeed, int... parameters) { + + } + + @Override + public void spawnParticle(int id, boolean ignoreRange, boolean p_190570_3_, double x, double y, double z, + double xSpeed, double ySpeed, double zSpeed, int... parameters) { + + } + + @Override + public void onEntityAdded(Entity entityIn) { + + } + + @Override + public void onEntityRemoved(Entity entityIn) { + + } + + @Override + public void broadcastSound(int soundID, BlockPos pos, int data) { + + } + + @Override + public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data) { + + } + + //Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken + @Override + public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) { + Minecraft mc = Minecraft.getMinecraft(); + + ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); + if (!BuildModifiers.isEnabled(modifierSettings, pos)) return; + + List coordinates = BuildModifiers.findCoordinates(mc.player, pos); + for (int i = 1; i < coordinates.size(); i++) { + BlockPos coordinate = coordinates.get(i); + if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) { + //Send i as entity id because only one block can be broken per id + //Unless i happens to be the player id, then take something else + int fakeId = mc.player.getEntityId() != i ? i : coordinates.size(); + mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress); + } + } + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/ShaderHelper.java b/src/main/java/nl/requios/effortlessbuilding/render/ShaderHandler.java similarity index 94% rename from src/main/java/nl/requios/effortlessbuilding/helper/ShaderHelper.java rename to src/main/java/nl/requios/effortlessbuilding/render/ShaderHandler.java index 1994341..1ffde12 100644 --- a/src/main/java/nl/requios/effortlessbuilding/helper/ShaderHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/render/ShaderHandler.java @@ -10,27 +10,22 @@ * * File Created @ [Apr 9, 2014, 11:20:26 PM (GMT)] */ -package nl.requios.effortlessbuilding.helper; +package nl.requios.effortlessbuilding.render; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GLAllocation; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.proxy.ClientProxy; import org.apache.logging.log4j.Level; import org.lwjgl.opengl.*; -import org.lwjgl.util.vector.Matrix4f; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; -import java.nio.FloatBuffer; import java.nio.charset.StandardCharsets; import java.util.function.Consumer; -public final class ShaderHelper { +public final class ShaderHandler { private static final int VERT_ST = ARBVertexShader.GL_VERTEX_SHADER_ARB; private static final int FRAG_ST = ARBFragmentShader.GL_FRAGMENT_SHADER_ARB; @@ -149,7 +144,7 @@ public final class ShaderHelper { private static String readFileAsString(String filename) throws Exception { StringBuilder source = new StringBuilder(); - InputStream in = ShaderHelper.class.getResourceAsStream(filename); + InputStream in = ShaderHandler.class.getResourceAsStream(filename); Exception exception = null; BufferedReader reader; diff --git a/src/main/resources/assets/effortlessbuilding/lang/en_us.lang b/src/main/resources/assets/effortlessbuilding/lang/en_us.lang index d7b8d3b..0353bfe 100644 --- a/src/main/resources/assets/effortlessbuilding/lang/en_us.lang +++ b/src/main/resources/assets/effortlessbuilding/lang/en_us.lang @@ -9,4 +9,6 @@ item.effortlessbuilding:reach_upgrade1.name=Reach Upgrade 1 item.effortlessbuilding:reach_upgrade2.name=Reach Upgrade 2 item.effortlessbuilding:reach_upgrade3.name=Reach Upgrade 3 -commands.reach.usage=/reach \ No newline at end of file +commands.reach.usage=/reach + +effortlessbuilding.subtitle.build_click=Click \ No newline at end of file diff --git a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag index bf5efb9..2663dff 100644 --- a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag +++ b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag @@ -2,7 +2,7 @@ uniform int time; // Passed in, see ShaderHelper.java -uniform float percentile; // Passed in via Callback +uniform float dissolve; // Passed in via Callback uniform int highlight; uniform vec3 blockpos; uniform vec3 firstpos; @@ -44,28 +44,28 @@ void main() { vec4 maskColor = texture2D(mask, maskcoord); float maskgs = maskColor.r; - //color.rgb *= gl_Color.rgb; + color.rgb *= gl_Color.rgb; //desaturate color.rgb *= vec3(0.8); //add blueish hue - color.rgb += vec3(-0.2, 0.0, 0.3); + color.rgb += vec3(-0.1, 0.0, 0.2); //add pulsing blue float pulse = (sin(time / 5.0) + 1.0) / 2.0; - color.rgb += (1.0 - color.rgb) * vec3(-0.5, 0.2, 0.6) * pulse; + color.rgb += 0.4 * vec3(-0.5, 0.2, 0.6) * pulse; //add diagonal highlights float diagTime = mod(time / 40.0, 1.4) - 0.2; float diag = smoothstep(diagTime - 0.2, diagTime, place) - smoothstep(diagTime, diagTime + 0.2, place); - color.rgb += (1.0 - color.rgb) * diag * vec3(0.0, 0.2, 0.4); + color.rgb += 0.2 * diag * vec3(0.0, 0.2, 0.4); float diagTime2 = mod(time / 70.0, 1.4) - 0.2; float diag2 = smoothstep(diagTime2 - 0.2, diagTime2, place) - smoothstep(diagTime2, diagTime2 + 0.2, place); - color.rgb += (1.0 - color.rgb) * diag2 * vec3(0.0, 0.4, 0.8); + color.rgb += 0.2 * diag2 * vec3(0.0, 0.4, 0.8); - //add shading + //add edge shading // vec3 p1; // //if (firstpos.x < secondpos.x) // @@ -77,21 +77,16 @@ void main() { // float distToEdge = min(min(distToEdge1, distToEdge2), distToEdge3); // color.rgb += vec3(0.5 - smoothstep(0, 0.5, distToEdge)) * 0.5; + //add flat shading + if (abs(normal.x) > 0.5) + color.rgb -= 0.0; + if (abs(normal.y) > 0.5) + color.rgb += 0.05; + if (abs(normal.z) > 0.5) + color.rgb -= 0.05; -// pulse = 1.0;//pulse / 2.0 + 0.5; -// vec4 pulseColor = texture2D(mask, maskcoord + time / 700.0); -// vec4 pulseColor2 = texture2D(mask, vec2(maskcoord.x + time / 600.0, maskcoord.y - time / 600.0)); -// float pulseGreyScale = pulseColor.r + pulseColor2.r / 2.0; -// -// color.r -= color.r * pulseColor.r * pulse * 0.2; -// color.g += (1.0 - color.g) * pulseColor.r * pulse * 0.2; -// color.b += (1.0 - color.b) * pulseColor.r * pulse * 0.8; -// -// color.r -= color.r * pulseColor2.r * pulse * 0.4; -// color.g += (1.0 - color.g) * pulseColor2.r * pulse * 0.2; -// color.b += (1.0 - color.b) * pulseColor2.r * pulse; - if(highlight == 1) { + if(highlight == 1 && dissolve == 0.0) { color.r += 0.0; color.g += 0.1; color.b -= 0.2; @@ -101,7 +96,7 @@ void main() { color.g = max(0, min(1, color.g)); color.b = max(0, min(1, color.b)); - if (maskgs * 0.3 + place * 0.7 <= percentile) - gl_FragColor = color; - else gl_FragColor = vec4(texcolor.rgb, 0.0); + if (maskgs * 0.3 + place * 0.7 <= dissolve) + gl_FragColor = vec4(texcolor.rgb, 0.0); + else gl_FragColor = color; } \ No newline at end of file diff --git a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.vert b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.vert index 0903b43..ac55820 100644 --- a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.vert +++ b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.vert @@ -2,7 +2,7 @@ uniform int time; // Passed in, see ShaderHelper.java -uniform float percentile; // Passed in via Callback +uniform float dissolve; // Passed in via Callback uniform int highlight; uniform vec3 blockpos; uniform vec3 firstpos; @@ -15,6 +15,8 @@ varying vec3 normal; void main() { gl_Position = ftransform();//gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_FrontColor = gl_Color; + gl_BackColor = gl_Color; position = gl_Vertex; normal = gl_Normal; diff --git a/src/main/resources/assets/effortlessbuilding/sounds.json b/src/main/resources/assets/effortlessbuilding/sounds.json new file mode 100644 index 0000000..7316a5d --- /dev/null +++ b/src/main/resources/assets/effortlessbuilding/sounds.json @@ -0,0 +1,11 @@ +{ + "build_click": { + "category": "block", + "subtitle": "effortlessbuilding.subtitle.build_click", + "sounds": [ + { + "name": "effortlessbuilding:build_click" + } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/effortlessbuilding/sounds/build_click.ogg b/src/main/resources/assets/effortlessbuilding/sounds/build_click.ogg new file mode 100644 index 0000000000000000000000000000000000000000..468f43c02c3692866aa5c59cf4fbd36da4f82eb0 GIT binary patch literal 4372 zcmeI0XHZjH*T+vnZyGwGTtW%Z2Xwf8>eCK@cjJ_?R5 zE-uU#!7P5KeZqYGA^^NsjE|PKil(NDx|$jyB+xr1EW$f565Px4WzPCvaS1%_&zx|O zSvUazHV3HxhVyU4{0`+e9{kSqZ|wXI_#4b``QnYNa2hH)IuWcJ|JtX8K(WVV0FZC{ zcE~AsulzgkpW1?ZV@&@;RshFP)_w0D+$aGcD8HVwJGDq4niQD@K+)(LlgLv?Vw4sf@ z;62dv-o2}X?;{62rII zSs9VHep_G6u8-cwlox-1jE?}o0YHGHU!(T%AXo{4jm($zwm=KZc8j0jK>l%;(U9gV zaILiCUwZ`D9LNGPMLsgdOR}T%b%olQlRkD!+}XylUv$~a=G)%nRq9t9H??=1Uvgz{ zy4vq@?~jn!u@5R1sB%%(+$^8TXnq9SV8T>!!$F--*-;+Gx~%cox3 zF#G?&5axF{P=zJ3$(3ddFc8NP?KTIE^Y~B_@XPAA;59IzhAP}FH}vLsPCI2y0ma3p zAL8V7tBP&BlaqEjDo36VW|G?;QYFh7>n3I0AD}9VmtzY`CHF1L220khS(y<;@qw18 zNyq4UVm}wHw8!x-oH(*sP-;nbl(WN41|?S6@HY=6y+~Ywc@p?T`}Gt!p{+E#57{pv zU&vvnk~7j8%9Q@xp__9HB`yeodriLgfp3kTo}iy6rv$(iIR`+*l#_hc>a{Q^(kTo8 zu;NZ0jG0oymkc|hO)l>7g7s(h?^ym4yS4?6;9UKUU@#0ofzgVq>s5m25-(WC4?qP0 z$7eh?NdmlLC70pRkj|lFiR??2lSSji)lK;kF8jgzj)@EQ>=H65`BHU{>k8a6`aL)A z5OtN$b(TgWok9%N89)%TB6@(b+VE|+Kckn{= zhilB2fWgyDhHHjE)tEka209T!{_MI zOp$n#6n>7~+EsNQ*w)zX(y`o=bro)k7NNC)Xb(nNz!U&n!2A-~IP%`2sGCt!Y9(t+ zV&*w$o)%K4LQ5Jgr46-c6cU^hq%De}kMK-ab{l0La3|Ev*nOCfqhAv~{2d-x_7dg_u07OtK1TRe3lySrm1v%pF*Ac8A7v9Y~3jFM4r z5>kZ2KebvHb8gh@DwaWWc@5{PzL1W+H^G~v=$ZXV&Bz{Oi>j-349AIFg-2W(ONl^T zOEVd2dZUnF{QmC9+2`d5$g7YmJaw9>JOW4rHda=ctJBtDc=>=&_Z3C)Ir;QFWaKR2+x1pMKd+0u6pzfR!l*`M;mE@U zN<5ruU;Ti4J-h7ivfYb(tdCIyiQ<;IojKsxK-4v>u}0KRvI;sc#>lGNP;d()*1S98 z&f2q`$FV}T6q!<=N+S>4m6+1en`bOPDzvP+_~702@<(#qy7Qi@%26ElWRk$wwF$Z0 z*4x(7aosPIs>1Bf%&{}W%6Y*SycqWYg*&SA5K-L*2&d zDn9I<)zJO;egou=d)fut;KL6gxQzGX3s10H*Uu?QA<5}6en4xT=atJA+vG=x4R}qds)lSaAp` z5SvVIWu*y0=lR&q6jIG)1_irNpAXhUQFl}|!f82ubaP)*+w-du_{d7OHq1hUeJ=m1 ziOgp3p2W)C0_j4rvrVg@`{m8pj$Ad{?dxfR`X>LzS+I z;-8M)kL$Dc$@EB?xWAwOmr1vcJRSB_eYPDUIJ*G3S+Us!%XPn$5<5WdA~U{Tics7I~Q%m70 zEG9a9LS$T>g)v4@Odl;kE@R8BE>>bM|oG#59eT#$==-`&Aura0r?h=$y#UKRQ`^C)W$c9aZSJMYwn=$oS~$tPS$&ps3AZ}FN2}K zvc4SH%-+urJCJ21Px}k1_*j1WKlwi)0XJSiLYyPXW|9C_uFPZH%1ot+u?lfMrvF7z}w7+YJnxu@@m(S)nb76`1mLu?ig<^##}n7xY!F zkGRZP4t5w9+S^_X%S-3?Qmj9Mv#2_6tQp}m&MhI?wx;)j1~u*T5x8ho5W0 z6A7M@p>0xqTeP3SyWTTSoI4paHJfSnIw@G_R@$KIGg||S zu3O}FOPQY|eKlT|#$2=Q4z4k4&z*zsuc_+_=LNaE- zu`6yr20`ZY5A*FCNd%M;qI!is#8(o_ksZj_`y_!hhv6Gsn&ZW9z2F6Z%A~7z+V{&k z?_^Nn)l13`;;*7uPWTe&Ux9x5i!vRV@|1*XuXtk-t~Q#^3}297fH$l?n_*4!HkI8t z9UzRUOD<)Yv~=KVg9J_Pgp&)ni^%(x-|K$FDG|Nj^3{|AUZ1;GFS literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/effortlessbuilding/textures/icons/cube.png b/src/main/resources/assets/effortlessbuilding/textures/icons/cube.png new file mode 100644 index 0000000000000000000000000000000000000000..c9afbbdea795c814ce80caa3e9196e1221b7a0a0 GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=DkxL735kHCP2G$X?><>&pI^iGztzODSZ^FQCvFPZ!4!i_>!_pA~FT;Axe&HWO|a zK3cJb&wB%}&IxWmjdt6EEgv4A+ZQ}xPrn3*fuNwOlGkP#Vk+47&+Z5@;BK32{Xy8k`)QSJTNU1AJ7)~)v1a4k$BcM7{s(PH*f z2DxvT+!o9;e61{g&T`K4$i^j=x3{fQ=T-1_TJm#iQ+>$S15w;*di-wM@!wzT8WeXf z-Fe+ddH#n&8Q-Sjyc_)zi(j5=V)1M+c{JVd+r8xiPP2Nyio1GGf5WN3^#$lJ22WQ% Jmvv4FO#sCQb_Da)($X?><>&pI^iGzvJ;J#TdNa(+(i(`nz>9dm-<{dT=aqV9|q4t2* z)ZSZ(j2BNVSy^JE#dXuarH}Qkyo^MgRFIfJ((z?S-?~>Mcwg0dJIj}O_a)`JUB|!M z+WrWi6vU>Py5kDJqQIdYx@^h~#e57)MHuc?8%mt_?_Me)C`6 zZabXhxqtW54H2I<)QJ}EQaUZ?zF?D%d;7Qa<^Qxh^WWFB-D7+>`*QBjICXAdP%wD9 L`njxgN@xNASYeX@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/effortlessbuilding/textures/icons/diagonalwall.png b/src/main/resources/assets/effortlessbuilding/textures/icons/diagonalwall.png new file mode 100644 index 0000000000000000000000000000000000000000..ac20e48bf20f534a06a7d04078d27204430ec76a GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=DkxL735kHCP2G$X?><>&pI^iGztzPt`KuF;Hl#r;B5V#p$Dy4f&2J@UW;0&Nt*= z^dvvv(+m@Z&ob+}TAGRum~LOH+Q0Uzl$_8+HKkrx*;?g>RZIzMSr=TZ^3hbfbZ^U+ zi5*+!6mu))G@nafIK`=_P-4-l6|Wv#{JHHa7sr7!e>9gC#ERdmZeYv`J73zoOzzFA z{|v>;&stt*2=e;fV7F=af`?rDoAw>s)Bo$;cE9_7n71nRKiwPZ?g4ZlgQu&X%Q~lo FCIIloWV!$V literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/effortlessbuilding/textures/icons/floor.png b/src/main/resources/assets/effortlessbuilding/textures/icons/floor.png index bcb950c32993efc779265c957e08969ca04ba367..bcf4a2251e02f0a5e2258787f15b725d37a6ac16 100644 GIT binary patch delta 275 zcmV+u0qp*u0?PuBBo78+OGiWi{{a60|De66laV1He+U8rCtT&|M*si-*hxe|R5;6} zlRa{UAQVOq88-u^TXBZcb5Lc5)2`j zyt-doXo*TNr9?{Uv4t2T0K+iUX4DeQnWpI>$baKJ&ll0Y@3g?5T0-yqrB!3BTNLh0L01m$Z01m$aI0aKA00007bV*G`2jc<-0Sh7~Op?X` z006&9L_t(I%e9iR5rZ%cMV|>fumeZMD)g*^S;Yg+ieLF#f3zJ2;>n!NKP%QD7sB+v6h@jTC- zaak4snx^sg0D!h_0jR3VCcCclZgh?B^%6OR)|$TW(OL)dZae{uhI5&p+{XR@0000< KMNUMnLSTaY7j9Jm diff --git a/src/main/resources/assets/effortlessbuilding/textures/icons/line.png b/src/main/resources/assets/effortlessbuilding/textures/icons/line.png index 4a43a614b7c84c6edfa142f156af48ccd08bf678..8109177d478c5134daae90cc8ae23f88eaee0218 100644 GIT binary patch delta 190 zcmV;v073ub0rmlqBo78+OGiWi{{a60|De66laV1He+U8rB*pBx{Qv*}gGod|R5;7k zlQ9ZJAq+%cz{@11hxw&<(<>=@oNOn%i-ihX>{KD}CNNCkucWH3s{X!{T@ax64uF{f zFvbu$0l#Htgd4E6Hs^2)ei+<ylv0Q>Zh=dK6L8tE soU_+jBz@Jm>#F`-;=Vp8vh^ms0N0>UxrfspV*mgE07*qoM6N<$f^nczSO5S3 delta 199 zcmV;&0672l0pkIXB!3BTNLh0L01m%YC zmnX@61uUgJ@xBUn4ZeVl!2-y}Af*HV2q6qXcc-dCL|P{^dq65s)z=$q@YXi!g1Zv{ zMWhSYpLoCNsLwIRZ$={%YlFSfnef&tgb*&pKgmJUw(WnDm@hHLsEjcLfMFO;$;KD}K;QQ{P|ZBg0D!LR z5Mxv?;)l^*IF4gBRp~cQ)0B;hj;skYQY6deoWrs#aL%39%P2nq&mo*Dc*&rv00000 LNkvXXu0mjf;mmNW delta 265 zcmV+k0rvjA0;B?vB!3BTNLh0L01m$Z01m$aI0aKA00007bV*G`2jc<-0R}dSI5_qI z006^DL_t(I%e|994ul{KML!OA;0`XiihHjD9>pGrjU+Bvy5$C)jWQ@WIx(3hO=#i$ zrW6D-s?-lzC@UVr8r0MPe+0&_bnQd}Yt z74WZ9cs$1c3P`QB008G)b)3#QaqA%+g|5KU7FHplwXOmo1cVS${8CC`o@caeTO3}N zWe3I>0RYCBlo#7?9EJe^&~;tj|E^jNejYk=;nrGA(*$d6b$=X3-qvs2s(H@$(c(D( P0000F($N`E}2=KgnP=Ik90dUTd0~H|z z0P4Dqe>a-YpxgVKET{xH9M`-!r>W4w@|hzwNI7rpx-Po;$-yuT`A4)k9M_P5Ot?R7 zc)ESR42X~~OL*_upElWVTmd}Zofq#-*)$CRBC-guN(-0Vr1JxOTMQ9VfVOR8&3hlu yRaJ3qGb2buG=!ji->c<+o^P@6TG;vnd;%g?5_2|SCVgfA0000PSLL%8?D9J5>T3 zPq<{R2|Uig-um7`^ucF)W+1T164Q&}@V9Yub1PuowQE<8ie=`*L#_Yyzopr01)j|U;qFB diff --git a/src/main/resources/assets/effortlessbuilding/textures/icons/slopefloor.png b/src/main/resources/assets/effortlessbuilding/textures/icons/slopefloor.png new file mode 100644 index 0000000000000000000000000000000000000000..c786eafe685f6dc09f535329e06f4b7a1b2325d6 GIT binary patch literal 310 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=DkxL735kHCP2G$X?><>&pI^iGxXq@jbha22kj*r;B5V#p$h+4|28`2)M?JMF&c3 zXo^{*rW)Z|wL#qRjYH9fjwustU6agQ?xq&cHhBM8BJII^f0w3?mi3PBYd_ozcb+A~ z5^-I$p>kg5)@xQ4&qL%EWIZt8S)R7mw9-Ra=^@venHqwek1Z~3)2+QPesI=F!{*xi z{SE4B?T$76zETX?x`t2sPHxMclP1uuJz0ds;MfN*`!!pa7<(R+(R=53a>?sm{3j%s z8;bo_UQ%18nCZZEZ&z#PtV5f09zI{Z>gygxE786SbA-QD0lmZE>FVdQ&MBb@0JlnW AhyVZp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/effortlessbuilding/textures/icons/wall.png b/src/main/resources/assets/effortlessbuilding/textures/icons/wall.png index 093f9e57f46d904fd05abc70636e9800bb03e118..e40ab142eb7bf4a5be4d9fa4011a0de2308b104e 100644 GIT binary patch delta 253 zcmVd& zfSK`Y)O8J|6f31TJo_r0uX89eGjkY97DIeQV!_>>AbY|v3=9C%G$F<~j+?b4A~@%= z#WmpNV_b0!_z4jK0II4=5qOu8QR$NxlF-sZW|paf00000NkvXXu0mjf DKD}?S delta 269 zcmV+o0rLK}0;mFzB!3BTNLh0L01m$Z01m$aI0aKA00007bV*G`2jc<-04@uS&#-y` z0075HL_t(I%casG4#F@PhT*ql2_YdtAa?*v4ZlHihWVa=JM1p?J;OLbXJ&914uG60 zf^=bH49Y&){?C`TsR|*GkT|U3LiTC0y0icscgqeoP1Egbt$)W0zQJL#e_>Z(tp&gs zlLUJwFvcXq7!^XmS{plK}dj%jOZxEm?%kdL9=TuP?hzQ>MN!TkmUsp;5)`t^XZ>cUVB2PSqUh@D^bW(VQ TWvn3p0000