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.
This commit is contained in:
Christian Knaapen
2019-02-14 02:02:22 +01:00
parent e1c23a5bec
commit be865d273c
24 changed files with 309 additions and 138 deletions

View File

@@ -58,10 +58,14 @@ public class BuildConfig {
@Comment({"Show a block preview if you have a block in hand on build mode Normal"}) @Comment({"Show a block preview if you have a block in hand on build mode Normal"})
public boolean alwaysShowBlockPreview = false; 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"}) @Comment({"Use fancy shaders while placing blocks"})
public boolean useShaders = true; public boolean useShaders = true;
@Comment({"How long the dissolve effect takes when placing blocks, in ticks."})
public int dissolveTime = 60;
} }
} }

View File

@@ -23,8 +23,10 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager; import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage; import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.network.RequestLookAtMessage; import nl.requios.effortlessbuilding.network.RequestLookAtMessage;
@@ -83,22 +85,31 @@ public class EventHandler
//Only called serverside //Only called serverside
public static void onBlockPlaced(BlockEvent.PlaceEvent event) { public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
//Cancel event if necessary //Cancel event if necessary
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode(); EntityPlayer player = event.getPlayer();
if (buildMode != BuildModes.BuildModeEnum.Normal) { BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.Normal || modifierSettings.doQuickReplace()) {
event.setCanceled(true); event.setCanceled(true);
} else { } else {
//Normal mode, let vanilla handle block placing
//But modifiers should still work
//Send message to client, which sends message back with raytrace info //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 @SubscribeEvent
public static void onBlockBroken(BlockEvent.BreakEvent event) { public static void onBlockBroken(BlockEvent.BreakEvent event) {
//Cancel event if necessary //Cancel event if necessary
//If cant break far then dont cancel event ever
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode(); 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); event.setCanceled(true);
} else { } else {
//Normal mode, let vanilla handle block breaking
//But modifiers should still work
BuildModes.onBlockBroken(event); BuildModes.onBlockBroken(event);
} }
} }

View File

@@ -5,23 +5,26 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent; 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.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.*; import nl.requios.effortlessbuilding.buildmodifier.*;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage; import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage; import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List; import java.util.List;
public class BuildModes { public class BuildModes {
//Static variables are shared between client and server in singleplayer
//We need them separate
public static Dictionary<EntityPlayer, Boolean> currentlyBreakingClient = new Hashtable<>();
public static Dictionary<EntityPlayer, Boolean> currentlyBreakingServer = new Hashtable<>();
public enum BuildModeEnum { public enum BuildModeEnum {
Normal ("Normal", new Normal()), Normal ("Normal", new Normal()),
NormalPlus ("Normal+", new NormalPlus()), NormalPlus ("Normal+", new NormalPlus()),
@@ -47,6 +50,14 @@ public class BuildModes {
//Raytraceresult is needed for sideHit and hitVec //Raytraceresult is needed for sideHit and hitVec
public static void onBlockPlacedMessage(EntityPlayer player, BlockPlacedMessage message) { public static void onBlockPlacedMessage(EntityPlayer player, BlockPlacedMessage message) {
//Check if not in the middle of breaking
Dictionary<EntityPlayer, Boolean> 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); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
BuildModeEnum buildMode = modeSettings.getBuildMode(); BuildModeEnum buildMode = modeSettings.getBuildMode();
@@ -74,14 +85,20 @@ public class BuildModes {
return; return;
} }
} }
//Even when no starting block is found, call buildmode instance //Even when no starting block is found, call buildmode instance
//We might want to place things in the air //We might want to place things in the air
List<BlockPos> posList = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec()); List<BlockPos> 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 //Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (posList.size() > limit) { if (coordinates.size() > limit) {
posList = posList.subList(0, limit); coordinates = coordinates.subList(0, limit);
} }
EnumFacing sideHit = buildMode.instance.getSideHit(player); EnumFacing sideHit = buildMode.instance.getSideHit(player);
@@ -90,11 +107,14 @@ public class BuildModes {
Vec3d hitVec = buildMode.instance.getHitVec(player); Vec3d hitVec = buildMode.instance.getHitVec(player);
if (hitVec == null) hitVec = message.getHitVec(); 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 //Use a network message to break blocks in the distance using clientside mouse input
public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) { public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) {
BlockPos blockPos = message.getBlockPos(); BlockPos blockPos = message.getBlockPos();
@@ -108,31 +128,45 @@ public class BuildModes {
} }
public static void onBlockBroken(BlockEvent.BreakEvent event) { public static void onBlockBroken(BlockEvent.BreakEvent event) {
World world = event.getWorld();
EntityPlayer player = event.getPlayer(); EntityPlayer player = event.getPlayer();
BlockPos pos = event.getPos(); BlockPos pos = event.getPos();
if (world.isRemote) return; //Check if not in the middle of placing
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) {
//Cancel placing
initializeMode(player);
return;
}
//get coordinates //get coordinates
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
BuildModeEnum buildMode = modeSettings.getBuildMode(); BuildModeEnum buildMode = modeSettings.getBuildMode();
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, pos, EnumFacing.UP, Vec3d.ZERO); List<BlockPos> coordinates = buildMode.instance.onRightClick(player, pos, EnumFacing.UP, Vec3d.ZERO, true);
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, true);
return;
}
//let buildmodifiers break blocks //let buildmodifiers break blocks
BuildModifiers.onBlockBroken(player, coordinates); BuildModifiers.onBlockBroken(player, coordinates);
} }
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) { public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos, boolean skipRaytrace) {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockPos> coordinates = new ArrayList<>();
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); 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; return coordinates;
} }
public static void initializeMode(EntityPlayer player) { public static void initializeMode(EntityPlayer player) {
//Resetting mode, so not placing or breaking
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
currentlyBreaking.remove(player);
ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player); ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player);
} }
} }

