Added breaking animation to all breakable blocks.
Smart preview: only blocks that can be (re)placed show a preview. Smart outline when breaking: only blocks that can be broken by the current tool get an outline. Improved occlusion by render further block previews first. Reversed order of mirror and array to mirror arrays (for roofs etc).
This commit is contained in:
@@ -89,6 +89,7 @@ public class Array {
|
||||
blockState = BuildModifiers.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
|
||||
}
|
||||
|
||||
//blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )
|
||||
blockStates.add(blockState);
|
||||
itemStacks.add(itemStack);
|
||||
}
|
||||
|
||||
@@ -86,6 +86,9 @@ public class BuildModifiers {
|
||||
public static void onBlockBroken(BlockEvent.BreakEvent event) {
|
||||
if (event.getWorld().isRemote) return;
|
||||
|
||||
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
|
||||
//Only use own break event if anything is enabled
|
||||
if (isEnabled(buildSettings, event.getPos())) {
|
||||
//get coordinates
|
||||
List<BlockPos> coordinates = findCoordinates(event.getPlayer(), event.getPos());
|
||||
|
||||
@@ -96,18 +99,19 @@ public class BuildModifiers {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
|
||||
List<BlockPos> coordinates = new ArrayList<>();
|
||||
//Add current block being placed too
|
||||
coordinates.add(startPos);
|
||||
|
||||
List<BlockPos> mirrorCoordinates = Mirror.findCoordinates(player, startPos);
|
||||
coordinates.addAll(mirrorCoordinates);
|
||||
coordinates.addAll(Array.findCoordinates(player, startPos));
|
||||
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, startPos);
|
||||
coordinates.addAll(arrayCoordinates);
|
||||
coordinates.addAll(Mirror.findCoordinates(player, startPos));
|
||||
//get array for each coordinate
|
||||
for (BlockPos coordinate : mirrorCoordinates) {
|
||||
coordinates.addAll(Array.findCoordinates(player, coordinate));
|
||||
for (BlockPos coordinate : arrayCoordinates) {
|
||||
coordinates.addAll(Mirror.findCoordinates(player, coordinate));
|
||||
}
|
||||
|
||||
return coordinates;
|
||||
@@ -137,17 +141,26 @@ public class BuildModifiers {
|
||||
blockStates.add(blockState);
|
||||
itemStacks.add(itemStack);
|
||||
|
||||
List<IBlockState> mirrorBlockStates = Mirror.findBlockStates(player, startPos, blockState, itemStack, itemStacks);
|
||||
blockStates.addAll(mirrorBlockStates);
|
||||
blockStates.addAll(Array.findBlockStates(player, startPos, blockState, itemStack, itemStacks));
|
||||
List<IBlockState> arrayBlockStates = Array.findBlockStates(player, startPos, blockState, itemStack, itemStacks);
|
||||
blockStates.addAll(arrayBlockStates);
|
||||
blockStates.addAll(Mirror.findBlockStates(player, startPos, blockState, itemStack, itemStacks));
|
||||
//add array for each mirror coordinate
|
||||
List<BlockPos> findCoordinates = Mirror.findCoordinates(player, startPos);
|
||||
for (int i = 0; i < findCoordinates.size(); i++) {
|
||||
BlockPos coordinate = findCoordinates.get(i);
|
||||
IBlockState blockState1 = mirrorBlockStates.get(i);
|
||||
blockStates.addAll(Array.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
|
||||
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, startPos);
|
||||
for (int i = 0; i < arrayCoordinates.size(); i++) {
|
||||
BlockPos coordinate = arrayCoordinates.get(i);
|
||||
IBlockState blockState1 = arrayBlockStates.get(i);
|
||||
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
|
||||
}
|
||||
|
||||
//Adjust blockstates for torches and ladders etc to place on a valid side
|
||||
//TODO optimize findCoordinates (done twice now)
|
||||
//TODO fix mirror
|
||||
// List<BlockPos> coordinates = findCoordinates(player, startPos);
|
||||
// for (int i = 0; i < blockStates.size(); i++) {
|
||||
// blockStates.set(i, blockStates.get(i).getBlock().getStateForPlacement(player.world, coordinates.get(i), facing,
|
||||
// (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, itemStacks.get(i).getMetadata(), player, EnumHand.MAIN_HAND));
|
||||
// }
|
||||
|
||||
return blockStates;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ public class EventHandler
|
||||
IBlockState blockState = world.getBlockState(coordinate);
|
||||
//add hardness for each blockstate, if can break
|
||||
if (SurvivalHelper.canBreak(world, player, coordinate))
|
||||
totalBlockHardness += world.getBlockState(coordinate).getBlockHardness(world, coordinate);
|
||||
totalBlockHardness += blockState.getBlockHardness(world, coordinate);
|
||||
}
|
||||
|
||||
//Grabbing percentage from config
|
||||
|
||||
@@ -26,7 +26,7 @@ public class Mirror {
|
||||
public Vec3d position = new Vec3d(0.5, 64.5, 0.5);
|
||||
public boolean mirrorX = true, mirrorY = false, mirrorZ = false;
|
||||
public int radius = 20;
|
||||
public boolean drawLines = true, drawPlanes = false;
|
||||
public boolean drawLines = true, drawPlanes = true;
|
||||
|
||||
public MirrorSettings() {
|
||||
}
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
package nl.requios.effortlessbuilding.helper;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.*;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemTool;
|
||||
import net.minecraft.util.BlockRenderLayer;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.MinecraftForgeClient;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.IWorldEventListener;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
@@ -25,11 +30,13 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.util.Color;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mod.EventBusSubscriber(Side.CLIENT)
|
||||
public class RenderHelper {
|
||||
public class RenderHelper implements IWorldEventListener {
|
||||
|
||||
private static final Color colorX = new Color(255, 72, 52);
|
||||
private static final Color colorY = new Color(67, 204, 51);
|
||||
@@ -76,20 +83,7 @@ public class RenderHelper {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFunc(GL11.GL_CONSTANT_ALPHA, GL11.GL_ONE_MINUS_CONSTANT_ALPHA);
|
||||
GL14.glBlendColor(1F, 1F, 1F, 0.6f);
|
||||
}
|
||||
|
||||
public static void renderBlockOutline(BlockPos pos) {
|
||||
renderBlockOutline(pos, pos);
|
||||
}
|
||||
|
||||
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
|
||||
public static void renderBlockOutline(BlockPos pos1, BlockPos pos2) {
|
||||
GL11.glLineWidth(2);
|
||||
|
||||
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
|
||||
|
||||
RenderGlobal.drawSelectionBoundingBox(aabb, 0f, 0f, 0f, 0.4f);
|
||||
GL14.glBlendColor(1F, 1F, 1F, 0.8f);
|
||||
}
|
||||
|
||||
private static void endBlockPreviews() {
|
||||
@@ -109,10 +103,23 @@ public class RenderHelper {
|
||||
GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.translate(-0.005f, -0.005f, 0.005f);
|
||||
GlStateManager.scale(1.01f, 1.01f, 1.01f);
|
||||
dispatcher.renderBlockBrightness(blockState, 1f);
|
||||
dispatcher.renderBlockBrightness(blockState, 0.85f);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
public static void renderBlockOutline(BlockPos pos) {
|
||||
renderBlockOutline(pos, pos);
|
||||
}
|
||||
|
||||
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
|
||||
public static void renderBlockOutline(BlockPos pos1, BlockPos pos2) {
|
||||
GL11.glLineWidth(2);
|
||||
|
||||
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
|
||||
|
||||
RenderGlobal.drawSelectionBoundingBox(aabb, 0f, 0f, 0f, 0.4f);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRender(RenderWorldLastEvent event) {
|
||||
EntityPlayer player = Minecraft.getMinecraft().player;
|
||||
@@ -170,7 +177,7 @@ public class RenderHelper {
|
||||
|
||||
//Check if tool (or none) in hand
|
||||
ItemStack mainhand = player.getHeldItemMainhand();
|
||||
boolean toolInHand = !mainhand.isEmpty() && mainhand.getItem() instanceof ItemTool;
|
||||
boolean toolInHand = mainhand.isEmpty() || (!mainhand.isEmpty() && mainhand.getItem() instanceof ItemTool);
|
||||
boolean replaceable =
|
||||
player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
|
||||
if (!buildSettings.doQuickReplace() && !toolInHand && !replaceable) {
|
||||
@@ -201,13 +208,19 @@ public class RenderHelper {
|
||||
|
||||
//check if valid blockstates
|
||||
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
|
||||
for (int i = 0; i < newCoordinates.size(); i++) {
|
||||
for (int i = newCoordinates.size() - 1; i >= 0; i--) {
|
||||
BlockPos blockPos = newCoordinates.get(i);
|
||||
IBlockState blockState = blockStates.get(i);
|
||||
ItemStack itemstack = itemStacks.get(i);
|
||||
//Check if can place
|
||||
if (!itemstack.isEmpty() && SurvivalHelper.canPlayerEdit(player, player.world, blockPos, itemstack) &&
|
||||
SurvivalHelper.mayPlace(player.world, Block.getBlockFromItem(itemstack.getItem()), blockState, blockPos, true, EnumFacing.UP, player) &&
|
||||
SurvivalHelper.canReplace(player.world, player, blockPos)) {
|
||||
renderBlockPreview(dispatcher, blockPos, blockState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
endBlockPreviews();
|
||||
|
||||
beginLines();
|
||||
@@ -217,7 +230,8 @@ public class RenderHelper {
|
||||
BlockPos coordinate = newCoordinates.get(i);
|
||||
|
||||
IBlockState blockState = player.world.getBlockState(coordinate);
|
||||
if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) {
|
||||
if (!blockState.getBlock().isAir(blockState, player.world, coordinate) &&
|
||||
SurvivalHelper.canBreak(player.world, player, coordinate)) {
|
||||
renderBlockOutline(coordinate);
|
||||
}
|
||||
}
|
||||
@@ -312,4 +326,82 @@ public class RenderHelper {
|
||||
tessellator.draw();
|
||||
}
|
||||
|
||||
//IWORLDEVENTLISTENER IMPLEMENTATION
|
||||
@Override
|
||||
public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyLightSet(BlockPos pos) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category,
|
||||
double x, double y, double z, float volume, float pitch) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playRecord(SoundEvent soundIn, BlockPos pos) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord,
|
||||
double xSpeed, double ySpeed, double zSpeed, int... parameters) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(int id, boolean ignoreRange, boolean p_190570_3_, double x, double y, double z,
|
||||
double xSpeed, double ySpeed, double zSpeed, int... parameters) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityAdded(Entity entityIn) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityRemoved(Entity entityIn) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastSound(int soundID, BlockPos pos, int data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data) {
|
||||
|
||||
}
|
||||
|
||||
//Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken
|
||||
@Override
|
||||
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
|
||||
if (!BuildModifiers.isEnabled(buildSettings, pos)) return;
|
||||
|
||||
List<BlockPos> coordinates = BuildModifiers.findCoordinates(mc.player, pos);
|
||||
for (int i = 1; i < coordinates.size(); i++) {
|
||||
BlockPos coordinate = coordinates.get(i);
|
||||
if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) {
|
||||
//Send i as entity id because only one block can be broken per id
|
||||
//Unless i happens to be the player id, then take something else
|
||||
int fakeId = mc.player.getEntityId() != i ? i : coordinates.size();
|
||||
mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package nl.requios.effortlessbuilding.helper;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.block.SoundType;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
@@ -20,6 +21,7 @@ import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import nl.requios.effortlessbuilding.BuildSettingsManager;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
|
||||
|
||||
@@ -108,11 +110,12 @@ public class SurvivalHelper {
|
||||
|
||||
//Can break using held tool? (or in creative)
|
||||
public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) {
|
||||
IBlockState blockState = world.getBlockState(pos);
|
||||
if (blockState.getBlock() instanceof BlockLiquid) return false;
|
||||
|
||||
if (player.isCreative()) return true;
|
||||
|
||||
IBlockState blockState = world.getBlockState(pos);
|
||||
return canHarvestBlock(blockState.getBlock(), player, world, pos);
|
||||
|
||||
}
|
||||
|
||||
//From ForgeHooks#canHarvestBlock
|
||||
@@ -169,21 +172,23 @@ public class SurvivalHelper {
|
||||
}
|
||||
|
||||
//From EntityPlayer#canPlayerEdit
|
||||
private static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack)
|
||||
public static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack)
|
||||
{
|
||||
if (player.capabilities.allowEdit)
|
||||
{
|
||||
//True in creative and survival mode
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Adventure mode
|
||||
Block block = world.getBlockState(pos).getBlock();
|
||||
return stack.canPlaceOn(block) || stack.canEditBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
//From World#mayPlace
|
||||
private static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer)
|
||||
public static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer)
|
||||
{
|
||||
IBlockState iblockstate1 = world.getBlockState(pos);
|
||||
AxisAlignedBB axisalignedbb = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionBoundingBox(world, pos);
|
||||
@@ -204,9 +209,11 @@ public class SurvivalHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO check config for allow to replace
|
||||
//Check quickreplace
|
||||
if (placer instanceof EntityPlayer && BuildSettingsManager.getBuildSettings(((EntityPlayer) placer)).doQuickReplace()) {
|
||||
return true;
|
||||
//TODO fix check canPlaceBlockOnSide
|
||||
//return /*iblockstate1.getBlock().isReplaceable(world, pos) &&*/ blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn);
|
||||
}
|
||||
|
||||
return iblockstate1.getBlock().isReplaceable(world, pos) && blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,27 @@ package nl.requios.effortlessbuilding.proxy;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.SoundType;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.IThreadListener;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.world.IWorldEventListener;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.ModelRegistryEvent;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
import net.minecraftforge.fml.client.registry.ClientRegistry;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.event.*;
|
||||
@@ -28,8 +35,12 @@ import net.minecraftforge.fml.relauncher.Side;
|
||||
import nl.requios.effortlessbuilding.BuildSettingsManager;
|
||||
import nl.requios.effortlessbuilding.EffortlessBuilding;
|
||||
import nl.requios.effortlessbuilding.gui.SettingsGui;
|
||||
import nl.requios.effortlessbuilding.helper.RenderHelper;
|
||||
import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import scala.collection.parallel.ParIterableLike;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Mod.EventBusSubscriber(Side.CLIENT)
|
||||
public class ClientProxy implements IProxy {
|
||||
@@ -88,6 +99,13 @@ public class ClientProxy implements IProxy {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
|
||||
if (event.getEntity() == Minecraft.getMinecraft().player) {
|
||||
event.getWorld().addEventListener(new RenderHelper());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true)
|
||||
public static void onKeyPress(InputEvent.KeyInputEvent event) {
|
||||
EntityPlayerSP player = Minecraft.getMinecraft().player;
|
||||
|
||||
Reference in New Issue
Block a user