package net.minecraft.block; import java.util.ArrayList; import java.util.List; import java.util.Random; import net.minecraft.block.material.Material; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.item.EntityMinecart; import net.minecraft.init.Blocks; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.ChunkPosition; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; public abstract class BlockRailBase extends Block { protected final boolean isPowered; private static final String __OBFID = "CL_00000195"; /** * Returns true if the block at the coordinates of world passed is a valid rail block (current is rail, powered or * detector). */ public static final boolean isRailBlockAt(World p_150049_0_, int p_150049_1_, int p_150049_2_, int p_150049_3_) { /** * Return true if the parameter is a blockID for a valid rail block (current is rail, powered or detector). */ return isRailBlock(p_150049_0_.getBlock(p_150049_1_, p_150049_2_, p_150049_3_)); } /** * Return true if the parameter is a blockID for a valid rail block (current is rail, powered or detector). */ public static final boolean isRailBlock(Block p_150051_0_) { return p_150051_0_ instanceof BlockRailBase; } protected BlockRailBase(boolean p_i45389_1_) { super(Material.circuits); this.isPowered = p_i45389_1_; this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F); this.setCreativeTab(CreativeTabs.tabTransport); } /** * Returns true if the block is power related rail. */ public boolean isPowered() { return this.isPowered; } /** * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been * cleared to be reused) */ public AxisAlignedBB getCollisionBoundingBoxFromPool(World worldIn, int x, int y, int z) { return null; } public boolean isOpaqueCube() { return false; } public MovingObjectPosition collisionRayTrace(World worldIn, int x, int y, int z, Vec3 startVec, Vec3 endVec) { this.setBlockBoundsBasedOnState(worldIn, x, y, z); return super.collisionRayTrace(worldIn, x, y, z, startVec, endVec); } public void setBlockBoundsBasedOnState(IBlockAccess worldIn, int x, int y, int z) { int l = worldIn.getBlockMetadata(x, y, z); if (l >= 2 && l <= 5) { this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.625F, 1.0F); } else { this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F); } } public boolean renderAsNormalBlock() { return false; } /** * The type of render function that is called for this block */ public int getRenderType() { return renderType; } /** * Returns the quantity of items to drop on block destruction. */ public int quantityDropped(Random random) { return 1; } public boolean canPlaceBlockAt(World worldIn, int x, int y, int z) { return World.doesBlockHaveSolidTopSurface(worldIn, x, y - 1, z); } public void onBlockAdded(World worldIn, int x, int y, int z) { if (!worldIn.isRemote) { this.refreshTrackShape(worldIn, x, y, z, true); if (this.isPowered) { this.onNeighborBlockChange(worldIn, x, y, z, this); } } } public void onNeighborBlockChange(World worldIn, int x, int y, int z, Block neighbor) { if (!worldIn.isRemote) { int l = worldIn.getBlockMetadata(x, y, z); int i1 = l; if (this.isPowered) { i1 = l & 7; } boolean flag = false; if (!World.doesBlockHaveSolidTopSurface(worldIn, x, y - 1, z)) { flag = true; } if (i1 == 2 && !World.doesBlockHaveSolidTopSurface(worldIn, x + 1, y, z)) { flag = true; } if (i1 == 3 && !World.doesBlockHaveSolidTopSurface(worldIn, x - 1, y, z)) { flag = true; } if (i1 == 4 && !World.doesBlockHaveSolidTopSurface(worldIn, x, y, z - 1)) { flag = true; } if (i1 == 5 && !World.doesBlockHaveSolidTopSurface(worldIn, x, y, z + 1)) { flag = true; } if (flag) { this.dropBlockAsItem(worldIn, x, y, z, worldIn.getBlockMetadata(x, y, z), 0); worldIn.setBlockToAir(x, y, z); } else { this.onRedstoneSignal(worldIn, x, y, z, l, i1, neighbor); } } } /** * Called when the rail is given a redstone signal. */ protected void onRedstoneSignal(World p_150048_1_, int p_150048_2_, int p_150048_3_, int p_150048_4_, int p_150048_5_, int p_150048_6_, Block p_150048_7_) {} /** * Completely recalculates the track shape based on neighboring tracks. */ protected void refreshTrackShape(World p_150052_1_, int p_150052_2_, int p_150052_3_, int p_150052_4_, boolean p_150052_5_) { if (!p_150052_1_.isRemote) { (new BlockRailBase.Rail(p_150052_1_, p_150052_2_, p_150052_3_, p_150052_4_)).func_150655_a(p_150052_1_.isBlockIndirectlyGettingPowered(p_150052_2_, p_150052_3_, p_150052_4_), p_150052_5_); } } public int getMobilityFlag() { return 0; } public void breakBlock(World worldIn, int x, int y, int z, Block blockBroken, int meta) { int i1 = meta; if (this.isPowered) { i1 = meta & 7; } super.breakBlock(worldIn, x, y, z, blockBroken, meta); if (i1 == 2 || i1 == 3 || i1 == 4 || i1 == 5) { worldIn.notifyBlocksOfNeighborChange(x, y + 1, z, blockBroken); } if (this.isPowered) { worldIn.notifyBlocksOfNeighborChange(x, y, z, blockBroken); worldIn.notifyBlocksOfNeighborChange(x, y - 1, z, blockBroken); } } /* ======================================== FORGE START =====================================*/ /** * Return true if the rail can make corners. * Used by placement logic. * @param world The world. * @param x The rail X coordinate. * @param y The rail Y coordinate. * @param z The rail Z coordinate. * @return True if the rail can make corners. */ public boolean isFlexibleRail(IBlockAccess world, int y, int x, int z) { return !isPowered(); } /** * Returns true if the rail can make up and down slopes. * Used by placement logic. * @param world The world. * @param x The rail X coordinate. * @param y The rail Y coordinate. * @param z The rail Z coordinate. * @return True if the rail can make slopes. */ public boolean canMakeSlopes(IBlockAccess world, int x, int y, int z) { return true; } /** * Return the rail's metadata (without the power bit if the rail uses one). * Can be used to make the cart think the rail something other than it is, * for example when making diamond junctions or switches. * The cart parameter will often be null unless it it called from EntityMinecart. * * Valid rail metadata is defined as follows: * 0x0: flat track going North-South * 0x1: flat track going West-East * 0x2: track ascending to the East * 0x3: track ascending to the West * 0x4: track ascending to the North * 0x5: track ascending to the South * 0x6: WestNorth corner (connecting East and South) * 0x7: EastNorth corner (connecting West and South) * 0x8: EastSouth corner (connecting West and North) * 0x9: WestSouth corner (connecting East and North) * * @param world The world. * @param cart The cart asking for the metadata, null if it is not called by EntityMinecart. * @param y The rail X coordinate. * @param x The rail Y coordinate. * @param z The rail Z coordinate. * @return The metadata. */ public int getBasicRailMetadata(IBlockAccess world, EntityMinecart cart, int x, int y, int z) { int meta = world.getBlockMetadata(x, y, z); if(isPowered()) { meta = meta & 7; } return meta; } /** * Returns the max speed of the rail at the specified position. * @param world The world. * @param cart The cart on the rail, may be null. * @param x The rail X coordinate. * @param y The rail Y coordinate. * @param z The rail Z coordinate. * @return The max speed of the current rail. */ public float getRailMaxSpeed(World world, EntityMinecart cart, int y, int x, int z) { return 0.4f; } /** * This function is called by any minecart that passes over this rail. * It is called once per update tick that the minecart is on the rail. * @param world The world. * @param cart The cart on the rail. * @param y The rail X coordinate. * @param x The rail Y coordinate. * @param z The rail Z coordinate. */ public void onMinecartPass(World world, EntityMinecart cart, int y, int x, int z) { } /** * Forge: Moved render type to a field and a setter. * This allows for a mod to change the render type * for vanilla rails, and any mod rails that extend * this class. */ private int renderType = 9; public void setRenderType(int value) { renderType = value; } /* ======================================== FORGE END =====================================*/ public class Rail { private World field_150660_b; private int field_150661_c; private int field_150658_d; private int field_150659_e; private final boolean field_150656_f; private List field_150657_g = new ArrayList(); private static final String __OBFID = "CL_00000196"; private final boolean canMakeSlopes; public Rail(World p_i45388_2_, int p_i45388_3_, int p_i45388_4_, int p_i45388_5_) { this.field_150660_b = p_i45388_2_; this.field_150661_c = p_i45388_3_; this.field_150658_d = p_i45388_4_; this.field_150659_e = p_i45388_5_; BlockRailBase block = (BlockRailBase)p_i45388_2_.getBlock(p_i45388_3_, p_i45388_4_, p_i45388_5_); int l = block.getBasicRailMetadata(p_i45388_2_, null, p_i45388_3_, p_i45388_4_, p_i45388_5_); this.field_150656_f = !block.isFlexibleRail(p_i45388_2_, p_i45388_3_, p_i45388_4_, p_i45388_5_); canMakeSlopes = block.canMakeSlopes(p_i45388_2_, p_i45388_3_, p_i45388_4_, p_i45388_5_); this.func_150648_a(l); } private void func_150648_a(int p_150648_1_) { this.field_150657_g.clear(); if (p_150648_1_ == 0) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d, this.field_150659_e - 1)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d, this.field_150659_e + 1)); } else if (p_150648_1_ == 1) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c - 1, this.field_150658_d, this.field_150659_e)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c + 1, this.field_150658_d, this.field_150659_e)); } else if (p_150648_1_ == 2) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c - 1, this.field_150658_d, this.field_150659_e)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c + 1, this.field_150658_d + 1, this.field_150659_e)); } else if (p_150648_1_ == 3) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c - 1, this.field_150658_d + 1, this.field_150659_e)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c + 1, this.field_150658_d, this.field_150659_e)); } else if (p_150648_1_ == 4) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d + 1, this.field_150659_e - 1)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d, this.field_150659_e + 1)); } else if (p_150648_1_ == 5) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d, this.field_150659_e - 1)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d + 1, this.field_150659_e + 1)); } else if (p_150648_1_ == 6) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c + 1, this.field_150658_d, this.field_150659_e)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d, this.field_150659_e + 1)); } else if (p_150648_1_ == 7) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c - 1, this.field_150658_d, this.field_150659_e)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d, this.field_150659_e + 1)); } else if (p_150648_1_ == 8) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c - 1, this.field_150658_d, this.field_150659_e)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d, this.field_150659_e - 1)); } else if (p_150648_1_ == 9) { this.field_150657_g.add(new ChunkPosition(this.field_150661_c + 1, this.field_150658_d, this.field_150659_e)); this.field_150657_g.add(new ChunkPosition(this.field_150661_c, this.field_150658_d, this.field_150659_e - 1)); } } private void func_150651_b() { for (int i = 0; i < this.field_150657_g.size(); ++i) { BlockRailBase.Rail rail = this.func_150654_a((ChunkPosition)this.field_150657_g.get(i)); if (rail != null && rail.func_150653_a(this)) { this.field_150657_g.set(i, new ChunkPosition(rail.field_150661_c, rail.field_150658_d, rail.field_150659_e)); } else { this.field_150657_g.remove(i--); } } } /** * Rail Logic wrapper for BlockRailBase's isRailBlockAt. */ private boolean isRailBlockAt(int p_150646_1_, int p_150646_2_, int p_150646_3_) { return BlockRailBase.isRailBlockAt(this.field_150660_b, p_150646_1_, p_150646_2_, p_150646_3_) ? true : (BlockRailBase.isRailBlockAt(this.field_150660_b, p_150646_1_, p_150646_2_ + 1, p_150646_3_) ? true : BlockRailBase.isRailBlockAt(this.field_150660_b, p_150646_1_, p_150646_2_ - 1, p_150646_3_)); } private BlockRailBase.Rail func_150654_a(ChunkPosition p_150654_1_) { return BlockRailBase.isRailBlockAt(this.field_150660_b, p_150654_1_.chunkPosX, p_150654_1_.chunkPosY, p_150654_1_.chunkPosZ) ? BlockRailBase.this.new Rail(this.field_150660_b, p_150654_1_.chunkPosX, p_150654_1_.chunkPosY, p_150654_1_.chunkPosZ) : (BlockRailBase.isRailBlockAt(this.field_150660_b, p_150654_1_.chunkPosX, p_150654_1_.chunkPosY + 1, p_150654_1_.chunkPosZ) ? BlockRailBase.this.new Rail(this.field_150660_b, p_150654_1_.chunkPosX, p_150654_1_.chunkPosY + 1, p_150654_1_.chunkPosZ) : (BlockRailBase.isRailBlockAt(this.field_150660_b, p_150654_1_.chunkPosX, p_150654_1_.chunkPosY - 1, p_150654_1_.chunkPosZ) ? BlockRailBase.this.new Rail(this.field_150660_b, p_150654_1_.chunkPosX, p_150654_1_.chunkPosY - 1, p_150654_1_.chunkPosZ) : null)); } private boolean func_150653_a(BlockRailBase.Rail p_150653_1_) { for (int i = 0; i < this.field_150657_g.size(); ++i) { ChunkPosition chunkposition = (ChunkPosition)this.field_150657_g.get(i); if (chunkposition.chunkPosX == p_150653_1_.field_150661_c && chunkposition.chunkPosZ == p_150653_1_.field_150659_e) { return true; } } return false; } private boolean func_150652_b(int p_150652_1_, int p_150652_2_, int p_150652_3_) { for (int l = 0; l < this.field_150657_g.size(); ++l) { ChunkPosition chunkposition = (ChunkPosition)this.field_150657_g.get(l); if (chunkposition.chunkPosX == p_150652_1_ && chunkposition.chunkPosZ == p_150652_3_) { return true; } } return false; } /** * Counts the number of rails adjacent to this rail. */ protected int countAdjacentRails() { int i = 0; if (this.isRailBlockAt(this.field_150661_c, this.field_150658_d, this.field_150659_e - 1)) { ++i; } if (this.isRailBlockAt(this.field_150661_c, this.field_150658_d, this.field_150659_e + 1)) { ++i; } if (this.isRailBlockAt(this.field_150661_c - 1, this.field_150658_d, this.field_150659_e)) { ++i; } if (this.isRailBlockAt(this.field_150661_c + 1, this.field_150658_d, this.field_150659_e)) { ++i; } return i; } private boolean func_150649_b(BlockRailBase.Rail p_150649_1_) { return this.func_150653_a(p_150649_1_) ? true : (this.field_150657_g.size() == 2 ? false : (this.field_150657_g.isEmpty() ? true : true)); } private void func_150645_c(BlockRailBase.Rail p_150645_1_) { this.field_150657_g.add(new ChunkPosition(p_150645_1_.field_150661_c, p_150645_1_.field_150658_d, p_150645_1_.field_150659_e)); boolean flag = this.func_150652_b(this.field_150661_c, this.field_150658_d, this.field_150659_e - 1); boolean flag1 = this.func_150652_b(this.field_150661_c, this.field_150658_d, this.field_150659_e + 1); boolean flag2 = this.func_150652_b(this.field_150661_c - 1, this.field_150658_d, this.field_150659_e); boolean flag3 = this.func_150652_b(this.field_150661_c + 1, this.field_150658_d, this.field_150659_e); byte b0 = -1; if (flag || flag1) { b0 = 0; } if (flag2 || flag3) { b0 = 1; } if (!this.field_150656_f) { if (flag1 && flag3 && !flag && !flag2) { b0 = 6; } if (flag1 && flag2 && !flag && !flag3) { b0 = 7; } if (flag && flag2 && !flag1 && !flag3) { b0 = 8; } if (flag && flag3 && !flag1 && !flag2) { b0 = 9; } } if (b0 == 0 && canMakeSlopes) { if (BlockRailBase.isRailBlockAt(this.field_150660_b, this.field_150661_c, this.field_150658_d + 1, this.field_150659_e - 1)) { b0 = 4; } if (BlockRailBase.isRailBlockAt(this.field_150660_b, this.field_150661_c, this.field_150658_d + 1, this.field_150659_e + 1)) { b0 = 5; } } if (b0 == 1 && canMakeSlopes) { if (BlockRailBase.isRailBlockAt(this.field_150660_b, this.field_150661_c + 1, this.field_150658_d + 1, this.field_150659_e)) { b0 = 2; } if (BlockRailBase.isRailBlockAt(this.field_150660_b, this.field_150661_c - 1, this.field_150658_d + 1, this.field_150659_e)) { b0 = 3; } } if (b0 < 0) { b0 = 0; } int i = b0; if (this.field_150656_f) { i = this.field_150660_b.getBlockMetadata(this.field_150661_c, this.field_150658_d, this.field_150659_e) & 8 | b0; } this.field_150660_b.setBlockMetadataWithNotify(this.field_150661_c, this.field_150658_d, this.field_150659_e, i, 3); } private boolean func_150647_c(int p_150647_1_, int p_150647_2_, int p_150647_3_) { BlockRailBase.Rail rail = this.func_150654_a(new ChunkPosition(p_150647_1_, p_150647_2_, p_150647_3_)); if (rail == null) { return false; } else { rail.func_150651_b(); return rail.func_150649_b(this); } } public void func_150655_a(boolean p_150655_1_, boolean p_150655_2_) { boolean flag2 = this.func_150647_c(this.field_150661_c, this.field_150658_d, this.field_150659_e - 1); boolean flag3 = this.func_150647_c(this.field_150661_c, this.field_150658_d, this.field_150659_e + 1); boolean flag4 = this.func_150647_c(this.field_150661_c - 1, this.field_150658_d, this.field_150659_e); boolean flag5 = this.func_150647_c(this.field_150661_c + 1, this.field_150658_d, this.field_150659_e); byte b0 = -1; if ((flag2 || flag3) && !flag4 && !flag5) { b0 = 0; } if ((flag4 || flag5) && !flag2 && !flag3) { b0 = 1; } if (!this.field_150656_f) { if (flag3 && flag5 && !flag2 && !flag4) { b0 = 6; } if (flag3 && flag4 && !flag2 && !flag5) { b0 = 7; } if (flag2 && flag4 && !flag3 && !flag5) { b0 = 8; } if (flag2 && flag5 && !flag3 && !flag4) { b0 = 9; } } if (b0 == -1) { if (flag2 || flag3) { b0 = 0; } if (flag4 || flag5) { b0 = 1; } if (!this.field_150656_f) { if (p_150655_1_) { if (flag3 && flag5) { b0 = 6; } if (flag4 && flag3) { b0 = 7; } if (flag5 && flag2) { b0 = 9; } if (flag2 && flag4) { b0 = 8; } } else { if (flag2 && flag4) { b0 = 8; } if (flag5 && flag2) { b0 = 9; } if (flag4 && flag3) { b0 = 7; } if (flag3 && flag5) { b0 = 6; } } } } if (b0 == 0 && canMakeSlopes) { if (BlockRailBase.isRailBlockAt(this.field_150660_b, this.field_150661_c, this.field_150658_d + 1, this.field_150659_e - 1)) { b0 = 4; } if (BlockRailBase.isRailBlockAt(this.field_150660_b, this.field_150661_c, this.field_150658_d + 1, this.field_150659_e + 1)) { b0 = 5; } } if (b0 == 1 && canMakeSlopes) { if (BlockRailBase.isRailBlockAt(this.field_150660_b, this.field_150661_c + 1, this.field_150658_d + 1, this.field_150659_e)) { b0 = 2; } if (BlockRailBase.isRailBlockAt(this.field_150660_b, this.field_150661_c - 1, this.field_150658_d + 1, this.field_150659_e)) { b0 = 3; } } if (b0 < 0) { b0 = 0; } this.func_150648_a(b0); int i = b0; if (this.field_150656_f) { i = this.field_150660_b.getBlockMetadata(this.field_150661_c, this.field_150658_d, this.field_150659_e) & 8 | b0; } if (p_150655_2_ || this.field_150660_b.getBlockMetadata(this.field_150661_c, this.field_150658_d, this.field_150659_e) != i) { this.field_150660_b.setBlockMetadataWithNotify(this.field_150661_c, this.field_150658_d, this.field_150659_e, i, 3); for (int j = 0; j < this.field_150657_g.size(); ++j) { BlockRailBase.Rail rail = this.func_150654_a((ChunkPosition)this.field_150657_g.get(j)); if (rail != null) { rail.func_150651_b(); if (rail.func_150649_b(this)) { rail.func_150645_c(this); } } } } } } }