View File

@@ -15,12 +15,12 @@ public class Cube implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
return new ArrayList<>(); return new ArrayList<>();
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
return new ArrayList<>(); return new ArrayList<>();
} }

View File

@@ -15,12 +15,12 @@ public class DiagonalLine implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
return new ArrayList<>(); return new ArrayList<>();
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
return new ArrayList<>(); return new ArrayList<>();
} }

View File

@@ -15,12 +15,12 @@ public class DiagonalWall implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
return new ArrayList<>(); return new ArrayList<>();
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
return new ArrayList<>(); return new ArrayList<>();
} }

View File

@@ -28,7 +28,7 @@ public class Floor implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
@@ -51,7 +51,7 @@ public class Floor implements IBuildMode {
} else { } else {
//Second click, place wall //Second click, place wall
list = findCoordinates(player, blockPos); list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0); rightClickTable.put(player.getUniqueID(), 0);
} }
@@ -59,7 +59,7 @@ public class Floor implements IBuildMode {
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID()); int rightClickNr = rightClickTable.get(player.getUniqueID());
@@ -98,10 +98,12 @@ public class Floor implements IBuildMode {
if (selected == null) return list; if (selected == null) return list;
//check if it doesnt go through blocks //check if it doesnt go through blocks
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); if (!skipRaytrace) {
if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false);
//return empty list if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) {
return list; //return empty list
return list;
}
} }
BlockPos secondPos = new BlockPos(selected); BlockPos secondPos = new BlockPos(selected);

View File

@@ -14,10 +14,10 @@ public interface IBuildMode {
//Fired when a block would be placed //Fired when a block would be placed
//Return a list of coordinates where you want to place blocks //Return a list of coordinates where you want to place blocks
List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec); List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace);
//Fired continuously for visualization purposes //Fired continuously for visualization purposes
List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos); List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace);
EnumFacing getSideHit(EntityPlayer player); EnumFacing getSideHit(EntityPlayer player);

View File

@@ -28,7 +28,7 @@ public class Line implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
@@ -51,7 +51,7 @@ public class Line implements IBuildMode {
} else { } else {
//Second click, place wall //Second click, place wall
list = findCoordinates(player, blockPos); list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0); rightClickTable.put(player.getUniqueID(), 0);
} }
@@ -59,7 +59,7 @@ public class Line implements IBuildMode {
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID()); int rightClickNr = rightClickTable.get(player.getUniqueID());
@@ -155,25 +155,31 @@ public class Line implements IBuildMode {
if (selected == null) return list; if (selected == null) return list;
//check if it doesnt go through blocks //check if it doesnt go through blocks
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); if (!skipRaytrace) {
if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false);
//return empty list if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) {
return list; //return empty list
return list;
}
} }
BlockPos secondPos = new BlockPos(selected); BlockPos secondPos = new BlockPos(selected);
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
//Add whole line //Add whole line
int x1 = firstPos.getX(), x2 = secondPos.getX(); int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY(); int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ(); 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 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 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) { for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
if (list.size() >= axisLimit) break outerloop;
list.add(new BlockPos(l, m, n)); list.add(new BlockPos(l, m, n));
} }
} }

