Refined Storage

Refined Storage

77M Downloads

Give cables correct bounding box

raoulvdberge opened this issue ยท 20 comments

commented
commented

I override RayTraceResult collisionRayTrace(IBlockState blockState, World worldIn, BlockPos pos, Vec3d start, Vec3d end) in the block.

there do your raytracing to check if your cable is hit, to allow it to pass threw selecting blocks behind the cable.

then draw your own Highlight box in void DrawHighligth(DrawBlockHighlightEvent e)

i could post my functions if you want to take a look at those, they may not be to easy to read though as they get the boxes and so on from other classes.

for adding player collisions, that can be done in void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB mask, List list, Entity collidingEntity) in the block

commented

also to prevent the player taking damage when getting inside the block and to prevent the game thinking you are inside a solid block, you need to return false on the following functions,
isFullBlock
isFullCube
isBlockNormalCube

commented

Wiredly enough cables count as a whole bloc (when jumping) when standing on them but f5 shows them npt a full block

commented

Take a look at Redstone in 1.10 it changes hit boxes based on connections

commented

draw selectionbox is drawing lines,, point to point,

commented

@tomevoll I've got the collision box & raytracing stuff working, but can you give an example on the DrawBlockHighlightEvent? Thanks!

commented

` @SubscribeEvent
public void DrawHighligth(DrawBlockHighlightEvent e) {
if (e.getTarget() == null || e.getTarget().getBlockPos() == null)
return;

    if (!(e.getPlayer().worldObj.getTileEntity(e.getTarget().getBlockPos()) instanceof CableHandler)) return;


    e.setCanceled(true);

    List<AxisAlignedBB> bounds = new ArrayList<AxisAlignedBB>();

    CableHandler c = (CableHandler) e.getPlayer().worldObj.getTileEntity(e.getTarget().getBlockPos());

    if (c == null)
        return;

    for (int i = 0; i < c.sides.length; i++) {
        Connection con = c.sides[i];
        if (con != null) {
            for (CablePart part : c.parts[i]) {
                if (part.partType == EnumPart.CONNECTOR || part.partType == EnumPart.SLEVE) {
                    if (con.type == ConnectionType.EXTRACT || con.type == ConnectionType.OUTPUT)
                        bounds.addAll(part.bounds);
                }
                if (part.partType == EnumPart.CABLE) {
                    if (con.type == ConnectionType.EXTRACT || con.type == ConnectionType.OUTPUT || con.type == ConnectionType.NORMAL)
                        bounds.addAll(part.bounds);
                }
            }
        }
    }

    if (c.parts[6] != null) {
        for (CablePart part : c.parts[6]) {
            bounds.addAll(part.bounds);
        }
    }

    RayTraceResult res = Raytrace.collisionRayTrace(e.getPlayer().worldObj, e.getTarget().getBlockPos(), e.getPlayer(), bounds);
    if (res != null) {
        drawSelectionBox(e.getPlayer(), res.bounds, 0, e.getPartialTicks(), c);
        // ( System.out.println(res.hit.sideHit);
        return;
    }
    // System.out.println("NO HIT!!!");

}

public void drawSelectionBox(EntityPlayer player, AxisAlignedBB movingObjectPositionIn, int p_72731_3_, float partialTicks, TileEntity tile) {

    GlStateManager.enableBlend();
    GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
    GlStateManager.color(0.0F, 0.0F, 0.0F, 0.4F);
    GL11.glLineWidth(2.0F);
    GlStateManager.disableTexture2D();
    GlStateManager.depthMask(false);
    float f = 0.002F;

    double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks;
    double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks;
    double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks;

    drawSelectionBoundingBox(movingObjectPositionIn.expand(0.0020000000949949026D, 0.0020000000949949026D, 0.0020000000949949026D).offset(-d0, -d1, -d2).offset(tile.getPos().getX(), tile.getPos().getY(), tile.getPos().getZ()));

    GlStateManager.depthMask(true);
    GlStateManager.enableTexture2D();
    GlStateManager.disableBlend();

}

public static void drawSelectionBoundingBox(AxisAlignedBB boundingBox)
{
    Tessellator tessellator = Tessellator.getInstance();
    VertexBuffer vertexbuffer = tessellator.getBuffer();
    vertexbuffer.begin(3, DefaultVertexFormats.POSITION);
    vertexbuffer.pos(boundingBox.minX, boundingBox.minY, boundingBox.minZ).endVertex();
    vertexbuffer.pos(boundingBox.maxX, boundingBox.minY, boundingBox.minZ).endVertex();
    vertexbuffer.pos(boundingBox.maxX, boundingBox.minY, boundingBox.maxZ).endVertex();
    vertexbuffer.pos(boundingBox.minX, boundingBox.minY, boundingBox.maxZ).endVertex();
    vertexbuffer.pos(boundingBox.minX, boundingBox.minY, boundingBox.minZ).endVertex();
    tessellator.draw();
    vertexbuffer.begin(3, DefaultVertexFormats.POSITION);
    vertexbuffer.pos(boundingBox.minX, boundingBox.maxY, boundingBox.minZ).endVertex();
    vertexbuffer.pos(boundingBox.maxX, boundingBox.maxY, boundingBox.minZ).endVertex();
    vertexbuffer.pos(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ).endVertex();
    vertexbuffer.pos(boundingBox.minX, boundingBox.maxY, boundingBox.maxZ).endVertex();
    vertexbuffer.pos(boundingBox.minX, boundingBox.maxY, boundingBox.minZ).endVertex();
    tessellator.draw();
    vertexbuffer.begin(1, DefaultVertexFormats.POSITION);
    vertexbuffer.pos(boundingBox.minX, boundingBox.minY, boundingBox.minZ).endVertex();
    vertexbuffer.pos(boundingBox.minX, boundingBox.maxY, boundingBox.minZ).endVertex();
    vertexbuffer.pos(boundingBox.maxX, boundingBox.minY, boundingBox.minZ).endVertex();
    vertexbuffer.pos(boundingBox.maxX, boundingBox.maxY, boundingBox.minZ).endVertex();
    vertexbuffer.pos(boundingBox.maxX, boundingBox.minY, boundingBox.maxZ).endVertex();
    vertexbuffer.pos(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ).endVertex();
    vertexbuffer.pos(boundingBox.minX, boundingBox.minY, boundingBox.maxZ).endVertex();
    vertexbuffer.pos(boundingBox.minX, boundingBox.maxY, boundingBox.maxZ).endVertex();
    tessellator.draw();
}`
commented

