Add better Pipe selection checking, open the gate GUI only if it has been clicked

This commit is contained in:
Player 2013-02-11 18:39:28 +01:00
parent e5c1af707f
commit bf22970fba

View file

@ -21,6 +21,7 @@ import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
@ -42,6 +43,20 @@ import buildcraft.transport.render.PipeWorldRenderer;
import cpw.mods.fml.common.registry.GameRegistry;
public class BlockGenericPipe extends BlockContainer {
static enum Part {
Pipe,
Gate
}
static class RaytraceResult {
RaytraceResult(Part hitPart, MovingObjectPosition movingObjectPosition) {
this.hitPart = hitPart;
this.movingObjectPosition = movingObjectPosition;
}
public Part hitPart;
public MovingObjectPosition movingObjectPosition;
}
/* Defined subprograms ************************************************* */
@ -213,42 +228,200 @@ public class BlockGenericPipe extends BlockContainer {
}
@Override
public MovingObjectPosition collisionRayTrace(World world, int i, int j, int k, Vec3 vec3d, Vec3 vec3d1) {
public MovingObjectPosition collisionRayTrace(World world, int x, int y, int z, Vec3 origin, Vec3 direction) {
RaytraceResult raytraceResult = doRayTrace(world, x, y, z, origin, direction);
if (raytraceResult == null) {
return null;
} else {
return raytraceResult.movingObjectPosition;
}
}
public RaytraceResult doRayTrace(World world, int x, int y, int z, EntityPlayer entityPlayer) {
double pitch = Math.toRadians(entityPlayer.rotationPitch);
double yaw = Math.toRadians(entityPlayer.rotationYaw);
double dirX = -Math.sin(yaw) * Math.cos(pitch);
double dirY = -Math.sin(pitch);
double dirZ = Math.cos(yaw) * Math.cos(pitch);
double reachDistance = 5;
if (entityPlayer instanceof EntityPlayerMP) {
reachDistance = ((EntityPlayerMP) entityPlayer).theItemInWorldManager.getBlockReachDistance();
}
Vec3 origin = Vec3.vec3dPool.getVecFromPool(entityPlayer.posX, entityPlayer.posY + 1.62 - entityPlayer.yOffset, entityPlayer.posZ);
Vec3 direction = origin.addVector(dirX * reachDistance, dirY * reachDistance, dirZ * reachDistance);
return doRayTrace(world, x, y, z, origin, direction);
}
public RaytraceResult doRayTrace(World world, int x, int y, int z, Vec3 origin, Vec3 direction) {
float xMin = Utils.pipeMinPos, xMax = Utils.pipeMaxPos, yMin = Utils.pipeMinPos, yMax = Utils.pipeMaxPos, zMin = Utils.pipeMinPos, zMax = Utils.pipeMaxPos;
TileEntity tile1 = world.getBlockTileEntity(i, j, k);
if (Utils.checkPipesConnections(world, tile1, i - 1, j, k)) {
TileEntity pipeTileEntity = world.getBlockTileEntity(x, y, z);
Pipe pipe = getPipe(world, x, y, z);
if (pipeTileEntity == null || !isValid(pipe)) {
return null;
}
/**
* pipe hits along x, y, and z axis, gate (all 6 sides) [and wires+facades]
*/
MovingObjectPosition[] hits = new MovingObjectPosition[] { null, null, null, null, null, null, null, null, null };
boolean needAxisCheck = false;
boolean needCenterCheck = true;
// check along the x axis
if (Utils.checkPipesConnections(world, pipeTileEntity, x - 1, y, z)) {
xMin = 0.0F;
needAxisCheck = true;
}
if (Utils.checkPipesConnections(world, tile1, i + 1, j, k)) {
if (Utils.checkPipesConnections(world, pipeTileEntity, x + 1, y, z)) {
xMax = 1.0F;
needAxisCheck = true;
}
if (needAxisCheck) {
setBlockBounds(xMin, yMin, zMin, xMax, yMax, zMax);
if (Utils.checkPipesConnections(world, tile1, i, j - 1, k)) {
hits[0] = super.collisionRayTrace(world, x, y, z, origin, direction);
xMin = Utils.pipeMinPos;
xMax = Utils.pipeMaxPos;
needAxisCheck = false;
needCenterCheck = false; // center already checked through this axis
}
// check along the y axis
if (Utils.checkPipesConnections(world, pipeTileEntity, x, y - 1, z)) {
yMin = 0.0F;
needAxisCheck = true;
}
if (Utils.checkPipesConnections(world, tile1, i, j + 1, k)) {
if (Utils.checkPipesConnections(world, pipeTileEntity, x, y + 1, z)) {
yMax = 1.0F;
needAxisCheck = true;
}
if (needAxisCheck) {
setBlockBounds(xMin, yMin, zMin, xMax, yMax, zMax);
if (Utils.checkPipesConnections(world, tile1, i, j, k - 1)) {
hits[1] = super.collisionRayTrace(world, x, y, z, origin, direction);
yMin = Utils.pipeMinPos;
yMax = Utils.pipeMaxPos;
needAxisCheck = false;
needCenterCheck = false; // center already checked through this axis
}
// check along the z axis
if (Utils.checkPipesConnections(world, pipeTileEntity, x, y, z - 1)) {
zMin = 0.0F;
needAxisCheck = true;
}
if (Utils.checkPipesConnections(world, tile1, i, j, k + 1)) {
if (Utils.checkPipesConnections(world, pipeTileEntity, x, y, z + 1)) {
zMax = 1.0F;
needAxisCheck = true;
}
if (needAxisCheck) {
setBlockBounds(xMin, yMin, zMin, xMax, yMax, zMax);
setBlockBounds(xMin, yMin, zMin, xMax, yMax, zMax);
hits[2] = super.collisionRayTrace(world, x, y, z, origin, direction);
zMin = Utils.pipeMinPos;
zMax = Utils.pipeMaxPos;
needAxisCheck = false;
needCenterCheck = false; // center already checked through this axis
}
// check center (only if no axis were checked/the pipe has no connections)
MovingObjectPosition r = super.collisionRayTrace(world, i, j, k, vec3d, vec3d1);
if (needCenterCheck) {
setBlockBounds(xMin, yMin, zMin, xMax, yMax, zMax);
hits[0] = super.collisionRayTrace(world, x, y, z, origin, direction);
}
// gates
if (pipe.hasGate()) {
for (int side = 0; side < 6; side++) {
setBlockBoundsToGate(ForgeDirection.VALID_DIRECTIONS[side]);
hits[3 + side] = super.collisionRayTrace(world, x, y, z, origin, direction);
}
}
// TODO: check wires, facades
// get closest hit
double minLengthSquared = Double.POSITIVE_INFINITY;
int minIndex = -1;
for (int i = 0; i < hits.length; i++) {
MovingObjectPosition hit = hits[i];
if (hit == null) continue;
double lengthSquared = hit.hitVec.squareDistanceTo(origin);
if (lengthSquared < minLengthSquared) {
minLengthSquared = lengthSquared;
minIndex = i;
}
}
// reset bounds
setBlockBounds(0, 0, 0, 1, 1, 1);
return r;
if (minIndex == -1) {
return null;
} else {
Part hitPart;
if (minIndex < 3) {
hitPart = Part.Pipe;
} else {
hitPart = Part.Gate;
}
return new RaytraceResult(hitPart, hits[minIndex]);
}
}
private void setBlockBoundsToGate(ForgeDirection dir) {
float min = Utils.pipeMinPos + 0.05F;
float max = Utils.pipeMaxPos - 0.05F;
switch (dir) {
case DOWN:
setBlockBounds(min, Utils.pipeMinPos - 0.10F, min, max, Utils.pipeMinPos, max);
break;
case UP:
setBlockBounds(min, Utils.pipeMaxPos, min, max, Utils.pipeMaxPos + 0.10F, max);
break;
case NORTH:
setBlockBounds(min, min, Utils.pipeMinPos - 0.10F, max, max, Utils.pipeMinPos);
break;
case SOUTH:
setBlockBounds(min, min, Utils.pipeMaxPos, max, max, Utils.pipeMaxPos + 0.10F);
break;
case WEST:
setBlockBounds(Utils.pipeMinPos - 0.10F, min, min, Utils.pipeMinPos, max, max);
break;
case EAST:
setBlockBounds(Utils.pipeMaxPos, min, min, Utils.pipeMaxPos + 0.10F, max, max);
break;
}
}
public static void removePipe(Pipe pipe) {
@ -376,12 +549,12 @@ public class BlockGenericPipe extends BlockContainer {
}
@Override
public boolean onBlockActivated(World world, int i, int j, int k, EntityPlayer entityplayer, int par6, float par7, float par8, float par9) {
super.onBlockActivated(world, i, j, k, entityplayer, par6, par7, par8, par9);
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityplayer, int par6, float xOffset, float yOffset, float zOffset) {
super.onBlockActivated(world, x, y, z, entityplayer, par6, xOffset, yOffset, zOffset);
world.notifyBlocksOfNeighborChange(i, j, k, BuildCraftTransport.genericPipeBlock.blockID);
world.notifyBlocksOfNeighborChange(x, y, z, BuildCraftTransport.genericPipeBlock.blockID);
Pipe pipe = getPipe(world, i, j, k);
Pipe pipe = getPipe(world, x, y, z);
if (isValid(pipe)) {
@ -404,7 +577,7 @@ public class BlockGenericPipe extends BlockContainer {
else if (entityplayer.getCurrentEquippedItem().getItem() instanceof IToolWrench)
// Only check the instance at this point. Call the IToolWrench
// interface callbacks for the individual pipe/logic calls
return pipe.blockActivated(world, i, j, k, entityplayer);
return pipe.blockActivated(world, x, y, z, entityplayer);
else if (entityplayer.getCurrentEquippedItem().getItem() == BuildCraftTransport.redPipeWire) {
if (!pipe.wireSet[IPipe.WireColor.Red.ordinal()]) {
pipe.wireSet[IPipe.WireColor.Red.ordinal()] = true;
@ -456,13 +629,23 @@ public class BlockGenericPipe extends BlockContainer {
pipe.container.scheduleRenderUpdate();
return true;
}
boolean openGateGui = false;
if (pipe.hasGate()) {
RaytraceResult rayTraceResult = doRayTrace(world, x, y, z, entityplayer);
if (rayTraceResult != null && rayTraceResult.hitPart == Part.Gate) {
openGateGui = true;
}
}
if (openGateGui) {
pipe.gate.openGui(entityplayer);
return true;
} else
return pipe.blockActivated(world, i, j, k, entityplayer);
return pipe.blockActivated(world, x, y, z, entityplayer);
}
return false;