View File

@@ -15,14 +15,14 @@ public class Normal implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
list.add(blockPos); list.add(blockPos);
return list; return list;
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
list.add(blockPos); list.add(blockPos);
return list; return list;

View File

@@ -15,14 +15,14 @@ public class NormalPlus implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
list.add(blockPos); list.add(blockPos);
return list; return list;
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
list.add(blockPos); list.add(blockPos);
return list; return list;

View File

@@ -15,12 +15,12 @@ public class SlopeFloor implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
return new ArrayList<>(); return new ArrayList<>();
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
return new ArrayList<>(); return new ArrayList<>();
} }

View File

@@ -5,7 +5,6 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*; import java.util.*;
@@ -29,7 +28,7 @@ public class Wall implements IBuildMode {
} }
@Override @Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) { public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
@@ -52,7 +51,7 @@ public class Wall implements IBuildMode {
} else { } else {
//Second click, place wall //Second click, place wall
list = findCoordinates(player, blockPos); list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0); rightClickTable.put(player.getUniqueID(), 0);
} }
@@ -60,7 +59,7 @@ public class Wall implements IBuildMode {
} }
@Override @Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) { public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID()); int rightClickNr = rightClickTable.get(player.getUniqueID());
@@ -123,10 +122,12 @@ public class Wall implements IBuildMode {
if (selected == null) return list; if (selected == null) return list;
//check if it doesnt go through blocks //check if it doesnt go through blocks
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false); if (!skipRaytrace) {
if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, selected, false, true, false);
//return empty list if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) {
return list; //return empty list
return list;
}
} }
BlockPos secondPos = new BlockPos(selected); BlockPos secondPos = new BlockPos(selected);
@@ -134,11 +135,20 @@ public class Wall implements IBuildMode {
//Add whole wall //Add whole wall
//Limit amount of blocks you can place per row //Limit amount of blocks you can place per row
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
int x1 = firstPos.getX(), x2 = secondPos.getX(); int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY(); int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ(); 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 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 n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {

View File

@@ -25,7 +25,7 @@ import java.util.List;
public class BuildModifiers { public class BuildModifiers {
//Called from BuildModes //Called from BuildModes
public static void onBlockPlaced(EntityPlayer player, List<BlockPos> posList, EnumFacing sideHit, Vec3d hitVec) { public static void onBlockPlaced(EntityPlayer player, List<BlockPos> startCoordinates, EnumFacing sideHit, Vec3d hitVec) {
World world = player.world; World world = player.world;
ItemRandomizerBag.renewRandomness(); 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))); 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 //find coordinates and blockstates
List<BlockPos> coordinates = findCoordinates(player, posList); List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
List<ItemStack> itemStacks = new ArrayList<>(); List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = findBlockStates(player, posList, hitVec, sideHit, itemStacks); List<IBlockState> blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
//check if valid blockstates //check if valid blockstates
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return; if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
@@ -54,7 +54,7 @@ public class BuildModifiers {
if (world.isBlockLoaded(blockPos, true)) { if (world.isBlockLoaded(blockPos, true)) {
//check itemstack empty //check itemstack empty
if (itemStack.isEmpty()) continue; 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 (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 //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; boolean onlyInstaBreaking = world.getBlockState(posList.get(0)).getBlockHardness(world, posList.get(0)) == 0f;
@@ -122,10 +127,11 @@ public class BuildModifiers {
ItemStack itemBlock = ItemStack.EMPTY; ItemStack itemBlock = ItemStack.EMPTY;
if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack; if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack;
else itemBlock = CompatHelper.getItemBlockFromStack(itemStack); else itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
ItemRandomizerBag.resetRandomness();
//Add blocks in posList first //Add blocks in posList first
for (BlockPos blockPos : posList) { 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); IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND);
blockStates.add(blockState); blockStates.add(blockState);
itemStacks.add(itemBlock); itemStacks.add(itemBlock);

View File

@@ -41,7 +41,7 @@ public class Mirror {
} }
public int getReach() { public int getReach() {
return radius * 2; return radius * 2; //Change ModifierSettings#setReachUpgrade too
} }
} }
@@ -114,8 +114,7 @@ public class Mirror {
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
oldBlockState = BuildModifiers oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
.getBlockStateFromItem(itemStack, player, oldBlockPos, EnumFacing.UP, new Vec3d(0, 0, 0), hand);
} }
//Find blockstate //Find blockstate

View File

@@ -5,6 +5,7 @@ import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
@@ -161,6 +162,20 @@ public class ModifierSettingsManager {
public void setReachUpgrade(int reachUpgrade) { public void setReachUpgrade(int reachUpgrade) {
this.reachUpgrade = 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;
} }
} }

View File

@@ -49,7 +49,6 @@ public class CompatHelper {
public static ItemStack getItemBlockFromStack(ItemStack stack) { public static ItemStack getItemBlockFromStack(ItemStack stack) {
Item item = stack.getItem(); Item item = stack.getItem();
if(item instanceof ItemRandomizerBag) { if(item instanceof ItemRandomizerBag) {
ItemRandomizerBag.resetRandomness();
return ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(stack)); return ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(stack));
} else if(item == dankNullItem) { } else if(item == dankNullItem) {
int index = 0; int index = 0;

View File

@@ -1,6 +1,7 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.MathHelper;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
@@ -27,7 +28,12 @@ public class ReachHelper {
public static int getMaxBlocksPlacedAtOnce(EntityPlayer player) { public static int getMaxBlocksPlacedAtOnce(EntityPlayer player) {
if (player.isCreative()) return 1000000; 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) { public static boolean canBreakFar(EntityPlayer player) {

View File

@@ -10,8 +10,10 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.init.Enchantments; import net.minecraft.init.Enchantments;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.stats.StatList;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
@@ -26,6 +28,7 @@ import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class SurvivalHelper { public class SurvivalHelper {
@@ -49,24 +52,12 @@ public class SurvivalHelper {
if (canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) { if (canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) {
//Drop existing block //Drop existing block
//TODO check if can replace
dropBlock(world, player, pos); 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); 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; if (!placed) return false;
// //From ItemBlock#placeBlockAt
// if (!world.setBlockState(pos, blockState, 11)) return false;
//
IBlockState afterState = world.getBlockState(pos); 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) { if (playSound) {
SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player); SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player);
@@ -90,6 +81,9 @@ public class SurvivalHelper {
//Check if can break //Check if can break
if (canBreak(world, player, pos)) if (canBreak(world, player, pos))
{ {
player.addStat(StatList.getBlockStats(world.getBlockState(pos).getBlock()));
player.addExhaustion(0.005F);
//Drop existing block //Drop existing block
dropBlock(world, player, pos); dropBlock(world, player, pos);
@@ -107,13 +101,38 @@ public class SurvivalHelper {
if (player.isCreative()) return; if (player.isCreative()) return;
IBlockState blockState = world.getBlockState(pos); IBlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock();
int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand()); block.harvestBlock(world, player, pos, blockState, world.getTileEntity(pos), player.getHeldItemMainhand());
List<ItemStack> drops = blockState.getBlock().getDrops(world, pos, blockState, fortune);
for (ItemStack drop : drops) //TODO drop items in inventory instead of world
{
ItemHandlerHelper.giveItemToPlayer(player, drop); // List<ItemStack> 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 //Check if itemstack is correct
if (!(itemStack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemStack.getItem()) != newBlockState.getBlock()) { if (!(itemStack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemStack.getItem()) != newBlockState.getBlock()) {
EffortlessBuilding.log(player, "Cannot (re)place block", true); // EffortlessBuilding.log(player, "Cannot (re)place block", true);
EffortlessBuilding.log("SurvivalHelper#placeBlock: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString()); // 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; 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) private static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer)
{ {
IBlockState iblockstate1 = world.getBlockState(pos); 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; return false;
} }

View File

@@ -186,11 +186,12 @@ public class ClientProxy implements IProxy {
if (breakCooldown <= 0) { if (breakCooldown <= 0) {
breakCooldown = 6; breakCooldown = 6;
RayTraceResult lookingAt = getLookingAt(player); 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(); BlockPos blockPos = lookingAt.getBlockPos();
IBlockState state = player.world.getBlockState(blockPos); IBlockState state = player.world.getBlockState(blockPos);
SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player); SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);

View File

@@ -55,14 +55,17 @@ public class BlockPreviewRenderer {
List<ItemStack> itemStacks; List<ItemStack> itemStacks;
BlockPos firstPos; BlockPos firstPos;
BlockPos secondPos; BlockPos secondPos;
boolean breaking;
public PlacedData(float time, List<BlockPos> coordinates, List<IBlockState> blockStates, List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos) { public PlacedData(float time, List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) {
this.time = time; this.time = time;
this.coordinates = coordinates; this.coordinates = coordinates;
this.blockStates = blockStates; this.blockStates = blockStates;
this.itemStacks = itemStacks; this.itemStacks = itemStacks;
this.firstPos = firstPos; this.firstPos = firstPos;
this.secondPos = secondPos; this.secondPos = secondPos;
this.breaking = breaking;
} }
} }
@@ -73,17 +76,18 @@ public class BlockPreviewRenderer {
public static void render(EntityPlayer player, ModifierSettings modifierSettings, ModeSettings modeSettings) { public static void render(EntityPlayer player, ModifierSettings modifierSettings, ModeSettings modeSettings) {
//Render placed blocks with dissolve effect //Render placed blocks with dissolve effect
for (int i = 0; i < placedDataList.size(); i++) { //Use fancy shader if config allows, otherwise no dissolve
PlacedData placed = placedDataList.get(i); if (BuildConfig.visuals.useShaders) {
if (placed.coordinates != null && !placed.coordinates.isEmpty()) { 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, placed.breaking);
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();
} }
RenderHandler.endBlockPreviews();
} }
//Expire //Expire
placedDataList.removeIf(placed -> placed.time + BuildConfig.visuals.dissolveTime < ClientProxy.ticksInGame); placedDataList.removeIf(placed -> placed.time + BuildConfig.visuals.dissolveTime < ClientProxy.ticksInGame);
@@ -122,16 +126,17 @@ public class BlockPreviewRenderer {
//Unless alwaysShowBlockPreview is true in config //Unless alwaysShowBlockPreview is true in config
if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) { if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) {
RenderHandler.beginBlockPreviews();
IBuildMode buildModeInstance = modeSettings.getBuildMode().instance; IBuildMode buildModeInstance = modeSettings.getBuildMode().instance;
if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player); if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player);
if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player); if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player);
if (sideHit != null) { if (sideHit != null) {
//Should be red?
boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player);
//get coordinates //get coordinates
List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos); List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace());
BlockPos firstPos = BlockPos.ORIGIN, secondPos = BlockPos.ORIGIN; BlockPos firstPos = BlockPos.ORIGIN, secondPos = BlockPos.ORIGIN;
//Remember first and last pos for the shader //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)), hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
Math.abs(hitVec.z - ((int) hitVec.z))); Math.abs(hitVec.z - ((int) hitVec.z)));
//Get blockstates
List<ItemStack> itemStacks = new ArrayList<>(); List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); List<IBlockState> 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 //Check if they are different from previous
//TODO fix triggering when moving player //TODO fix triggering when moving player
@@ -173,7 +189,7 @@ public class BlockPreviewRenderer {
//if so, renew randomness of randomizer bag //if so, renew randomness of randomizer bag
ItemRandomizerBag.renewRandomness(); ItemRandomizerBag.renewRandomness();
//and play sound (max once every tick) //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; soundTime = ClientProxy.ticksInGame;
//player.playSound(EffortlessBuilding.SOUND_BUILD_CLICK, 0.2f, 1f); //player.playSound(EffortlessBuilding.SOUND_BUILD_CLICK, 0.2f, 1f);
player.playSound(blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.world, player.playSound(blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.world,
@@ -183,12 +199,30 @@ public class BlockPreviewRenderer {
//Render block previews //Render block previews
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) { 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(); RenderHandler.beginLines();
//Draw outlines if tool in hand //Draw outlines if tool in hand
//Find proper raytrace: either normal range or increased range depending on canBreakFar //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); IBlockState blockState = player.world.getBlockState(coordinate);
if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) { if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) {
if (SurvivalHelper.canBreak(player.world, player, coordinate) || i == 0) { 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) { public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) {
return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.Normal || return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.Normal ||
(startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) || (startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) ||
@@ -222,8 +257,9 @@ public class BlockPreviewRenderer {
protected static void renderBlockPreviews(List<BlockPos> coordinates, List<IBlockState> blockStates, protected static void renderBlockPreviews(List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, float dissolve, BlockPos firstPos, List<ItemStack> itemStacks, float dissolve, BlockPos firstPos,
BlockPos secondPos, boolean checkCanPlace) { BlockPos secondPos, boolean checkCanPlace, boolean red) {
EntityPlayer player = Minecraft.getMinecraft().player; EntityPlayer player = Minecraft.getMinecraft().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
if (coordinates.isEmpty()) return; if (coordinates.isEmpty()) return;
@@ -231,22 +267,21 @@ public class BlockPreviewRenderer {
for (int i = coordinates.size() - 1; i >= 0; i--) { for (int i = coordinates.size() - 1; i >= 0; i--) {
BlockPos blockPos = coordinates.get(i); BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i); IBlockState blockState = blockStates.get(i);
ItemStack itemstack = itemStacks.get(i); ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i);
if(CompatHelper.isItemBlockProxy(itemstack)) if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState); itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
//Check if can place //Check if can place
//If check is turned off, check if blockstate is the same (for dissolve effect) //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) || if ((!checkCanPlace /*&& player.world.getBlockState(blockPos) == blockState*/) ||
(!checkCanPlace && player.world.getBlockState(blockPos) == blockState)) { SurvivalHelper.canPlace(player.world, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), EnumFacing.UP)) {
ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve, ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve,
new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos), new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos),
blockPos == secondPos)); blockPos == secondPos, red));
RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState); RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState);
} }
} }
} }
public static void onBlocksPlaced() { public static void onBlocksPlaced() {
@@ -256,18 +291,45 @@ public class BlockPreviewRenderer {
//Check if block previews are enabled //Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, previousFirstPos)) { if (doRenderBlockPreviews(modifierSettings, modeSettings, previousFirstPos)) {
//Save current coordinates, blockstates and itemstacks //Save current coordinates, blockstates and itemstacks
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates, if (!previousCoordinates.isEmpty() && previousBlockStates.size() == previousCoordinates.size() &&
previousItemStacks, previousFirstPos, previousSecondPos)); previousCoordinates.size() < BuildConfig.visuals.shaderTreshold) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, previousCoordinates, previousBlockStates,
previousItemStacks, previousFirstPos, previousSecondPos, false));
}
} }
} }
private static Consumer<Integer> 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<Integer> generateShaderCallback(final float dissolve, final Vec3d blockpos,
final Vec3d firstpos, final Vec3d secondpos,
final boolean highlight, final boolean red) {
Minecraft mc = Minecraft.getMinecraft(); Minecraft mc = Minecraft.getMinecraft();
return (Integer shader) -> { return (Integer shader) -> {
int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "dissolve"); int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "dissolve");
int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight"); int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight");
int redUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "red");
int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos"); int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos");
int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos"); int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos");
int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos"); int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos");
@@ -298,6 +360,8 @@ public class BlockPreviewRenderer {
ARBShaderObjects.glUniform1fARB(percentileUniform, dissolve); ARBShaderObjects.glUniform1fARB(percentileUniform, dissolve);
//highlight //highlight
ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0); ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0);
//red
ARBShaderObjects.glUniform1iARB(redUniform, red ? 1 : 0);
}; };
} }
} }

