Check if can break and replace blocks. Breaking only works if your current held tool can break it. Replace only works with blocks that can be harvested with your hand.

Damages used tool appropriately.
Added block outlines to mirror and array.
This commit is contained in:
Christian Knaapen
2018-10-20 16:15:14 +02:00
parent 821b46a253
commit bda53e4b08
7 changed files with 235 additions and 103 deletions

View File

@@ -2,19 +2,25 @@ package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
@Mod.EventBusSubscriber
public class Array {
//TODO config file
public static final int MAX_COUNT = 100;
@@ -99,14 +105,46 @@ public class Array {
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
for (int i = 0; i < a.count; i++) {
pos = pos.add(offset);
if (event.getWorld().isBlockLoaded(pos, false)) {
//TODO check if can break
SurvivalHelper.breakBlock(event.getWorld(), event.getPlayer(), pos);
}
}
//Drop existing block
SurvivalHelper.dropBlock(event.getWorld(), pos, event.getPlayer());
@SubscribeEvent
@SideOnly(Side.CLIENT)
public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getMinecraft().player;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
if (buildSettings == null) return;
ArraySettings a = buildSettings.getArraySettings();
event.getWorld().setBlockToAir(pos);
}
if (a == null || !a.enabled || (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0)) return;
RenderHelper.begin(event.getPartialTicks());
//Render block outlines
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
if (objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK)
{
BlockPos blockPos = objectMouseOver.getBlockPos();
if (!buildSettings.doQuickReplace()) blockPos = blockPos.offset(objectMouseOver.sideHit);
drawBlockOutlines(a, blockPos);
}
RenderHelper.end();
}
@SideOnly(Side.CLIENT)
public static void drawBlockOutlines(ArraySettings a, BlockPos pos) {
if (a == null || !a.enabled || (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0)) return;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
//RenderHelper.renderBlockOutline(blockPos);
for (int i = 0; i < a.count; i++)
{
pos = pos.add(offset);
RenderHelper.renderBlockOutline(pos);
}
}
}

View File