cablehandler is basicly my conduit, that event will fire on every block u look at so make sure its your block first. raytrace will allow u to target blocks threw the transparent part of the cable since it isnt a full block

I also raytrace for hits on sub parts of my cable like the connectors, you may not need that

commented

to allow targeting blocks threw your block i override
@OverRide
public net.minecraft.util.math.RayTraceResult collisionRayTrace(IBlockState blockState, World worldIn, BlockPos pos, Vec3d start, Vec3d end) {

in the Block

commented

Thanks

What does Raytrace#collisionRayTrace do? Can't I use my own Block#collisionRayTrace?

RayTraceResult res = Raytrace.collisionRayTrace(e.getPlayer().worldObj, e.getTarget().getBlockPos(), e.getPlayer(), bounds);

commented

for me that raytrace the bounds of the block, or in my case all the sub parts, you can use your own

bounds is a list containing all the squares on my conduit thats visible on the cable im looking at, like the core, the extension, the connector so on

commented

This is my raytrace method:

@Override
    public RayTraceResult collisionRayTraceDefault(IBlockState state, World world, BlockPos pos, Vec3d start, Vec3d end) {
        List<RayTraceResult> list = Lists.<RayTraceResult>newArrayList();

        for (AxisAlignedBB axisalignedbb : getCollisionBoxList(this.getActualState(state, world, pos))) {
            list.add(this.rayTrace(pos, start, end, axisalignedbb));
        }

        RayTraceResult raytraceresult1 = null;
        double d1 = 0.0D;

        for (RayTraceResult raytraceresult : list) {
            if (raytraceresult != null) {
                double d0 = raytraceresult.hitVec.squareDistanceTo(end);

                if (d0 > d1) {
                    raytraceresult1 = raytraceresult;
                    d1 = d0;
                }
            }
        }

But how do I use it in the render highlight thing? What do I provide for "start" and "end" args?

Also you appear to be using RayTraceResult.bounds but that field does not exist..

commented

ya i use a custom raytrace class.

`
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;

import java.util.Collection;

public final class Raytrace {

private Raytrace() {

}

public static Vec3d getStart(EntityPlayer player) {

    return new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
}

public static Vec3d getEnd(EntityPlayer player) {

    double reachDistance = (player.capabilities.isCreativeMode ? 5.0D : 4.5D);
    Vec3d lookVec = player.getLookVec();
    Vec3d start = getStart(player);
    return start.addVector(lookVec.xCoord * reachDistance, lookVec.yCoord * reachDistance, lookVec.zCoord * reachDistance);
}

public static RayTraceResult collisionRayTrace(World world, BlockPos pos, EntityPlayer player, Collection<AxisAlignedBB> boxes) {

    return collisionRayTrace(world, pos, getStart(player), getEnd(player), boxes);
}

public static RayTraceResult collisionRayTrace(World world, BlockPos pos, EntityPlayer player, AxisAlignedBB aabb, int subHit, Object hitInfo) {

    return collisionRayTrace(pos, getStart(player), getEnd(player), aabb, subHit, hitInfo);
}

public static RayTraceResult collisionRayTrace(World world, BlockPos pos, Vec3d start, Vec3d end, Collection<AxisAlignedBB> boxes) {

    double minDistance = Double.POSITIVE_INFINITY;
    RayTraceResult hit = null;

    int i = -1;
    for (AxisAlignedBB aabb : boxes) {
        RayTraceResult result = aabb == null ? null : collisionRayTrace(pos, start, end, aabb, i, null);
        if (result != null) {
            double d = result.squareDistanceTo(start);
            if (d < minDistance) {
                minDistance = d;
                hit = result;
            }
        }
        i++;
    }

    return hit;
}

public static RayTraceResult collisionRayTrace(BlockPos pos, Vec3d start, Vec3d end, AxisAlignedBB bounds, int subHit, Object hitInfo) {

    start = start.addVector((-pos.getX()), (-pos.getY()), (-pos.getZ()));
    end = end.addVector((-pos.getX()), (-pos.getY()), (-pos.getZ()));

    Vec3d vec3 = start.getIntermediateWithXValue(end, bounds.minX);
    Vec3d vec31 = start.getIntermediateWithXValue(end, bounds.maxX);
    Vec3d vec32 = start.getIntermediateWithYValue(end, bounds.minY);
    Vec3d vec33 = start.getIntermediateWithYValue(end, bounds.maxY);
    Vec3d vec34 = start.getIntermediateWithZValue(end, bounds.minZ);
    Vec3d vec35 = start.getIntermediateWithZValue(end, bounds.maxZ);

    if (!isVecInsideYZBounds(bounds, vec3))
        vec3 = null;
    if (!isVecInsideYZBounds(bounds, vec31))
        vec31 = null;
    if (!isVecInsideXZBounds(bounds, vec32))
        vec32 = null;
    if (!isVecInsideXZBounds(bounds, vec33))
        vec33 = null;
    if (!isVecInsideXYBounds(bounds, vec34))
        vec34 = null;
    if (!isVecInsideXYBounds(bounds, vec35))
        vec35 = null;

    Vec3d vec36 = null;

    if (vec3 != null && (vec36 == null || start.squareDistanceTo(vec3) < start.squareDistanceTo(vec36)))
        vec36 = vec3;
    if (vec31 != null && (vec36 == null || start.squareDistanceTo(vec31) < start.squareDistanceTo(vec36)))
        vec36 = vec31;
    if (vec32 != null && (vec36 == null || start.squareDistanceTo(vec32) < start.squareDistanceTo(vec36)))
        vec36 = vec32;
    if (vec33 != null && (vec36 == null || start.squareDistanceTo(vec33) < start.squareDistanceTo(vec36)))
        vec36 = vec33;
    if (vec34 != null && (vec36 == null || start.squareDistanceTo(vec34) < start.squareDistanceTo(vec36)))
        vec36 = vec34;
    if (vec35 != null && (vec36 == null || start.squareDistanceTo(vec35) < start.squareDistanceTo(vec36)))
        vec36 = vec35;

    if (vec36 == null) {
        return null;
    } else {
        EnumFacing enumfacing = null;

        if (vec36 == vec3)
            enumfacing = EnumFacing.WEST;
        if (vec36 == vec31)
            enumfacing = EnumFacing.EAST;
        if (vec36 == vec32)
            enumfacing = EnumFacing.DOWN;
        if (vec36 == vec33)
            enumfacing = EnumFacing.UP;
        if (vec36 == vec34)
            enumfacing = EnumFacing.NORTH;
        if (vec36 == vec35)
            enumfacing = EnumFacing.SOUTH;
        //new net.minecraft.util.math.RayTraceResult(hitVecIn, sideHitIn, blockPosIn)
        net.minecraft.util.math.RayTraceResult mop = new net.minecraft.util.math.RayTraceResult(vec36.addVector(pos.getX(), pos.getY(), pos.getZ()), enumfacing, pos);
        mop.subHit = subHit;
        mop.hitInfo = hitInfo;
        return new RayTraceResult(mop, bounds);
    }
}

private static boolean isVecInsideYZBounds(AxisAlignedBB bounds, Vec3d vec) {

    return vec != null && (vec.yCoord >= bounds.minY && vec.yCoord <= bounds.maxY && vec.zCoord >= bounds.minZ && vec.zCoord <= bounds.maxZ);
}

private static boolean isVecInsideXZBounds(AxisAlignedBB bounds, Vec3d vec) {

    return vec != null && (vec.xCoord >= bounds.minX && vec.xCoord <= bounds.maxX && vec.zCoord >= bounds.minZ && vec.zCoord <= bounds.maxZ);
}

private static boolean isVecInsideXYBounds(AxisAlignedBB bounds, Vec3d vec) {

    return vec != null && (vec.xCoord >= bounds.minX && vec.xCoord <= bounds.maxX && vec.yCoord >= bounds.minY && vec.yCoord <= bounds.maxY);
}

private static class RayTraceResultBase<T extends RayTraceResult> {


    public final AxisAlignedBB bounds;
    public final net.minecraft.util.math.RayTraceResult hit;

    public RayTraceResultBase(net.minecraft.util.math.RayTraceResult mop, AxisAlignedBB bounds) {

        this.hit = mop;
        this.bounds = bounds;
    }

    public boolean valid() {

        return hit != null && bounds != null;
    }

    /*  public void setBounds(World world, BlockPos pos)
        {

            world.getBlockState(pos).getBlock().setBlockBounds((float) bounds.minX, (float) bounds.minY, (float) bounds.minZ, (float) bounds.maxX, (float) bounds.maxY, (float) bounds.maxZ);
        }
        */
    public double squareDistanceTo(Vec3d vec) {

        return hit.hitVec.squareDistanceTo(vec);
    }
}

public static class RayTraceResult extends RayTraceResultBase<RayTraceResult> {

    public RayTraceResult(net.minecraft.util.math.RayTraceResult mop, AxisAlignedBB bounds) {

        super(mop, bounds);
    }
}

}
`

commented

just easier imo, all i supply is the player, block position and the hitboxes to raytrace, end start all happends in that class

commented

Ah ty ^_^, actually MCMultiPart provides RayTraceUtils which is very similair to your util class. :)

commented

ya its possible that is where i got it from before they updated and modify it to work on 1.9+

commented

This is how i got it now:
x
I modified the code a little bit so it renders all the boxes (which is how I want it to be)

Only thing that is still bothering me is the fact that it renders each box individually, I want it to be 1 connected box as a whole, if you understand. Like this (where green is the box desired):

x

commented

do some checking and skip drawing lines between them i think would be the only way
maybe ship lines that touch,

commented

Well, how do I skip individual lines? I'd have to somehow change the mode from "normal box" to "line" right?

commented

Think I'm just gonna draw the union of all the AABB boxes, otherwise its too big of a pain. At least there is better collision now.

x