View File

@@ -200,17 +200,17 @@ public class RenderHandler implements IWorldEventListener {
GlStateManager.popMatrix(); GlStateManager.popMatrix();
} }
protected static void renderBlockOutline(BlockPos pos) { protected static void renderBlockOutline(BlockPos pos, Vec3d color) {
renderBlockOutline(pos, pos); renderBlockOutline(pos, pos, color);
} }
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z //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); GL11.glLineWidth(2);
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026); 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);
} }

View File

@@ -4,6 +4,7 @@ uniform int time; // Passed in, see ShaderHelper.java
uniform float dissolve; // Passed in via Callback uniform float dissolve; // Passed in via Callback
uniform int highlight; uniform int highlight;
uniform int red;
uniform vec3 blockpos; uniform vec3 blockpos;
uniform vec3 firstpos; uniform vec3 firstpos;
uniform vec3 secondpos; uniform vec3 secondpos;
@@ -87,10 +88,12 @@ void main() {
color.rgb -= 0.05; color.rgb -= 0.05;
if(highlight == 1 && dissolve == 0.0) { if (highlight == 1 && dissolve == 0.0) {
color.r += 0.0; color.rgb += vec3(0.0, 0.1, -0.2);
color.g += 0.1; }
color.b -= 0.2;
if (red == 1) {
color.rgb += vec3(0.4, -0.3, -0.5);
} }
color.r = max(0, min(1, color.r)); color.r = max(0, min(1, color.r));

View File

@@ -1,14 +1,5 @@
#version 120 #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 vec4 position;
varying vec3 normal; varying vec3 normal;