From 728644c104fc58fe34eae555d0285d3cf26031ab Mon Sep 17 00:00:00 2001 From: SquidDev Date: Tue, 9 May 2017 23:03:42 +0100 Subject: [PATCH 1/5] Initial attempt at improving cable/wired modem interactions - Cable and modem can be broken individually - Ray tracing will go through "holes" in the cable. - Pick block will determine which part you are looking at. - Selection box will only highlight the region you are looking at: modem or cable. --- .../proxy/ComputerCraftProxyClient.java | 2 + .../client/render/RenderOverlayCable.java | 215 ++++++++++++++++++ .../shared/common/BlockGeneric.java | 4 +- .../shared/peripheral/common/BlockCable.java | 125 +++++++++- .../shared/peripheral/modem/TileCable.java | 4 +- .../computercraft/shared/util/WorldUtil.java | 46 +++- 6 files changed, 385 insertions(+), 11 deletions(-) create mode 100644 src/main/java/dan200/computercraft/client/render/RenderOverlayCable.java diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java index db2da9330..ad9267680 100644 --- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -8,6 +8,7 @@ package dan200.computercraft.client.proxy; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.*; +import dan200.computercraft.client.render.RenderOverlayCable; import dan200.computercraft.client.render.TileEntityMonitorRenderer; import dan200.computercraft.shared.computer.blocks.ComputerState; import dan200.computercraft.shared.computer.blocks.TileComputer; @@ -442,6 +443,7 @@ public class ComputerCraftProxyClient extends ComputerCraftProxyCommon { ForgeHandlers handlers = new ForgeHandlers(); MinecraftForge.EVENT_BUS.register( handlers ); + MinecraftForge.EVENT_BUS.register( new RenderOverlayCable() ); } public class ForgeHandlers diff --git a/src/main/java/dan200/computercraft/client/render/RenderOverlayCable.java b/src/main/java/dan200/computercraft/client/render/RenderOverlayCable.java new file mode 100644 index 000000000..5ee9e430f --- /dev/null +++ b/src/main/java/dan200/computercraft/client/render/RenderOverlayCable.java @@ -0,0 +1,215 @@ +package dan200.computercraft.client.render; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.BlockCable; +import dan200.computercraft.shared.peripheral.modem.TileCable; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +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.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; +import net.minecraftforge.client.event.DrawBlockHighlightEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.opengl.GL11; + +public class RenderOverlayCable +{ + private static final float EXPAND = 0.002f; + private static final double MIN = TileCable.MIN - EXPAND; + private static final double MAX = TileCable.MAX + EXPAND; + + @SubscribeEvent + public void drawHighlight( DrawBlockHighlightEvent event ) + { + if( event.getTarget().typeOfHit != RayTraceResult.Type.BLOCK ) return; + + BlockPos pos = event.getTarget().getBlockPos(); + World world = event.getPlayer().getEntityWorld(); + + IBlockState state = world.getBlockState( pos ); + if( state.getBlock() != ComputerCraft.Blocks.cable ) return; + + TileEntity tile = world.getTileEntity( pos ); + if( tile == null || !(tile instanceof TileCable) ) return; + + event.setCanceled( true ); + TileCable cable = (TileCable) tile; + + PeripheralType type = cable.getPeripheralType(); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0 ); + GlStateManager.color( 0.0f, 0.0f, 0.0f, 0.4f ); + GL11.glLineWidth( 2.0F ); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask( false ); + GlStateManager.pushMatrix(); + + EnumFacing direction = type != PeripheralType.Cable ? cable.getDirection() : null; + + { + EntityPlayer player = event.getPlayer(); + double x = player.lastTickPosX + (player.posX - player.lastTickPosX) * event.getPartialTicks(); + double y = player.lastTickPosY + (player.posY - player.lastTickPosY) * event.getPartialTicks(); + double z = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * event.getPartialTicks(); + + GlStateManager.translate( -x + pos.getX(), -y + pos.getY(), -z + pos.getZ() ); + } + + if( type != PeripheralType.Cable && WorldUtil.isVecInsideInclusive( cable.getModemBounds(), event.getTarget().hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ) + { + RenderGlobal.drawSelectionBoundingBox( cable.getModemBounds(), 0, 0, 0, 0.4f ); + } + else + { + int flags = 0; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + for( EnumFacing facing : EnumFacing.VALUES ) + { + if( direction == facing || BlockCable.isCable( world, pos.offset( facing ) ) ) + { + flags |= 1 << facing.ordinal(); + + + switch( facing.getAxis() ) + { + case X: + { + double offset = facing == EnumFacing.WEST ? -EXPAND : 1 + EXPAND; + double centre = facing == EnumFacing.WEST ? MIN : MAX; + + buffer.begin( GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION ); + buffer.pos( offset, MIN, MIN ).endVertex(); + buffer.pos( offset, MAX, MIN ).endVertex(); + buffer.pos( offset, MAX, MAX ).endVertex(); + buffer.pos( offset, MIN, MAX ).endVertex(); + buffer.pos( offset, MIN, MIN ).endVertex(); + tessellator.draw(); + + buffer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION ); + buffer.pos( offset, MIN, MIN ).endVertex(); + buffer.pos( centre, MIN, MIN ).endVertex(); + buffer.pos( offset, MAX, MIN ).endVertex(); + buffer.pos( centre, MAX, MIN ).endVertex(); + buffer.pos( offset, MAX, MAX ).endVertex(); + buffer.pos( centre, MAX, MAX ).endVertex(); + buffer.pos( offset, MIN, MAX ).endVertex(); + buffer.pos( centre, MIN, MAX ).endVertex(); + tessellator.draw(); + break; + } + case Y: + { + double offset = facing == EnumFacing.DOWN ? -EXPAND : 1 + EXPAND; + double centre = facing == EnumFacing.DOWN ? MIN : MAX; + + buffer.begin( GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION ); + buffer.pos( MIN, offset, MIN ).endVertex(); + buffer.pos( MAX, offset, MIN ).endVertex(); + buffer.pos( MAX, offset, MAX ).endVertex(); + buffer.pos( MIN, offset, MAX ).endVertex(); + buffer.pos( MIN, offset, MIN ).endVertex(); + tessellator.draw(); + + buffer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION ); + buffer.pos( MIN, offset, MIN ).endVertex(); + buffer.pos( MIN, centre, MIN ).endVertex(); + buffer.pos( MAX, offset, MIN ).endVertex(); + buffer.pos( MAX, centre, MIN ).endVertex(); + buffer.pos( MAX, offset, MAX ).endVertex(); + buffer.pos( MAX, centre, MAX ).endVertex(); + buffer.pos( MIN, offset, MAX ).endVertex(); + buffer.pos( MIN, centre, MAX ).endVertex(); + tessellator.draw(); + break; + } + case Z: + { + double offset = facing == EnumFacing.NORTH ? -EXPAND : 1 + EXPAND; + double centre = facing == EnumFacing.NORTH ? MIN : MAX; + + buffer.begin( GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION ); + buffer.pos( MIN, MIN, offset ).endVertex(); + buffer.pos( MAX, MIN, offset ).endVertex(); + buffer.pos( MAX, MAX, offset ).endVertex(); + buffer.pos( MIN, MAX, offset ).endVertex(); + buffer.pos( MIN, MIN, offset ).endVertex(); + tessellator.draw(); + + buffer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION ); + buffer.pos( MIN, MIN, offset ).endVertex(); + buffer.pos( MIN, MIN, centre ).endVertex(); + buffer.pos( MAX, MIN, offset ).endVertex(); + buffer.pos( MAX, MIN, centre ).endVertex(); + buffer.pos( MAX, MAX, offset ).endVertex(); + buffer.pos( MAX, MAX, centre ).endVertex(); + buffer.pos( MIN, MAX, offset ).endVertex(); + buffer.pos( MIN, MAX, centre ).endVertex(); + tessellator.draw(); + break; + } + } + } + } + + buffer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION ); + + draw( buffer, flags, EnumFacing.WEST, EnumFacing.DOWN, EnumFacing.Axis.Z ); + draw( buffer, flags, EnumFacing.WEST, EnumFacing.UP, EnumFacing.Axis.Z ); + draw( buffer, flags, EnumFacing.EAST, EnumFacing.DOWN, EnumFacing.Axis.Z ); + draw( buffer, flags, EnumFacing.EAST, EnumFacing.UP, EnumFacing.Axis.Z ); + + draw( buffer, flags, EnumFacing.WEST, EnumFacing.NORTH, EnumFacing.Axis.Y ); + draw( buffer, flags, EnumFacing.WEST, EnumFacing.SOUTH, EnumFacing.Axis.Y ); + draw( buffer, flags, EnumFacing.EAST, EnumFacing.NORTH, EnumFacing.Axis.Y ); + draw( buffer, flags, EnumFacing.EAST, EnumFacing.SOUTH, EnumFacing.Axis.Y ); + + draw( buffer, flags, EnumFacing.DOWN, EnumFacing.NORTH, EnumFacing.Axis.X ); + draw( buffer, flags, EnumFacing.DOWN, EnumFacing.SOUTH, EnumFacing.Axis.X ); + draw( buffer, flags, EnumFacing.UP, EnumFacing.NORTH, EnumFacing.Axis.X ); + draw( buffer, flags, EnumFacing.UP, EnumFacing.SOUTH, EnumFacing.Axis.X ); + + tessellator.draw(); + } + + GlStateManager.popMatrix(); + GlStateManager.depthMask( true ); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + + private static void draw( BufferBuilder buffer, int flags, EnumFacing a, EnumFacing b, EnumFacing.Axis other ) + { + if( ((flags >> a.ordinal()) & 1) != ((flags >> b.ordinal()) & 1) ) return; + + double offA = a.getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE ? MIN : MAX; + double offB = b.getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE ? MIN : MAX; + switch( other ) + { + case X: + buffer.pos( MIN, offA, offB ).endVertex(); + buffer.pos( MAX, offA, offB ).endVertex(); + break; + case Y: + buffer.pos( offA, MIN, offB ).endVertex(); + buffer.pos( offA, MAX, offB ).endVertex(); + break; + case Z: + buffer.pos( offA, offB, MIN ).endVertex(); + buffer.pos( offA, offB, MAX ).endVertex(); + break; + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java index cf65d541b..983c7e1f5 100644 --- a/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/BlockGeneric.java @@ -68,7 +68,7 @@ public abstract class BlockGeneric extends Block implements } @Override - public final boolean removedByPlayer( @Nonnull IBlockState state, World world, @Nonnull BlockPos pos, @Nonnull EntityPlayer player, boolean willHarvest ) + public boolean removedByPlayer( @Nonnull IBlockState state, World world, @Nonnull BlockPos pos, @Nonnull EntityPlayer player, boolean willHarvest ) { if( !world.isRemote ) { @@ -122,7 +122,7 @@ public abstract class BlockGeneric extends Block implements @Nonnull @Override - public final ItemStack getPickBlock( @Nonnull IBlockState state, RayTraceResult target, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player ) + public ItemStack getPickBlock( @Nonnull IBlockState state, RayTraceResult target, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player ) { TileEntity tile = world.getTileEntity( pos ); if( tile != null && tile instanceof TileGeneric ) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java index 2fb4abb35..4e5d2419b 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java @@ -7,21 +7,32 @@ package dan200.computercraft.shared.peripheral.common; import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.peripheral.PeripheralType; import dan200.computercraft.shared.peripheral.modem.TileCable; +import dan200.computercraft.shared.util.WorldUtil; import net.minecraft.block.Block; import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.BlockFaceShape; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +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.IBlockAccess; +import net.minecraft.world.World; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; public class BlockCable extends BlockPeripheralBase { @@ -195,7 +206,7 @@ public class BlockCable extends BlockPeripheralBase TileEntity tile = world.getTileEntity( pos ); if( tile != null && tile instanceof TilePeripheralBase ) { - TilePeripheralBase peripheral = (TilePeripheralBase)tile; + TilePeripheralBase peripheral = (TilePeripheralBase) tile; anim = peripheral.getAnim(); } else @@ -208,7 +219,7 @@ public class BlockCable extends BlockPeripheralBase { modem = BlockCableModemVariant.values()[ 1 + 6 * anim + modem.getFacing().getIndex() - ]; + ]; } state = state.withProperty( Properties.MODEM, modem ); @@ -253,6 +264,116 @@ public class BlockCable extends BlockPeripheralBase return new TileCable(); } + @Nullable + @Override + @Deprecated + public RayTraceResult collisionRayTrace( IBlockState blockState, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Vec3d start, @Nonnull Vec3d end ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileGeneric && tile.hasWorld() ) + { + TileGeneric generic = (TileGeneric) tile; + + double distance = Double.POSITIVE_INFINITY; + RayTraceResult result = null; + + List bounds = new ArrayList( 7 ); + generic.getCollisionBounds( bounds ); + + Vec3d startOff = start.subtract( pos.getX(), pos.getY(), pos.getZ() ); + Vec3d endOff = end.subtract( pos.getX(), pos.getY(), pos.getZ() ); + + for( AxisAlignedBB bb : bounds ) + { + RayTraceResult hit = bb.calculateIntercept( startOff, endOff ); + if( hit != null ) + { + double newDistance = hit.hitVec.squareDistanceTo( startOff ); + if( newDistance <= distance ) + { + distance = newDistance; + result = hit; + } + } + } + + return result == null ? null : new RayTraceResult( result.hitVec.addVector( pos.getX(), pos.getY(), pos.getZ() ), result.sideHit, pos ); + } + else + { + return super.collisionRayTrace( blockState, world, pos, start, end ); + } + } + + @Override + public boolean removedByPlayer( @Nonnull IBlockState state, World world, @Nonnull BlockPos pos, @Nonnull EntityPlayer player, boolean willHarvest ) + { + PeripheralType type = getPeripheralType( world, pos ); + if( type == PeripheralType.WiredModemWithCable ) + { + RayTraceResult hit = state.collisionRayTrace( world, pos, WorldUtil.getRayStart( player ), WorldUtil.getRayEnd( player ) ); + if( hit != null ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileCable && tile.hasWorld() ) + { + TileCable cable = (TileCable) tile; + + ItemStack item; + + AxisAlignedBB bb = cable.getModemBounds(); + if( WorldUtil.isVecInsideInclusive( bb, hit.hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ) + { + world.setBlockState( pos, state.withProperty( Properties.MODEM, BlockCableModemVariant.None ), 3 ); + cable.networkChanged(); + item = PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ); + } + else + { + world.setBlockState( pos, state.withProperty( Properties.CABLE, false ), 3 ); + cable.networkChanged(); + item = PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ); + } + + if( !world.isRemote && !player.capabilities.isCreativeMode ) dropItem( world, pos, item ); + + return false; + } + } + } + + return super.removedByPlayer( state, world, pos, player, willHarvest ); + } + + @Override + public ItemStack getPickBlock( @Nonnull IBlockState state, RayTraceResult hit, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileCable && tile.hasWorld() ) + { + TileCable cable = (TileCable) tile; + PeripheralType type = getPeripheralType( state ); + + if( type == PeripheralType.WiredModemWithCable ) + { + if( hit == null || WorldUtil.isVecInsideInclusive( cable.getModemBounds(), hit.hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ) + { + return PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ); + } + else + { + return PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ); + } + } + else + { + return PeripheralItemFactory.create( type, null, 1 ); + } + } + + return PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ); + } + @Override @Deprecated public final boolean isOpaqueCube( IBlockState state ) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java index b463a0c25..212fe807f 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java @@ -46,8 +46,8 @@ import static dan200.computercraft.core.apis.ArgumentHelper.getString; public class TileCable extends TileModemBase implements IPacketNetwork { - private static final double MIN = 0.375; - private static final double MAX = 1 - MIN; + public static final double MIN = 0.375; + public static final double MAX = 1 - MIN; private static final AxisAlignedBB BOX_CENTRE = new AxisAlignedBB( MIN, MIN, MIN, MAX, MAX, MAX ); private static final AxisAlignedBB[] BOXES = new AxisAlignedBB[]{ diff --git a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java index ff7289a4d..a2785a429 100644 --- a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java @@ -6,11 +6,18 @@ package dan200.computercraft.shared.util; +import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; -import net.minecraft.util.*; -import net.minecraft.util.math.*; +import net.minecraft.util.EnumFacing; +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.World; import org.apache.commons.lang3.tuple.Pair; @@ -47,9 +54,9 @@ public class WorldUtil } // Check for entities - float xStretch = (Math.abs(vecDir.x) > 0.25f) ? 0.0f : 1.0f; - float yStretch = (Math.abs(vecDir.y) > 0.25f) ? 0.0f : 1.0f; - float zStretch = (Math.abs(vecDir.z) > 0.25f) ? 0.0f : 1.0f; + float xStretch = Math.abs(vecDir.x) > 0.25f ? 0.0f : 1.0f; + float yStretch = Math.abs(vecDir.y) > 0.25f ? 0.0f : 1.0f; + float zStretch = Math.abs(vecDir.z) > 0.25f ? 0.0f : 1.0f; AxisAlignedBB bigBox = new AxisAlignedBB( Math.min(vecStart.x, vecEnd.x) - 0.375f * xStretch, Math.min(vecStart.y, vecEnd.y) - 0.375f * yStretch, @@ -113,6 +120,35 @@ public class WorldUtil return null; } + public static Vec3d getRayStart( EntityLivingBase entity ) + { + return new Vec3d( entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ ); + } + + public static Vec3d getRayEnd( EntityPlayer player) { + double reach = 4.5; + if( player instanceof EntityPlayerMP ) + { + reach = ((EntityPlayerMP) player).interactionManager.getBlockReachDistance(); + } + else if( player.getEntityWorld().isRemote ) + { + reach = Minecraft.getMinecraft().playerController.getBlockReachDistance(); + } + else if( player.capabilities.isCreativeMode ) + { + reach = 5.0; + } + + Vec3d look = player.getLookVec(); + + return getRayStart( player ).addVector( look.x * reach, look.y * reach, look.z * reach ); + } + + public static boolean isVecInsideInclusive(AxisAlignedBB bb , Vec3d vec) { + return vec.x >= bb.minX && vec.x <= bb.maxX && vec.y >= bb.minY && vec.y <= bb.maxY && vec.z >= bb.minZ && vec.z <= bb.maxZ; + } + public static void dropItemStack( @Nonnull ItemStack stack, World world, BlockPos pos ) { dropItemStack( stack, world, pos, null ); From 75ccfbdb3d1788a3554604840010b88d38fc8f1b Mon Sep 17 00:00:00 2001 From: SquidDev Date: Thu, 11 May 2017 14:57:58 +0100 Subject: [PATCH 2/5] Migrate cable core block state to an enum This allows us to render the cable "core", as was done pre-1.8. --- .../shared/peripheral/common/BlockCable.java | 43 +++++++++++++----- .../common/BlockCableCableVariant.java | 28 ++++++++++++ .../shared/peripheral/common/ItemCable.java | 6 +-- .../computercraft/blockstates/cable.json | 12 +++-- .../computercraft/models/block/cable_arm.json | 2 +- .../models/block/cable_core_any.json | 21 +++++++++ ...cable_core.json => cable_core_facing.json} | 44 +++++++++---------- 7 files changed, 111 insertions(+), 45 deletions(-) create mode 100644 src/main/java/dan200/computercraft/shared/peripheral/common/BlockCableCableVariant.java create mode 100644 src/main/resources/assets/computercraft/models/block/cable_core_any.json rename src/main/resources/assets/computercraft/models/block/{cable_core.json => cable_core_facing.json} (89%) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java index 4e5d2419b..6a84ff0e4 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java @@ -41,7 +41,7 @@ public class BlockCable extends BlockPeripheralBase public static class Properties { public static final PropertyEnum MODEM = PropertyEnum.create( "modem", BlockCableModemVariant.class ); - public static final PropertyBool CABLE = PropertyBool.create( "cable" ); + public static final PropertyEnum CABLE = PropertyEnum.create( "cable", BlockCableCableVariant.class ); public static final PropertyBool NORTH = PropertyBool.create( "north" ); public static final PropertyBool SOUTH = PropertyBool.create( "south" ); public static final PropertyBool EAST = PropertyBool.create( "east" ); @@ -76,7 +76,7 @@ public class BlockCable extends BlockPeripheralBase setCreativeTab( ComputerCraft.mainCreativeTab ); setDefaultState( this.blockState.getBaseState() .withProperty( Properties.MODEM, BlockCableModemVariant.None ) - .withProperty( Properties.CABLE, true ) + .withProperty( Properties.CABLE, BlockCableCableVariant.ANY ) .withProperty( Properties.NORTH, false ) .withProperty( Properties.SOUTH, false ) .withProperty( Properties.EAST, false ) @@ -110,17 +110,17 @@ public class BlockCable extends BlockPeripheralBase IBlockState state = getDefaultState(); if( meta < 6 ) { - state = state.withProperty( Properties.CABLE, false ); + state = state.withProperty( Properties.CABLE, BlockCableCableVariant.NONE ); state = state.withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( EnumFacing.getFront( meta ) ) ); } else if( meta < 12 ) { - state = state.withProperty( Properties.CABLE, true ); + state = state.withProperty( Properties.CABLE, BlockCableCableVariant.ANY ); state = state.withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( EnumFacing.getFront( meta - 6 ) ) ); } else if( meta == 13 ) { - state = state.withProperty( Properties.CABLE, true ); + state = state.withProperty( Properties.CABLE, BlockCableCableVariant.ANY ); state = state.withProperty( Properties.MODEM, BlockCableModemVariant.None ); } return state; @@ -130,7 +130,7 @@ public class BlockCable extends BlockPeripheralBase public int getMetaFromState( IBlockState state ) { int meta = 0; - boolean cable = state.getValue( Properties.CABLE ); + boolean cable = state.getValue( Properties.CABLE ) != BlockCableCableVariant.NONE; BlockCableModemVariant modem = state.getValue( Properties.MODEM ); if( cable && modem != BlockCableModemVariant.None ) { @@ -155,20 +155,20 @@ public class BlockCable extends BlockPeripheralBase case Cable: { return getDefaultState() - .withProperty( Properties.CABLE, true ) + .withProperty( Properties.CABLE, BlockCableCableVariant.ANY ) .withProperty( Properties.MODEM, BlockCableModemVariant.None ); } case WiredModem: default: { return getDefaultState() - .withProperty( Properties.CABLE, false ) + .withProperty( Properties.CABLE, BlockCableCableVariant.ANY ) .withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( placedSide.getOpposite() ) ); } case WiredModemWithCable: { return getDefaultState() - .withProperty( Properties.CABLE, true ) + .withProperty( Properties.CABLE, BlockCableCableVariant.ANY ) .withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( placedSide.getOpposite() ) ); } } @@ -176,7 +176,7 @@ public class BlockCable extends BlockPeripheralBase private boolean doesConnect( IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing dir ) { - if( !state.getValue( Properties.CABLE ) ) + if( state.getValue( Properties.CABLE ) == BlockCableCableVariant.NONE ) { return false; } @@ -202,6 +202,25 @@ public class BlockCable extends BlockPeripheralBase state = state.withProperty( Properties.UP, doesConnect( state, world, pos, EnumFacing.UP ) ); state = state.withProperty( Properties.DOWN, doesConnect( state, world, pos, EnumFacing.DOWN ) ); + if( state.getValue( Properties.CABLE ) != BlockCableCableVariant.NONE ) + { + BlockCableCableVariant direction = null; + if( state.getValue( Properties.WEST ) || state.getValue( Properties.EAST ) ) + { + direction = direction == null ? BlockCableCableVariant.X_AXIS : BlockCableCableVariant.ANY; + } + if( state.getValue( Properties.DOWN ) || state.getValue( Properties.UP ) ) + { + direction = direction == null ? BlockCableCableVariant.Y_AXIS : BlockCableCableVariant.ANY; + } + if( state.getValue( Properties.NORTH ) || state.getValue( Properties.SOUTH ) ) + { + direction = direction == null ? BlockCableCableVariant.Z_AXIS : BlockCableCableVariant.ANY; + } + + state = state.withProperty( Properties.CABLE, direction == null ? BlockCableCableVariant.Z_AXIS : direction ); + } + int anim; TileEntity tile = world.getTileEntity( pos ); if( tile != null && tile instanceof TilePeripheralBase ) @@ -242,7 +261,7 @@ public class BlockCable extends BlockPeripheralBase @Override public PeripheralType getPeripheralType( IBlockState state ) { - boolean cable = state.getValue( Properties.CABLE ); + boolean cable = state.getValue( Properties.CABLE ) != BlockCableCableVariant.NONE; BlockCableModemVariant modem = state.getValue( Properties.MODEM ); if( cable && modem != BlockCableModemVariant.None ) { @@ -330,7 +349,7 @@ public class BlockCable extends BlockPeripheralBase } else { - world.setBlockState( pos, state.withProperty( Properties.CABLE, false ), 3 ); + world.setBlockState( pos, state.withProperty( Properties.CABLE, BlockCableCableVariant.NONE ), 3 ); cable.networkChanged(); item = PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCableCableVariant.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCableCableVariant.java new file mode 100644 index 000000000..f9a55f7ff --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCableCableVariant.java @@ -0,0 +1,28 @@ +package dan200.computercraft.shared.peripheral.common; + +import net.minecraft.util.IStringSerializable; + +import javax.annotation.Nonnull; + +public enum BlockCableCableVariant implements IStringSerializable +{ + NONE( "none" ), + ANY( "any" ), + X_AXIS( "x" ), + Y_AXIS( "y" ), + Z_AXIS( "z" ),; + + private final String m_name; + + BlockCableCableVariant( String name ) + { + m_name = name; + } + + @Override + @Nonnull + public String getName() + { + return m_name; + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/ItemCable.java b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemCable.java index 8ad66a8e4..792fe47b9 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/common/ItemCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/ItemCable.java @@ -89,12 +89,12 @@ public class ItemCable extends ItemPeripheralBase { if( !stack.isEmpty() ) { - IBlockState newState = existingState.withProperty( BlockCable.Properties.CABLE, true ); + IBlockState newState = existingState.withProperty( BlockCable.Properties.CABLE, BlockCableCableVariant.ANY ); world.setBlockState( pos, newState, 3 ); SoundType soundType = newState.getBlock().getSoundType( newState, world, pos, player ); world.playSound( null, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, soundType.getPlaceSound(), SoundCategory.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F ); stack.shrink( 1 ); - + TileEntity tile = world.getTileEntity( pos ); if( tile != null && tile instanceof TileCable ) { @@ -143,7 +143,7 @@ public class ItemCable extends ItemPeripheralBase { if( !stack.isEmpty() ) { - IBlockState newState = offsetExistingState.withProperty( BlockCable.Properties.CABLE, true ); + IBlockState newState = offsetExistingState.withProperty( BlockCable.Properties.CABLE, BlockCableCableVariant.ANY ); world.setBlockState( offset, newState, 3 ); SoundType soundType = newState.getBlock().getSoundType( newState, world, offset, player ); world.playSound( null, offset.getX() + 0.5, offset.getY() + 0.5, offset.getZ() + 0.5, soundType.getPlaceSound(), SoundCategory.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F ); diff --git a/src/main/resources/assets/computercraft/blockstates/cable.json b/src/main/resources/assets/computercraft/blockstates/cable.json index a4cea04e3..b06b69112 100644 --- a/src/main/resources/assets/computercraft/blockstates/cable.json +++ b/src/main/resources/assets/computercraft/blockstates/cable.json @@ -2,13 +2,11 @@ "forge_marker": 1, "variants": { "cable": { - "true": { - "submodel": { - "cable": { "model": "computercraft:cable_core" } - } - }, - "false": { - } + "none": { }, + "any": { "submodel": { "cable": { "model": "computercraft:cable_core_any" } } }, + "x": { "submodel": { "cable": { "model": "computercraft:cable_core_facing", "y": 90 } } }, + "y": { "submodel": { "cable": { "model": "computercraft:cable_core_facing", "x": 90 } } }, + "z": { "submodel": { "cable": { "model": "computercraft:cable_core_facing", "y": 0 } } } }, "up": { "true": { diff --git a/src/main/resources/assets/computercraft/models/block/cable_arm.json b/src/main/resources/assets/computercraft/models/block/cable_arm.json index 93d448067..9e407d854 100644 --- a/src/main/resources/assets/computercraft/models/block/cable_arm.json +++ b/src/main/resources/assets/computercraft/models/block/cable_arm.json @@ -6,7 +6,7 @@ }, "elements": [ { - "from": [ 6, 6, 10 ], + "from": [ 6, 6, 10 ], "to": [ 10, 10, 16 ], "faces": { "down": { "uv": [ 6, 0, 10, 6 ], "texture": "#side" }, diff --git a/src/main/resources/assets/computercraft/models/block/cable_core_any.json b/src/main/resources/assets/computercraft/models/block/cable_core_any.json new file mode 100644 index 000000000..05d4daeb6 --- /dev/null +++ b/src/main/resources/assets/computercraft/models/block/cable_core_any.json @@ -0,0 +1,21 @@ +{ + "parent": "block/block", + "textures": { + "particle": "computercraft:blocks/cable_core", + "side": "computercraft:blocks/cable_side" + }, + "elements": [ + { + "from": [ 6, 6, 6 ], + "to": [ 10, 10, 10 ], + "faces": { + "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" } + } + } + ] +} diff --git a/src/main/resources/assets/computercraft/models/block/cable_core.json b/src/main/resources/assets/computercraft/models/block/cable_core_facing.json similarity index 89% rename from src/main/resources/assets/computercraft/models/block/cable_core.json rename to src/main/resources/assets/computercraft/models/block/cable_core_facing.json index 52121908d..aa47ecf87 100644 --- a/src/main/resources/assets/computercraft/models/block/cable_core.json +++ b/src/main/resources/assets/computercraft/models/block/cable_core_facing.json @@ -1,22 +1,22 @@ -{ - "parent": "block/block", - "textures": { - "particle": "computercraft:blocks/cable_core", - "side": "computercraft:blocks/cable_side", - "end": "computercraft:blocks/cable_core" - }, - "elements": [ - { - "from": [ 6, 6, 6 ], - "to": [ 10, 10, 10 ], - "faces": { - "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, - "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, - "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, - "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, - "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, - "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" } - } - } - ] -} +{ + "parent": "block/block", + "textures": { + "particle": "computercraft:blocks/cable_core", + "side": "computercraft:blocks/cable_side", + "end": "computercraft:blocks/cable_core" + }, + "elements": [ + { + "from": [ 6, 6, 6 ], + "to": [ 10, 10, 10 ], + "faces": { + "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#end" }, + "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#end" }, + "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" }, + "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#side" } + } + } + ] +} From 7169abcd7baa55538661f1b68d707ff4d72d4626 Mon Sep 17 00:00:00 2001 From: SquidDev Date: Thu, 11 May 2017 15:47:14 +0100 Subject: [PATCH 3/5] Ensure the modem's peripheral is incorrectly invalidated when changed --- .../shared/peripheral/common/BlockCable.java | 25 ++++++++++++++++--- .../shared/peripheral/modem/TileCable.java | 22 +++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java index 6a84ff0e4..801f001cb 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/common/BlockCable.java @@ -17,6 +17,7 @@ import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.BlockFaceShape; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -76,7 +77,7 @@ public class BlockCable extends BlockPeripheralBase setCreativeTab( ComputerCraft.mainCreativeTab ); setDefaultState( this.blockState.getBaseState() .withProperty( Properties.MODEM, BlockCableModemVariant.None ) - .withProperty( Properties.CABLE, BlockCableCableVariant.ANY ) + .withProperty( Properties.CABLE, BlockCableCableVariant.NONE ) .withProperty( Properties.NORTH, false ) .withProperty( Properties.SOUTH, false ) .withProperty( Properties.EAST, false ) @@ -162,7 +163,7 @@ public class BlockCable extends BlockPeripheralBase default: { return getDefaultState() - .withProperty( Properties.CABLE, BlockCableCableVariant.ANY ) + .withProperty( Properties.CABLE, BlockCableCableVariant.NONE ) .withProperty( Properties.MODEM, BlockCableModemVariant.fromFacing( placedSide.getOpposite() ) ); } case WiredModemWithCable: @@ -344,16 +345,16 @@ public class BlockCable extends BlockPeripheralBase if( WorldUtil.isVecInsideInclusive( bb, hit.hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ) { world.setBlockState( pos, state.withProperty( Properties.MODEM, BlockCableModemVariant.None ), 3 ); - cable.networkChanged(); + cable.modemChanged(); item = PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ); } else { world.setBlockState( pos, state.withProperty( Properties.CABLE, BlockCableCableVariant.NONE ), 3 ); - cable.networkChanged(); item = PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ); } + cable.networkChanged(); if( !world.isRemote && !player.capabilities.isCreativeMode ) dropItem( world, pos, item ); return false; @@ -393,6 +394,22 @@ public class BlockCable extends BlockPeripheralBase return PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ); } + @Override + public void onBlockPlacedBy( World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack ) + { + TileEntity tile = world.getTileEntity( pos ); + if( tile != null && tile instanceof TileCable ) + { + TileCable cable = (TileCable) tile; + if( cable.getPeripheralType() != PeripheralType.WiredModem ) + { + cable.networkChanged(); + } + } + + super.onBlockPlacedBy( world, pos, state, placer, stack ); + } + @Override @Deprecated public final boolean isOpaqueCube( IBlockState state ) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java index 212fe807f..77e281416 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java @@ -359,6 +359,7 @@ public class TileCable extends TileModemBase ((BlockGeneric)getBlockType()).dropItem( getWorld(), getPos(), PeripheralItemFactory.create( PeripheralType.WiredModem, getLabel(), 1 ) ); setLabel( null ); setBlockState( getBlockState().withProperty( BlockCable.Properties.MODEM, BlockCableModemVariant.None ) ); + modemChanged(); break; } } @@ -682,7 +683,7 @@ public class TileCable extends TileModemBase { if( !getWorld().isRemote ) { - if( !m_destroyed ) + if( !m_destroyed && getPeripheralType() != PeripheralType.WiredModem) { // If this modem is alive, rebuild the network searchNetwork( ( modem, distance ) -> @@ -712,6 +713,25 @@ public class TileCable extends TileModemBase } } } + + public void modemChanged() + { + if( getWorld().isRemote ) return; + + PeripheralType type = getPeripheralType(); + if( type == PeripheralType.Cable ) + { + m_attachedPeripheralID = -1; + } + + if( type != PeripheralType.WiredModemWithCable && m_peripheralAccessAllowed ) + { + m_peripheralAccessAllowed = false; + } + + markDirty(); + updateAnim(); + } // private stuff From 6b364052c7dc33e64256bfdd4b23e9c5d2fa350d Mon Sep 17 00:00:00 2001 From: SquidDev Date: Thu, 11 May 2017 20:49:47 +0100 Subject: [PATCH 4/5] Only render breaking animation on the part being hit --- .../proxy/ComputerCraftProxyClient.java | 3 + .../render/TileEntityCableRenderer.java | 122 ++++++++++++++++++ .../shared/peripheral/modem/TileCable.java | 6 + 3 files changed, 131 insertions(+) create mode 100644 src/main/java/dan200/computercraft/client/render/TileEntityCableRenderer.java diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java index ad9267680..9f8cb5c5a 100644 --- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -9,6 +9,7 @@ package dan200.computercraft.client.proxy; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.gui.*; import dan200.computercraft.client.render.RenderOverlayCable; +import dan200.computercraft.client.render.TileEntityCableRenderer; import dan200.computercraft.client.render.TileEntityMonitorRenderer; import dan200.computercraft.shared.computer.blocks.ComputerState; import dan200.computercraft.shared.computer.blocks.TileComputer; @@ -20,6 +21,7 @@ import dan200.computercraft.shared.media.items.ItemDiskLegacy; import dan200.computercraft.shared.media.items.ItemPrintout; import dan200.computercraft.shared.network.ComputerCraftPacket; import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; +import dan200.computercraft.shared.peripheral.modem.TileCable; import dan200.computercraft.shared.peripheral.monitor.TileMonitor; import dan200.computercraft.shared.peripheral.printer.TilePrinter; import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; @@ -223,6 +225,7 @@ public class ComputerCraftProxyClient extends ComputerCraftProxyCommon // Setup renderers ClientRegistry.bindTileEntitySpecialRenderer( TileMonitor.class, new TileEntityMonitorRenderer() ); + ClientRegistry.bindTileEntitySpecialRenderer( TileCable.class, new TileEntityCableRenderer() ); } private void registerItemModel( Block block, int damage, String name ) diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityCableRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityCableRenderer.java new file mode 100644 index 000000000..fb125e929 --- /dev/null +++ b/src/main/java/dan200/computercraft/client/render/TileEntityCableRenderer.java @@ -0,0 +1,122 @@ +package dan200.computercraft.client.render; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.PeripheralType; +import dan200.computercraft.shared.peripheral.common.BlockCable; +import dan200.computercraft.shared.peripheral.common.BlockCableModemVariant; +import dan200.computercraft.shared.peripheral.modem.TileCable; +import dan200.computercraft.shared.util.WorldUtil; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderGlobal; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; +import net.minecraftforge.client.ForgeHooksClient; +import net.minecraftforge.client.MinecraftForgeClient; +import org.lwjgl.opengl.GL11; + +import javax.annotation.Nonnull; + +/** + * Render breaking animation only over part of a {@link TileCable}. + */ +public class TileEntityCableRenderer extends TileEntitySpecialRenderer +{ + @Override + public void render( @Nonnull TileCable te, double x, double y, double z, float partialTicks, int destroyStage, float alpha ) + { + if( destroyStage < 0 ) return; + + BlockPos pos = te.getPos(); + + Minecraft mc = Minecraft.getMinecraft(); + + RayTraceResult hit = mc.objectMouseOver; + if( hit == null || !hit.getBlockPos().equals( pos ) ) return; + + if( MinecraftForgeClient.getRenderPass() != 0 ) return; + + World world = te.getWorld(); + IBlockState state = world.getBlockState( pos ); + Block block = state.getBlock(); + if( block != ComputerCraft.Blocks.cable ) return; + + state = state.getActualState( world, pos ); + if( te.getPeripheralType() != PeripheralType.Cable && WorldUtil.isVecInsideInclusive( te.getModemBounds(), hit.hitVec.subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ) + { + state = block.getDefaultState().withProperty( BlockCable.Properties.MODEM, state.getValue( BlockCable.Properties.MODEM ) ); + } + else + { + state = state.withProperty( BlockCable.Properties.MODEM, BlockCableModemVariant.None ); + } + + IBakedModel model = mc.getBlockRendererDispatcher().getModelForState( state ); + if( model == null ) return; + + preRenderDamagedBlocks(); + + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.BLOCK ); + buffer.setTranslation( x - pos.getX(), y - pos.getY(), z - pos.getZ() ); + buffer.noColor(); + + ForgeHooksClient.setRenderLayer( block.getBlockLayer() ); + + // See BlockRendererDispatcher#renderBlockDamage + TextureAtlasSprite breakingTexture = mc.getTextureMapBlocks().getAtlasSprite( "minecraft:blocks/destroy_stage_" + destroyStage ); + Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelRenderer().renderModel( + world, + ForgeHooksClient.getDamageModel( model, breakingTexture, state, world, pos ), + state, pos, buffer, true + ); + + ForgeHooksClient.setRenderLayer( BlockRenderLayer.SOLID ); + + buffer.setTranslation( 0, 0, 0 ); + Tessellator.getInstance().draw(); + + postRenderDamagedBlocks(); + } + + /** + * @see RenderGlobal#preRenderDamagedBlocks() + */ + private void preRenderDamagedBlocks() + { + GlStateManager.disableLighting(); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate( GlStateManager.SourceFactor.DST_COLOR, GlStateManager.DestFactor.SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO ); + GlStateManager.enableBlend(); + GlStateManager.color( 1.0F, 1.0F, 1.0F, 0.5F ); + GlStateManager.doPolygonOffset( -3.0F, -3.0F ); + GlStateManager.enablePolygonOffset(); + GlStateManager.alphaFunc( 516, 0.1F ); + GlStateManager.enableAlpha(); + GlStateManager.pushMatrix(); + } + + /** + * @see RenderGlobal#postRenderDamagedBlocks() + */ + private void postRenderDamagedBlocks() + { + GlStateManager.disableAlpha(); + GlStateManager.doPolygonOffset( 0.0F, 0.0F ); + GlStateManager.disablePolygonOffset(); + GlStateManager.disablePolygonOffset(); + GlStateManager.depthMask( true ); + GlStateManager.popMatrix(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java index 77e281416..8c5600a14 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java @@ -1061,4 +1061,10 @@ public class TileCable extends TileModemBase } //System.out.println( "Visited "+visited+" common" ); } + + @Override + public boolean canRenderBreaking() + { + return true; + } } From fb6d65ec23df43db2e1d4ced013d041354ee01c3 Mon Sep 17 00:00:00 2001 From: SquidDev Date: Mon, 15 May 2017 09:46:40 +0100 Subject: [PATCH 5/5] Invalidate the network when the peripheral is removed Fixes #83 --- .../shared/peripheral/modem/TileCable.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java index 8c5600a14..579fd4967 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/TileCable.java @@ -359,7 +359,7 @@ public class TileCable extends TileModemBase ((BlockGeneric)getBlockType()).dropItem( getWorld(), getPos(), PeripheralItemFactory.create( PeripheralType.WiredModem, getLabel(), 1 ) ); setLabel( null ); setBlockState( getBlockState().withProperty( BlockCable.Properties.MODEM, BlockCableModemVariant.None ) ); - modemChanged(); + if( modemChanged() ) networkChanged(); break; } } @@ -714,9 +714,11 @@ public class TileCable extends TileModemBase } } - public void modemChanged() + public boolean modemChanged() { - if( getWorld().isRemote ) return; + if( getWorld().isRemote ) return false; + + boolean requiresUpdate = false; PeripheralType type = getPeripheralType(); if( type == PeripheralType.Cable ) @@ -727,10 +729,12 @@ public class TileCable extends TileModemBase if( type != PeripheralType.WiredModemWithCable && m_peripheralAccessAllowed ) { m_peripheralAccessAllowed = false; + requiresUpdate = true; + markDirty(); + updateAnim(); } - - markDirty(); - updateAnim(); + + return requiresUpdate; } // private stuff