1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-11-11 02:43:14 +00:00

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.
This commit is contained in:
SquidDev
2017-05-09 23:03:42 +01:00
parent 19e4c03d3a
commit 728644c104
6 changed files with 385 additions and 11 deletions

View File

@@ -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 )

View File

@@ -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<AxisAlignedBB> bounds = new ArrayList<AxisAlignedBB>( 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 )

View File

@@ -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[]{

View File

@@ -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 );