From be865d273c64a99c5ff79f041162b81cb8822b31 Mon Sep 17 00:00:00 2001 From: Christian Knaapen Date: Thu, 14 Feb 2019 02:02:22 +0100 Subject: [PATCH] Breaking shows preview (breaking only in creative). Build mode cancels when opposite mouse button is pressed (left button when placing, right button when breaking). Simple shader when placing more than 1500 blocks (or when useShaders is false). Added axis limits in addition to total block limit. Fixed placing on self (and being pushed). Fixed issue #15 silk touch, shearing leaves, dropping bed etc by using Block#harvestBlock (items dont drop directly to inventory anymore). Fixed randomizerbag not randomizing in buildmodes. --- .../effortlessbuilding/BuildConfig.java | 8 +- .../effortlessbuilding/EventHandler.java | 19 ++- .../buildmode/BuildModes.java | 62 +++++++-- .../effortlessbuilding/buildmode/Cube.java | 4 +- .../buildmode/DiagonalLine.java | 4 +- .../buildmode/DiagonalWall.java | 4 +- .../effortlessbuilding/buildmode/Floor.java | 16 ++- .../buildmode/IBuildMode.java | 4 +- .../effortlessbuilding/buildmode/Line.java | 20 ++- .../effortlessbuilding/buildmode/Normal.java | 4 +- .../buildmode/NormalPlus.java | 4 +- .../buildmode/SlopeFloor.java | 4 +- .../effortlessbuilding/buildmode/Wall.java | 26 ++-- .../buildmodifier/BuildModifiers.java | 16 ++- .../buildmodifier/Mirror.java | 5 +- .../ModifierSettingsManager.java | 15 +++ .../compatibility/CompatHelper.java | 1 - .../helper/ReachHelper.java | 8 +- .../helper/SurvivalHelper.java | 64 +++++---- .../effortlessbuilding/proxy/ClientProxy.java | 9 +- .../render/BlockPreviewRenderer.java | 122 +++++++++++++----- .../render/RenderHandler.java | 8 +- .../effortlessbuilding/shaders/dissolve.frag | 11 +- .../effortlessbuilding/shaders/dissolve.vert | 9 -- 24 files changed, 309 insertions(+), 138 deletions(-) diff --git a/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java b/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java index 5ea8858..1b452de 100644 --- a/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java +++ b/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java @@ -58,10 +58,14 @@ public class BuildConfig { @Comment({"Show a block preview if you have a block in hand on build mode Normal"}) public boolean alwaysShowBlockPreview = false; + @Comment({"How long the dissolve effect takes when placing blocks, in ticks."}) + public int dissolveTime = 40; + + @Comment({"Switch to using the simple performance shader when placing more than so many blocks."}) + public int shaderTreshold = 1500; + @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/EventHandler.java b/src/main/java/nl/requios/effortlessbuilding/EventHandler.java index 913e6f5..0928aa8 100644 --- a/src/main/java/nl/requios/effortlessbuilding/EventHandler.java +++ b/src/main/java/nl/requios/effortlessbuilding/EventHandler.java @@ -23,8 +23,10 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; +import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.capability.ModeCapabilityManager; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; +import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.network.BlockPlacedMessage; import nl.requios.effortlessbuilding.network.RequestLookAtMessage; @@ -83,22 +85,31 @@ public class EventHandler //Only called serverside public static void onBlockPlaced(BlockEvent.PlaceEvent event) { //Cancel event if necessary - BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode(); - if (buildMode != BuildModes.BuildModeEnum.Normal) { + EntityPlayer player = event.getPlayer(); + BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode(); + ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); + + if (buildMode != BuildModes.BuildModeEnum.Normal || modifierSettings.doQuickReplace()) { event.setCanceled(true); } else { + //Normal mode, let vanilla handle block placing + //But modifiers should still work + //Send message to client, which sends message back with raytrace info - EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(), (EntityPlayerMP) event.getPlayer()); + EffortlessBuilding.packetHandler.sendTo(new RequestLookAtMessage(), (EntityPlayerMP) player); } } @SubscribeEvent public static void onBlockBroken(BlockEvent.BreakEvent event) { //Cancel event if necessary + //If cant break far then dont cancel event ever BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode(); - if (buildMode != BuildModes.BuildModeEnum.Normal) { + if (buildMode != BuildModes.BuildModeEnum.Normal && ReachHelper.canBreakFar(event.getPlayer())) { event.setCanceled(true); } else { + //Normal mode, let vanilla handle block breaking + //But modifiers should still work BuildModes.onBlockBroken(event); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java index e0939e7..d6e013b 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java @@ -5,23 +5,26 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; import net.minecraftforge.event.world.BlockEvent; -import net.minecraftforge.fml.common.event.FMLInitializationEvent; -import net.minecraftforge.fml.relauncher.Side; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmodifier.*; import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.helper.ReachHelper; -import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.network.BlockBrokenMessage; import nl.requios.effortlessbuilding.network.BlockPlacedMessage; import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Hashtable; import java.util.List; public class BuildModes { + //Static variables are shared between client and server in singleplayer + //We need them separate + public static Dictionary currentlyBreakingClient = new Hashtable<>(); + public static Dictionary currentlyBreakingServer = new Hashtable<>(); + public enum BuildModeEnum { Normal ("Normal", new Normal()), NormalPlus ("Normal+", new NormalPlus()), @@ -47,6 +50,14 @@ public class BuildModes { //Raytraceresult is needed for sideHit and hitVec public static void onBlockPlacedMessage(EntityPlayer player, BlockPlacedMessage message) { + //Check if not in the middle of breaking + Dictionary currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; + if (currentlyBreaking.get(player) != null && currentlyBreaking.get(player)) { + //Cancel breaking + initializeMode(player); + return; + } + ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); BuildModeEnum buildMode = modeSettings.getBuildMode(); @@ -74,14 +85,20 @@ public class BuildModes { return; } } + //Even when no starting block is found, call buildmode instance //We might want to place things in the air - List posList = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec()); + List coordinates = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec(), modifierSettings.doQuickReplace()); + + if (coordinates.isEmpty()) { + currentlyBreaking.put(player, false); + return; + } //Limit number of blocks you can place int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); - if (posList.size() > limit) { - posList = posList.subList(0, limit); + if (coordinates.size() > limit) { + coordinates = coordinates.subList(0, limit); } EnumFacing sideHit = buildMode.instance.getSideHit(player); @@ -90,11 +107,14 @@ public class BuildModes { Vec3d hitVec = buildMode.instance.getHitVec(player); if (hitVec == null) hitVec = message.getHitVec(); - BuildModifiers.onBlockPlaced(player, posList, sideHit, hitVec); + BuildModifiers.onBlockPlaced(player, coordinates, sideHit, hitVec); + + //Only works when finishing a buildmode is equal to placing some blocks + //No intermediate blocks allowed + currentlyBreaking.remove(player); } - //Use a network message to break blocks in the distance using clientside mouse input public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) { BlockPos blockPos = message.getBlockPos(); @@ -108,31 +128,45 @@ public class BuildModes { } public static void onBlockBroken(BlockEvent.BreakEvent event) { - World world = event.getWorld(); EntityPlayer player = event.getPlayer(); BlockPos pos = event.getPos(); - if (world.isRemote) return; + //Check if not in the middle of placing + Dictionary currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; + if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) { + //Cancel placing + initializeMode(player); + return; + } //get coordinates ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); BuildModeEnum buildMode = modeSettings.getBuildMode(); - List coordinates = buildMode.instance.onRightClick(player, pos, EnumFacing.UP, Vec3d.ZERO); + List coordinates = buildMode.instance.onRightClick(player, pos, EnumFacing.UP, Vec3d.ZERO, true); + + if (coordinates.isEmpty()) { + currentlyBreaking.put(player, true); + return; + } //let buildmodifiers break blocks BuildModifiers.onBlockBroken(player, coordinates); } - public static List findCoordinates(EntityPlayer player, BlockPos startPos) { + public static List findCoordinates(EntityPlayer player, BlockPos startPos, boolean skipRaytrace) { List coordinates = new ArrayList<>(); ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); - coordinates.addAll(modeSettings.getBuildMode().instance.findCoordinates(player, startPos)); + coordinates.addAll(modeSettings.getBuildMode().instance.findCoordinates(player, startPos, skipRaytrace)); return coordinates; } public static void initializeMode(EntityPlayer player) { + //Resetting mode, so not placing or breaking + Dictionary currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; + currentlyBreaking.remove(player); + ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java index 0719dcc..29206f8 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Cube.java @@ -15,12 +15,12 @@ public class Cube implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { return new ArrayList<>(); } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { return new ArrayList<>(); } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java index c830c83..1823ad5 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalLine.java @@ -15,12 +15,12 @@ public class DiagonalLine implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { return new ArrayList<>(); } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { return new ArrayList<>(); } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java index aa9f6eb..5f25335 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/DiagonalWall.java @@ -15,12 +15,12 @@ public class DiagonalWall implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { return new ArrayList<>(); } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { return new ArrayList<>(); } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java index 014b12c..c038ca1 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Floor.java @@ -28,7 +28,7 @@ public class Floor implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { List list = new ArrayList<>(); Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; @@ -51,7 +51,7 @@ public class Floor implements IBuildMode { } else { //Second click, place wall - list = findCoordinates(player, blockPos); + list = findCoordinates(player, blockPos, skipRaytrace); rightClickTable.put(player.getUniqueID(), 0); } @@ -59,7 +59,7 @@ public class Floor implements IBuildMode { } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { List list = new ArrayList<>(); Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; int rightClickNr = rightClickTable.get(player.getUniqueID()); @@ -98,10 +98,12 @@ public class Floor implements IBuildMode { if (selected == null) return list; //check if it doesnt go through blocks - RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); - if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { - //return empty list - return list; + if (!skipRaytrace) { + RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); + if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { + //return empty list + return list; + } } BlockPos secondPos = new BlockPos(selected); diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/IBuildMode.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/IBuildMode.java index ba724e0..f455641 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/IBuildMode.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/IBuildMode.java @@ -14,10 +14,10 @@ public interface IBuildMode { //Fired when a block would be placed //Return a list of coordinates where you want to place blocks - List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec); + List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace); //Fired continuously for visualization purposes - List findCoordinates(EntityPlayer player, BlockPos blockPos); + List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace); EnumFacing getSideHit(EntityPlayer player); diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java index a8099c1..e2c88cd 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Line.java @@ -28,7 +28,7 @@ public class Line implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { List list = new ArrayList<>(); Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; @@ -51,7 +51,7 @@ public class Line implements IBuildMode { } else { //Second click, place wall - list = findCoordinates(player, blockPos); + list = findCoordinates(player, blockPos, skipRaytrace); rightClickTable.put(player.getUniqueID(), 0); } @@ -59,7 +59,7 @@ public class Line implements IBuildMode { } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { List list = new ArrayList<>(); Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; int rightClickNr = rightClickTable.get(player.getUniqueID()); @@ -155,25 +155,31 @@ public class Line implements IBuildMode { if (selected == null) return list; //check if it doesnt go through blocks - RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); - if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { - //return empty list - return list; + if (!skipRaytrace) { + RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); + if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { + //return empty list + return list; + } } BlockPos secondPos = new BlockPos(selected); + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + //Add whole line int x1 = firstPos.getX(), x2 = secondPos.getX(); int y1 = firstPos.getY(), y2 = secondPos.getY(); int z1 = firstPos.getZ(), z2 = secondPos.getZ(); + outerloop: for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { + if (list.size() >= axisLimit) break outerloop; list.add(new BlockPos(l, m, n)); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Normal.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Normal.java index 8fcfcee..f602376 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Normal.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Normal.java @@ -15,14 +15,14 @@ public class Normal implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { List list = new ArrayList<>(); list.add(blockPos); return list; } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { List list = new ArrayList<>(); list.add(blockPos); return list; diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/NormalPlus.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/NormalPlus.java index 7aaf1bb..f800bfb 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/NormalPlus.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/NormalPlus.java @@ -15,14 +15,14 @@ public class NormalPlus implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { List list = new ArrayList<>(); list.add(blockPos); return list; } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { List list = new ArrayList<>(); list.add(blockPos); return list; diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java index 77f93e3..b3c3d74 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/SlopeFloor.java @@ -15,12 +15,12 @@ public class SlopeFloor implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { return new ArrayList<>(); } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { return new ArrayList<>(); } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java index d5a4fee..c15b3a5 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/Wall.java @@ -5,7 +5,6 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; -import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.helper.ReachHelper; import java.util.*; @@ -29,7 +28,7 @@ public class Wall implements IBuildMode { } @Override - public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { + public List onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) { List list = new ArrayList<>(); Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; @@ -52,7 +51,7 @@ public class Wall implements IBuildMode { } else { //Second click, place wall - list = findCoordinates(player, blockPos); + list = findCoordinates(player, blockPos, skipRaytrace); rightClickTable.put(player.getUniqueID(), 0); } @@ -60,7 +59,7 @@ public class Wall implements IBuildMode { } @Override - public List findCoordinates(EntityPlayer player, BlockPos blockPos) { + public List findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) { List list = new ArrayList<>(); Dictionary rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; int rightClickNr = rightClickTable.get(player.getUniqueID()); @@ -123,10 +122,12 @@ public class Wall implements IBuildMode { if (selected == null) return list; //check if it doesnt go through blocks - RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); - if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { - //return empty list - return list; + if (!skipRaytrace) { + RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); + if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { + //return empty list + return list; + } } BlockPos secondPos = new BlockPos(selected); @@ -134,11 +135,20 @@ public class Wall implements IBuildMode { //Add whole wall //Limit amount of blocks you can place per row int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); int x1 = firstPos.getX(), x2 = secondPos.getX(); int y1 = firstPos.getY(), y2 = secondPos.getY(); int z1 = firstPos.getZ(), z2 = secondPos.getZ(); + //limit axis + if (x2 - x1 > axisLimit) x2 = x1 + axisLimit; + if (x1 - x2 > axisLimit) x2 = x1 - axisLimit; + if (y2 - y1 > axisLimit) y2 = y1 + axisLimit; + if (y1 - y2 > axisLimit) y2 = y1 - axisLimit; + if (z2 - z1 > axisLimit) z2 = z1 + axisLimit; + if (z1 - z2 > axisLimit) z2 = z1 - axisLimit; + for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java index d15e7b7..9cb6712 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java @@ -25,7 +25,7 @@ import java.util.List; public class BuildModifiers { //Called from BuildModes - public static void onBlockPlaced(EntityPlayer player, List posList, EnumFacing sideHit, Vec3d hitVec) { + public static void onBlockPlaced(EntityPlayer player, List startCoordinates, EnumFacing sideHit, Vec3d hitVec) { World world = player.world; ItemRandomizerBag.renewRandomness(); @@ -33,9 +33,9 @@ public class BuildModifiers { hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z))); //find coordinates and blockstates - List coordinates = findCoordinates(player, posList); + List coordinates = findCoordinates(player, startCoordinates); List itemStacks = new ArrayList<>(); - List blockStates = findBlockStates(player, posList, hitVec, sideHit, itemStacks); + List blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); //check if valid blockstates if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return; @@ -54,7 +54,7 @@ public class BuildModifiers { if (world.isBlockLoaded(blockPos, true)) { //check itemstack empty if (itemStack.isEmpty()) continue; - SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, true, false); + SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false); } } @@ -67,6 +67,11 @@ public class BuildModifiers { if (coordinates.isEmpty()) return; + if (world.isRemote) { + BlockPreviewRenderer.onBlocksBroken(); + return; + } + //If the player is going to instabreak grass or a plant, only break other instabreaking things boolean onlyInstaBreaking = world.getBlockState(posList.get(0)).getBlockHardness(world, posList.get(0)) == 0f; @@ -122,10 +127,11 @@ public class BuildModifiers { ItemStack itemBlock = ItemStack.EMPTY; if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack; else itemBlock = CompatHelper.getItemBlockFromStack(itemStack); + ItemRandomizerBag.resetRandomness(); //Add blocks in posList first for (BlockPos blockPos : posList) { - //if (itemStack.getItem() instanceof ItemRandomizerBag) itemBlock = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack)); + if (!(itemStack.getItem() instanceof ItemBlock)) itemBlock = CompatHelper.getItemBlockFromStack(itemStack); IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND); blockStates.add(blockState); itemStacks.add(itemBlock); diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/Mirror.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/Mirror.java index 5b8b9b3..34a9b21 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/Mirror.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/Mirror.java @@ -41,7 +41,7 @@ public class Mirror { } public int getReach() { - return radius * 2; + return radius * 2; //Change ModifierSettings#setReachUpgrade too } } @@ -114,8 +114,7 @@ public class Mirror { //Randomizer bag synergy if (bagInventory != null) { itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); - oldBlockState = BuildModifiers - .getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand); + oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand); } //Find blockstate diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/ModifierSettingsManager.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/ModifierSettingsManager.java index 46f3c56..d5bfe3d 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/ModifierSettingsManager.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/ModifierSettingsManager.java @@ -5,6 +5,7 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.helper.ReachHelper; @@ -161,6 +162,20 @@ public class ModifierSettingsManager { public void setReachUpgrade(int reachUpgrade) { this.reachUpgrade = reachUpgrade; + //Set mirror radius to max + int reach = 10; + switch (reachUpgrade) { + case 0: reach = BuildConfig.reach.maxReachLevel0; break; + case 1: reach = BuildConfig.reach.maxReachLevel1; break; + case 2: reach = BuildConfig.reach.maxReachLevel2; break; + case 3: reach = BuildConfig.reach.maxReachLevel3; break; + } + + if (this.mirrorSettings != null) + this.mirrorSettings.radius = reach / 2; + if (this.radialMirrorSettings != null) + this.radialMirrorSettings.radius = reach / 2; + } } diff --git a/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java b/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java index ca05445..d7273dc 100644 --- a/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java @@ -49,7 +49,6 @@ public class CompatHelper { public static ItemStack getItemBlockFromStack(ItemStack stack) { Item item = stack.getItem(); if(item instanceof ItemRandomizerBag) { - ItemRandomizerBag.resetRandomness(); return ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(stack)); } else if(item == dankNullItem) { int index = 0; diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/ReachHelper.java b/src/main/java/nl/requios/effortlessbuilding/helper/ReachHelper.java index 46d4944..e350a53 100644 --- a/src/main/java/nl/requios/effortlessbuilding/helper/ReachHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/helper/ReachHelper.java @@ -1,6 +1,7 @@ package nl.requios.effortlessbuilding.helper; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.math.MathHelper; import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; @@ -27,7 +28,12 @@ public class ReachHelper { public static int getMaxBlocksPlacedAtOnce(EntityPlayer player) { if (player.isCreative()) return 1000000; - return getMaxReach(player) / 2; + return getMaxReach(player) * 5; + } + + public static int getMaxBlocksPerAxis(EntityPlayer player) { + if (player.isCreative()) return 2000; + return MathHelper.ceil(MathHelper.sqrt(getMaxReach(player))); } public static boolean canBreakFar(EntityPlayer player) { diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java b/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java index d284f21..ca29a30 100644 --- a/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java @@ -10,8 +10,10 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Enchantments; +import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; +import net.minecraft.stats.StatList; import net.minecraft.util.EnumFacing; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; @@ -26,6 +28,7 @@ import nl.requios.effortlessbuilding.compatibility.CompatHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.List; public class SurvivalHelper { @@ -49,24 +52,12 @@ public class SurvivalHelper { if (canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) { //Drop existing block - //TODO check if can replace dropBlock(world, player, pos); boolean placed = ((ItemBlock) itemstack.getItem()).placeBlockAt(itemstack, player, world, pos, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, blockState); if (!placed) return false; -// //From ItemBlock#placeBlockAt -// if (!world.setBlockState(pos, blockState, 11)) return false; -// IBlockState afterState = world.getBlockState(pos); -// if (afterState.getBlock() == block) -// { -// ((ItemBlock) itemstack.getItem()).setTileEntityNBT(world, player, pos, itemstack); -// block.onBlockPlacedBy(world, pos, afterState, player, itemstack); -// -//// if (player instanceof EntityPlayerMP) -//// CriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP)player, pos, itemstack); -// } if (playSound) { SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player); @@ -90,6 +81,9 @@ public class SurvivalHelper { //Check if can break if (canBreak(world, player, pos)) { + player.addStat(StatList.getBlockStats(world.getBlockState(pos).getBlock())); + player.addExhaustion(0.005F); + //Drop existing block dropBlock(world, player, pos); @@ -107,13 +101,38 @@ public class SurvivalHelper { if (player.isCreative()) return; IBlockState blockState = world.getBlockState(pos); + Block block = blockState.getBlock(); - 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); - } + block.harvestBlock(world, player, pos, blockState, world.getTileEntity(pos), player.getHeldItemMainhand()); + + //TODO drop items in inventory instead of world + +// List drops = new ArrayList<>(); +// +// //From Block#harvestBlock +// int silktouch = EnchantmentHelper.getEnchantmentLevel(Enchantments.SILK_TOUCH, player.getHeldItemMainhand()); +// if (block.canSilkHarvest(world, pos, blockState, player) && silktouch > 0) { +// +// //From Block#getSilkTouchDrop (protected) +// Item item = Item.getItemFromBlock(block); +// int i = 0; +// +// if (item.getHasSubtypes()) +// { +// i = block.getMetaFromState(blockState); +// } +// +// drops.add(new ItemStack(item, 1, i)); +// +// net.minecraftforge.event.ForgeEventFactory.fireBlockHarvesting(drops, world, pos, blockState, 0, 1.0f, true, player); +// } +// +// int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand()); +// drops.addAll(block.getDrops(world, pos, blockState, fortune)); +// for (ItemStack drop : drops) +// { +// ItemHandlerHelper.giveItemToPlayer(player, drop); +// } } /** @@ -132,8 +151,9 @@ public class SurvivalHelper { //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()); +// EffortlessBuilding.log(player, "Cannot (re)place block", true); +// EffortlessBuilding.log("SurvivalHelper#canPlace: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString()); + //Happens when breaking blocks, no need to notify in that case return false; } @@ -175,9 +195,9 @@ public class SurvivalHelper { 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); + AxisAlignedBB axisalignedbb = skipCollisionCheck ? Block.NULL_AABB : blockIn.getDefaultState().getCollisionBoundingBox(world, pos); - if (axisalignedbb != Block.NULL_AABB && !world.checkNoEntityCollision(axisalignedbb.offset(pos), placer)) + if (axisalignedbb != Block.NULL_AABB && !world.checkNoEntityCollision(axisalignedbb.offset(pos))) { return false; } diff --git a/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java b/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java index ca210ca..2bfbf9b 100644 --- a/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java +++ b/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java @@ -186,11 +186,12 @@ public class ClientProxy implements IProxy { if (breakCooldown <= 0) { breakCooldown = 6; RayTraceResult lookingAt = getLookingAt(player); - if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) { - BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage(lookingAt)); - EffortlessBuilding.packetHandler.sendToServer(new BlockBrokenMessage(lookingAt)); - //play sound + BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage(lookingAt)); + EffortlessBuilding.packetHandler.sendToServer(new BlockBrokenMessage(lookingAt)); + + //play sound + if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) { BlockPos blockPos = lookingAt.getBlockPos(); IBlockState state = player.world.getBlockState(blockPos); SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player); diff --git a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java index a5e8f4d..ee3e3c3 100644 --- a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java +++ b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java @@ -55,14 +55,17 @@ public class BlockPreviewRenderer { List itemStacks; BlockPos firstPos; BlockPos secondPos; + boolean breaking; - public 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, boolean breaking) { this.time = time; this.coordinates = coordinates; this.blockStates = blockStates; this.itemStacks = itemStacks; this.firstPos = firstPos; this.secondPos = secondPos; + this.breaking = breaking; } } @@ -73,17 +76,18 @@ public class BlockPreviewRenderer { public static void render(EntityPlayer player, ModifierSettings modifierSettings, 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()) { + //Use fancy shader if config allows, otherwise no dissolve + if (BuildConfig.visuals.useShaders) { + RenderHandler.beginBlockPreviews(); + 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(); + float dissolve = (ClientProxy.ticksInGame - placed.time) / (float) BuildConfig.visuals.dissolveTime; + renderBlockPreviews(placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking); + } } + RenderHandler.endBlockPreviews(); } //Expire placedDataList.removeIf(placed -> placed.time + BuildConfig.visuals.dissolveTime < ClientProxy.ticksInGame); @@ -122,16 +126,17 @@ public class BlockPreviewRenderer { //Unless alwaysShowBlockPreview is true in config if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) { - 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) { + //Should be red? + boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player); + //get coordinates - List startCoordinates = BuildModes.findCoordinates(player, startPos); + List startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace()); BlockPos firstPos = BlockPos.ORIGIN, secondPos = BlockPos.ORIGIN; //Remember first and last pos for the shader @@ -157,8 +162,19 @@ public class BlockPreviewRenderer { hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z))); + + //Get blockstates List itemStacks = new ArrayList<>(); - List blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); + List blockStates = new ArrayList<>(); + if (breaking) { + //Find blockstate of world + for (BlockPos coordinate : newCoordinates) { + blockStates.add(player.world.getBlockState(coordinate)); + } + } else { + blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); + } + //Check if they are different from previous //TODO fix triggering when moving player @@ -173,7 +189,7 @@ public class BlockPreviewRenderer { //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) { + if (startCoordinates.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, @@ -183,12 +199,30 @@ public class BlockPreviewRenderer { //Render block previews if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) { - renderBlockPreviews(newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, true); + //Use fancy shader if config allows, otherwise outlines + if (BuildConfig.visuals.useShaders && newCoordinates.size() < BuildConfig.visuals.shaderTreshold) { + + RenderHandler.beginBlockPreviews(); + + renderBlockPreviews(newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking); + + RenderHandler.endBlockPreviews(); + } else { + + RenderHandler.beginLines(); + + Vec3d color = new Vec3d(1f, 1f, 1f); + if (breaking) color = new Vec3d(1f, 0f, 0f); + + for (int i = newCoordinates.size() - 1; i >= 0; i--) { + RenderHandler.renderBlockOutline(newCoordinates.get(i), color); + } + + RenderHandler.endLines(); + } } } - RenderHandler.endBlockPreviews(); - RenderHandler.beginLines(); //Draw outlines if tool in hand //Find proper raytrace: either normal range or increased range depending on canBreakFar @@ -205,7 +239,7 @@ public class BlockPreviewRenderer { 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.renderBlockOutline(coordinate, new Vec3d(0f, 0f, 0f)); } } } @@ -214,6 +248,7 @@ public class BlockPreviewRenderer { } } + //Whether to draw any block previews or outlines public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) { return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.Normal || (startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) || @@ -222,8 +257,9 @@ public class BlockPreviewRenderer { protected static void renderBlockPreviews(List coordinates, List blockStates, List itemStacks, float dissolve, BlockPos firstPos, - BlockPos secondPos, boolean checkCanPlace) { + BlockPos secondPos, boolean checkCanPlace, boolean red) { EntityPlayer player = Minecraft.getMinecraft().player; + ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); if (coordinates.isEmpty()) return; @@ -231,22 +267,21 @@ public class BlockPreviewRenderer { for (int i = coordinates.size() - 1; i >= 0; i--) { BlockPos blockPos = coordinates.get(i); IBlockState blockState = blockStates.get(i); - ItemStack itemstack = itemStacks.get(i); - if(CompatHelper.isItemBlockProxy(itemstack)) + ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i); + if (CompatHelper.isItemBlockProxy(itemstack)) itemstack = CompatHelper.getItemBlockByState(itemstack, blockState); //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)) { + if ((!checkCanPlace /*&& player.world.getBlockState(blockPos) == blockState*/) || + SurvivalHelper.canPlace(player.world, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), EnumFacing.UP)) { ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve, new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos), - blockPos == secondPos)); + blockPos == secondPos, red)); RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState); } } - } public static void onBlocksPlaced() { @@ -256,18 +291,45 @@ public class BlockPreviewRenderer { //Check if block previews are enabled if (doRenderBlockPreviews(modifierSettings, modeSettings, previousFirstPos)) { + //Save current coordinates, blockstates and itemstacks - placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates, - previousItemStacks, previousFirstPos, previousSecondPos)); + if (!previousCoordinates.isEmpty() && previousBlockStates.size() == previousCoordinates.size() && + previousCoordinates.size() < BuildConfig.visuals.shaderTreshold) { + + placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates, + previousItemStacks, previousFirstPos, previousSecondPos, false)); + } } } - private static Consumer generateShaderCallback(final float dissolve, final Vec3d blockpos, final Vec3d firstpos, final Vec3d secondpos, final boolean highlight) { + public static void onBlocksBroken() { + EntityPlayerSP player = Minecraft.getMinecraft().player; + ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); + ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); + + //Check if block previews are enabled + if (doRenderBlockPreviews(modifierSettings, modeSettings, previousFirstPos)) { + + //Save current coordinates, blockstates and itemstacks + if (!previousCoordinates.isEmpty() && previousBlockStates.size() == previousCoordinates.size() && + previousCoordinates.size() < BuildConfig.visuals.shaderTreshold) { + + placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates, + previousItemStacks, previousFirstPos, previousSecondPos, true)); + } + } + + } + + private static Consumer generateShaderCallback(final float dissolve, final Vec3d blockpos, + final Vec3d firstpos, final Vec3d secondpos, + final boolean highlight, final boolean red) { Minecraft mc = Minecraft.getMinecraft(); return (Integer shader) -> { int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "dissolve"); int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight"); + int redUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "red"); int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos"); int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos"); int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos"); @@ -298,6 +360,8 @@ public class BlockPreviewRenderer { ARBShaderObjects.glUniform1fARB(percentileUniform, dissolve); //highlight ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0); + //red + ARBShaderObjects.glUniform1iARB(redUniform, red ? 1 : 0); }; } } diff --git a/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java b/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java index 3293ddb..816439f 100644 --- a/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java +++ b/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java @@ -200,17 +200,17 @@ public class RenderHandler implements IWorldEventListener { GlStateManager.popMatrix(); } - protected static void renderBlockOutline(BlockPos pos) { - renderBlockOutline(pos, pos); + protected static void renderBlockOutline(BlockPos pos, Vec3d color) { + renderBlockOutline(pos, pos, color); } //Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z - protected static void renderBlockOutline(BlockPos pos1, BlockPos pos2) { + protected static void renderBlockOutline(BlockPos pos1, BlockPos pos2, Vec3d color) { GL11.glLineWidth(2); AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026); - RenderGlobal.drawSelectionBoundingBox(aabb, 0f, 0f, 0f, 0.4f); + RenderGlobal.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f); } diff --git a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag index 1a34ca8..7377da6 100644 --- a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag +++ b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.frag @@ -4,6 +4,7 @@ uniform int time; // Passed in, see ShaderHelper.java uniform float dissolve; // Passed in via Callback uniform int highlight; +uniform int red; uniform vec3 blockpos; uniform vec3 firstpos; uniform vec3 secondpos; @@ -87,10 +88,12 @@ void main() { color.rgb -= 0.05; - if(highlight == 1 && dissolve == 0.0) { - color.r += 0.0; - color.g += 0.1; - color.b -= 0.2; + if (highlight == 1 && dissolve == 0.0) { + color.rgb += vec3(0.0, 0.1, -0.2); + } + + if (red == 1) { + color.rgb += vec3(0.4, -0.3, -0.5); } color.r = max(0, min(1, color.r)); diff --git a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.vert b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.vert index f147aa0..c3975f6 100644 --- a/src/main/resources/assets/effortlessbuilding/shaders/dissolve.vert +++ b/src/main/resources/assets/effortlessbuilding/shaders/dissolve.vert @@ -1,14 +1,5 @@ #version 120 -uniform int time; // Passed in, see ShaderHelper.java - -uniform float dissolve; // Passed in via Callback -uniform int highlight; -uniform vec3 blockpos; -uniform vec3 firstpos; -uniform vec3 secondpos; -uniform sampler2D mask; - varying vec4 position; varying vec3 normal;