@@ -3,6 +3,7 @@ package nl.requios.effortlessbuilding;
import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
@@ -11,6 +12,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
@@ -259,9 +261,7 @@ public class Mirror {
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
//break block
if (event.getWorld().isBlockLoaded(newBlockPos, true)) {
breakBlock(event, newBlockPos);
}
if (m.mirrorY) breakMirrorY(event, m, newBlockPos);
if (m.mirrorZ) breakMirrorZ(event, m, newBlockPos);
}
@@ -270,10 +270,8 @@ public class Mirror {
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
//place block
if (event.getWorld().isBlockLoaded(newBlockPos, true)) {
//break block
breakBlock(event, newBlockPos);
}
if (m.mirrorZ) breakMirrorZ(event, m, newBlockPos);
}
@@ -281,17 +279,14 @@ public class Mirror {
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
//place block
if (event.getWorld().isBlockLoaded(newBlockPos, true)) {
//break block
breakBlock(event, newBlockPos);
}
}
private static void breakBlock(BlockEvent.BreakEvent event, BlockPos newBlockPos) {
//TODO check if can break
if (!event.getWorld().isBlockLoaded(newBlockPos, false)) return;
SurvivalHelper.dropBlock(event.getWorld(), newBlockPos, event.getPlayer());
event.getWorld().setBlockToAir(newBlockPos);
SurvivalHelper.breakBlock(event.getWorld(), event.getPlayer(), newBlockPos);
//Array synergy
BlockEvent.BreakEvent breakEvent = new BlockEvent.BreakEvent(event.getWorld(), newBlockPos, event.getState(), event.getPlayer());
@@ -308,11 +303,8 @@ public class Mirror {
if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * event.getPartialTicks();
double playerY = player.prevPosY + (player.posY - player.prevPosY) * event.getPartialTicks();
double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * event.getPartialTicks();
RenderHelper.begin(event.getPartialTicks());
Vec3d playerPos = new Vec3d(playerX, playerY, playerZ);
Vec3d pos = m.position.add(epsilon);
int radius = m.radius;
@@ -320,45 +312,47 @@ public class Mirror {
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius);
Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius);
drawMirrorPlane(playerPos, posA, posB, colorX, m.drawLines, m.drawPlanes);
drawMirrorPlane(posA, posB, colorX, m.drawLines, m.drawPlanes);
}
if (m.mirrorY) {
Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius);
Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius);
drawMirrorPlaneY(playerPos, posA, posB, colorY, m.drawLines, m.drawPlanes);
drawMirrorPlaneY(posA, posB, colorY, m.drawLines, m.drawPlanes);
}
if (m.mirrorZ) {
Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z);
drawMirrorPlane(playerPos, posA, posB, colorZ, m.drawLines, m.drawPlanes);
drawMirrorPlane(posA, posB, colorZ, m.drawLines, m.drawPlanes);
}
//Draw axis coordinated colors if two or more axes are enabled
//(If only one is enabled the lines are that planes color)
if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ))) {
drawMirrorLines(playerPos, m);
drawMirrorLines(m);
}
//Render block outlines
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
if (objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK)
{
BlockPos blockPos = objectMouseOver.getBlockPos();
if (!buildSettings.doQuickReplace()) blockPos = blockPos.offset(objectMouseOver.sideHit);
//RenderHelper.renderBlockOutline(blockPos);
if (m.mirrorX) drawBlockOutlineX(buildSettings, blockPos);
if (m.mirrorY) drawBlockOutlineY(buildSettings, blockPos);
if (m.mirrorZ) drawBlockOutlineZ(buildSettings, blockPos);
}
RenderHelper.end();
}
@SideOnly(Side.CLIENT)
public static void drawMirrorPlane(Vec3d playerPos, Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
public static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
GL11.glLineWidth(2);
GL11.glDepthMask(false);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
@@ -384,28 +378,12 @@ public class Mirror {
tessellator.draw();
}
GL11.glDepthMask(true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
@SideOnly(Side.CLIENT)
public static void drawMirrorPlaneY(Vec3d playerPos, Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
public static void drawMirrorPlaneY(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
GL11.glLineWidth(2);
GL11.glDepthMask(false);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
@@ -431,30 +409,15 @@ public class Mirror {
tessellator.draw();
}
GL11.glDepthMask(true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
@SideOnly(Side.CLIENT)
public static void drawMirrorLines(Vec3d playerPos, MirrorSettings m) {
public static void drawMirrorLines(MirrorSettings m) {
Vec3d pos = m.position.add(epsilon);
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
GL11.glColor4d(100, 100, 100, 255);
GL11.glLineWidth(2);
GL11.glDepthMask(false);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
@@ -468,11 +431,50 @@ public class Mirror {
bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
tessellator.draw();
GL11.glDepthMask(true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
@SideOnly(Side.CLIENT)
public static void drawBlockOutlineX(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) {
MirrorSettings m = buildSettings.getMirrorSettings();
//find mirror position
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
RenderHelper.renderBlockOutline(newBlockPos);
//Array synergy
Array.drawBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
if (m.mirrorY) drawBlockOutlineY(buildSettings, newBlockPos);
if (m.mirrorZ) drawBlockOutlineZ(buildSettings, newBlockPos);
}
@SideOnly(Side.CLIENT)
public static void drawBlockOutlineY(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) {
MirrorSettings m = buildSettings.getMirrorSettings();
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
RenderHelper.renderBlockOutline(newBlockPos);
//Array synergy
Array.drawBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
if (m.mirrorZ) drawBlockOutlineZ(buildSettings, newBlockPos);
}
@SideOnly(Side.CLIENT)
public static void drawBlockOutlineZ(BuildSettingsManager.BuildSettings buildSettings, BlockPos oldBlockPos) {
MirrorSettings m = buildSettings.getMirrorSettings();
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
RenderHelper.renderBlockOutline(newBlockPos);
//Array synergy
Array.drawBlockOutlines(buildSettings.getArraySettings(), newBlockPos);
}
}

View File

@@ -1,6 +1,5 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;

View File

@@ -0,0 +1,60 @@
package nl.requios.effortlessbuilding;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.Color;
@SideOnly(Side.CLIENT)
public class RenderHelper {
public static void begin(float partialTicks) {
EntityPlayer player = Minecraft.getMinecraft().player;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;
Vec3d playerPos = new Vec3d(playerX, playerY, playerZ);
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
GL11.glLineWidth(2);
GL11.glDepthMask(false);
}
public static void end() {
GL11.glDepthMask(true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
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, 1f, 1f, 1f, 0.6f);
}
}

View File

@@ -1,18 +1,15 @@
package nl.requios.effortlessbuilding;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
@@ -27,8 +24,11 @@ import java.util.List;
public class SurvivalHelper {
//From ItemBlock#onItemUse
//Used for all placing of blocks in this mod.
//Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack.
//Based on ItemBlock#onItemUse
public static boolean placeBlock(World world, EntityPlayer player, BlockPos pos, IBlockState blockState, ItemStack itemstack, EnumFacing facing, boolean skipCollisionCheck, boolean playSound) {
if (!world.isBlockLoaded(pos, true)) return false;
//Randomizer bag synergy
//Find itemstack that belongs to the blockstate
@@ -39,18 +39,20 @@ public class SurvivalHelper {
//Check if itemstack is correct
if (!(itemstack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemstack.getItem()) != blockState.getBlock()) {
EffortlessBuilding.log(player, "Cannot place block", true);
EffortlessBuilding.log(player, "Cannot replace block", true);
EffortlessBuilding.log("SurvivalHelper#placeBlock: itemstack " + itemstack.toString() + " does not match blockstate " + blockState.toString());
return false;
}
Block block = ((ItemBlock) itemstack.getItem()).getBlock();
if (!itemstack.isEmpty() && canPlayerEdit(player, world, pos, itemstack) && mayPlace(world, block, blockState, pos, skipCollisionCheck, facing.getOpposite(), player))
if (!itemstack.isEmpty() && canPlayerEdit(player, world, pos, itemstack) &&
mayPlace(world, block, blockState, pos, skipCollisionCheck, facing.getOpposite(), player) &&
canReplace(world, player, pos))
{
//Drop existing block
//TODO check if can replace
dropBlock(world, pos, player);
dropBlock(world, player, pos);
//From ItemBlock#placeBlockAt
if (!world.setBlockState(pos, blockState, 11)) return false;
@@ -79,18 +81,49 @@ public class SurvivalHelper {
return false;
}
public static boolean canBreak(){
//Can break using held tool? (or in creative)
//Used for all breaking of blocks in this mod.
//Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory
public static boolean breakBlock(World world, EntityPlayer player, BlockPos pos) {
if (!world.isBlockLoaded(pos, false)) return false;
//Check if can break
if (canBreak(world, player, pos))
{
//Drop existing block
dropBlock(world, player, pos);
//Damage tool
player.getHeldItemMainhand().onBlockDestroyed(world, world.getBlockState(pos), pos, player);
world.setBlockToAir(pos);
return true;
}
return false;
}
//Can break using held tool? (or in creative)
public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) {
if (player.isCreative()) return true;
IBlockState blockState = world.getBlockState(pos);
if (blockState.getBlock().canHarvestBlock(world, pos, player)) return true;
return false;
}
public static boolean canReplace(){
//Can be harvested with hand? (or in creative)
return true;
public static boolean canReplace(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return true;
IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos);
if (state.getMaterial().isToolNotRequired()) return true;
return false;
}
//Gives items directly to player
public static void dropBlock(World world, BlockPos pos, EntityPlayer player){
public static void dropBlock(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return;
IBlockState blockState = world.getBlockState(pos);

View File

@@ -45,9 +45,9 @@ public class ClientProxy implements IProxy {
keyBindings = new KeyBinding[3];
// instantiate the key bindings
keyBindings[0] = new KeyBinding("key.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category");
keyBindings[1] = new KeyBinding("key.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category");
keyBindings[2] = new KeyBinding("key.creative.desc", Keyboard.KEY_F4, "key.effortlessbuilding.category");
keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category");
keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category");
keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", Keyboard.KEY_F4, "key.effortlessbuilding.category");
// register all the key bindings
for (int i = 0; i < keyBindings.length; ++i) {

View File

@@ -1,6 +1,6 @@
key.effortlessbuilding.category=Effortless Building
key.hud.desc=Open Settings
key.replace.desc=Toggle QuickReplace
key.creative.desc=Toggle Creative/Survival
key.effortlessbuilding.hud.desc=Open Settings
key.effortlessbuilding.replace.desc=Toggle QuickReplace
key.effortlessbuilding.creative.desc=Toggle Survival/Creative Mode
item.effortlessbuilding:randomizer_bag.name=Randomizer Bag