package blusunrize.immersiveengineering.common.blocks; import blusunrize.immersiveengineering.api.IEProperties; import blusunrize.immersiveengineering.api.energy.wires.IImmersiveConnectable; import blusunrize.immersiveengineering.api.energy.wires.ImmersiveNetHandler; import blusunrize.immersiveengineering.api.energy.wires.TileEntityImmersiveConnectable; import blusunrize.immersiveengineering.api.shader.CapabilityShader; import blusunrize.immersiveengineering.client.models.IOBJModelCallback; import blusunrize.immersiveengineering.common.CommonProxy; import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.*; import blusunrize.immersiveengineering.common.util.Utils; import blusunrize.immersiveengineering.common.util.inventory.IEInventoryHandler; import blusunrize.immersiveengineering.common.util.inventory.IIEInventory; import net.minecraft.block.Block; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; import net.minecraft.block.properties.PropertyDirection; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; 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.EnumFacing.AxisDirection; import net.minecraft.util.EnumHand; 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 net.minecraftforge.client.model.obj.OBJModel.OBJState; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.common.property.Properties; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import javax.annotation.Nullable; import java.util.Collection; import java.util.List; public abstract class BlockIETileProvider<E extends Enum<E> & BlockIEBase.IBlockEnum> extends BlockIEBase<E> implements ITileEntityProvider, IColouredBlock { private boolean hasColours = false; public BlockIETileProvider(String name, Material material, PropertyEnum<E> mainProperty, Class<? extends ItemBlockIEBase> itemBlock, Object... additionalProperties) { super(name, material, mainProperty, itemBlock, additionalProperties); } @Override public List<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { return super.getDrops(world, pos, state, fortune); } @Override public void breakBlock(World world, BlockPos pos, IBlockState state) { TileEntity tile = world.getTileEntity(pos); if(tile != null && ( !(tile instanceof ITileDrop) || !((ITileDrop)tile).preventInventoryDrop())) { if(tile instanceof IIEInventory && ((IIEInventory)tile).getDroppedItems()!=null) { for(ItemStack s : ((IIEInventory)tile).getDroppedItems()) if(s!=null) spawnAsEntity(world, pos, s); } else if(tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null)) { IItemHandler h = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); if(h instanceof IEInventoryHandler) for(int i = 0; i < h.getSlots(); i++) if(h.getStackInSlot(i)!=null) { spawnAsEntity(world, pos, h.getStackInSlot(i)); ((IEInventoryHandler)h).setStackInSlot(i, null); } } } if(tile instanceof IHasDummyBlocks) { ((IHasDummyBlocks)tile).breakDummies(pos, state); } if(tile instanceof IImmersiveConnectable) if(!world.isRemote||!Minecraft.getMinecraft().isSingleplayer()) ImmersiveNetHandler.INSTANCE.clearAllConnectionsFor(Utils.toCC(tile),world, !world.isRemote&&world.getGameRules().getBoolean("doTileDrops")); super.breakBlock(world, pos, state); world.removeTileEntity(pos); } @Override public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, TileEntity tile, ItemStack stack) { if(tile instanceof ITileDrop) { ItemStack s = ((ITileDrop)tile).getTileDrop(player, state); if(s!=null) { spawnAsEntity(world, pos, s); return; } } if(tile instanceof IAdditionalDrops) { Collection<ItemStack> stacks = ((IAdditionalDrops)tile).getExtraDrops(player, state); if(stacks!=null && !stacks.isEmpty()) for(ItemStack s : stacks) if(s!=null) spawnAsEntity(world, pos, s); } super.harvestBlock(world, player, pos, state, tile, stack); } @Override public boolean canEntityDestroy(IBlockState state, IBlockAccess world, BlockPos pos, Entity entity) { TileEntity tile = world.getTileEntity(pos); if(tile instanceof IEntityProof) return ((IEntityProof)tile).canEntityDestroy(entity); return super.canEntityDestroy(state, world, pos, entity); } @Override public ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos, EntityPlayer player) { TileEntity tile = world.getTileEntity(pos); if(tile instanceof ITileDrop) { ItemStack s = ((ITileDrop)tile).getTileDrop(player, world.getBlockState(pos)); if(s!=null) return s; } Item item = Item.getItemFromBlock(this); return item == null ? null : new ItemStack(item, 1, this.damageDropped(world.getBlockState(pos))); } @Override public boolean eventReceived(IBlockState state, World worldIn, BlockPos pos, int eventID, int eventParam) { super.eventReceived(state, worldIn, pos, eventID, eventParam); TileEntity tileentity = worldIn.getTileEntity(pos); return tileentity != null && tileentity.receiveClientEvent(eventID, eventParam); } protected EnumFacing getDefaultFacing() { return EnumFacing.NORTH; } @Override public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos) { state = super.getActualState(state, world, pos); TileEntity tile = world.getTileEntity(pos); if(tile instanceof IAttachedIntegerProperies) { for(String s : ((IAttachedIntegerProperies)tile).getIntPropertyNames()) state = applyProperty(state, ((IAttachedIntegerProperies)tile).getIntProperty(s), ((IAttachedIntegerProperies)tile).getIntPropertyValue(s)); } if(tile instanceof IDirectionalTile && (state.getPropertyNames().contains(IEProperties.FACING_ALL) || state.getPropertyNames().contains(IEProperties.FACING_HORIZONTAL))) { PropertyDirection prop = state.getPropertyNames().contains(IEProperties.FACING_HORIZONTAL)?IEProperties.FACING_HORIZONTAL: IEProperties.FACING_ALL; state = applyProperty(state, prop, ((IDirectionalTile)tile).getFacing()); } else if(state.getPropertyNames().contains(IEProperties.FACING_HORIZONTAL)) state = state.withProperty(IEProperties.FACING_HORIZONTAL, getDefaultFacing()); else if(state.getPropertyNames().contains(IEProperties.FACING_ALL)) state = state.withProperty(IEProperties.FACING_ALL, getDefaultFacing()); if(tile instanceof IActiveState) { IProperty boolProp = ((IActiveState) tile).getBoolProperty(IActiveState.class); if(state.getPropertyNames().contains(boolProp)) state = applyProperty(state, boolProp, ((IActiveState) tile).getIsActive()); } if(tile instanceof IDualState) { IProperty boolProp = ((IDualState) tile).getBoolProperty(IDualState.class); if(state.getPropertyNames().contains(boolProp)) state = applyProperty(state, boolProp, ((IDualState) tile).getIsSecondState()); } if(tile instanceof TileEntityMultiblockPart) state = applyProperty(state, IEProperties.MULTIBLOCKSLAVE, ((TileEntityMultiblockPart)tile).isDummy()); else if(tile instanceof IHasDummyBlocks) state = applyProperty(state, IEProperties.MULTIBLOCKSLAVE, ((IHasDummyBlocks)tile).isDummy()); if(tile instanceof IMirrorAble) state = applyProperty(state, ((IMirrorAble)tile).getBoolProperty(IMirrorAble.class), ((IMirrorAble)tile).getIsMirrored()); return state; } @Override public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis) { TileEntity tile = world.getTileEntity(pos); if(tile instanceof IDirectionalTile) { if(!((IDirectionalTile)tile).canRotate(axis)) return false; IBlockState state = world.getBlockState(pos); if(state.getPropertyNames().contains(IEProperties.FACING_ALL) || state.getPropertyNames().contains(IEProperties.FACING_HORIZONTAL)) { PropertyDirection prop = state.getPropertyNames().contains(IEProperties.FACING_HORIZONTAL)?IEProperties.FACING_HORIZONTAL: IEProperties.FACING_ALL; EnumFacing f = ((IDirectionalTile)tile).getFacing(); int limit = ((IDirectionalTile)tile).getFacingLimitation(); if(limit==0) f = EnumFacing.VALUES[(f.ordinal() + 1) % EnumFacing.VALUES.length]; else if(limit==1) f = axis.getAxisDirection()==AxisDirection.POSITIVE?f.rotateAround(axis.getAxis()).getOpposite():f.rotateAround(axis.getAxis()); else if(limit == 2 || limit == 5) f = axis.getAxisDirection()==AxisDirection.POSITIVE?f.rotateY():f.rotateYCCW(); if(f != ((IDirectionalTile)tile).getFacing()) { EnumFacing old = ((IDirectionalTile)tile).getFacing(); ((IDirectionalTile)tile).setFacing(f); ((IDirectionalTile)tile).afterRotation(old,f); state = applyProperty(state, prop, ((IDirectionalTile)tile).getFacing()); world.setBlockState(pos, state.cycleProperty(prop)); } } } return false; } @Override public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos) { state = super.getExtendedState(state, world, pos); if(state instanceof IExtendedBlockState) { IExtendedBlockState extended = (IExtendedBlockState)state; TileEntity te = world.getTileEntity(pos); if(te!=null) { if(te instanceof IConfigurableSides) for(int i = 0; i < 6; i++) if(extended.getUnlistedNames().contains(IEProperties.SIDECONFIG[i])) extended = extended.withProperty(IEProperties.SIDECONFIG[i], ((IConfigurableSides)te).getSideConfig(i)); if(te instanceof IAdvancedHasObjProperty) extended = extended.withProperty(Properties.AnimationProperty, ((IAdvancedHasObjProperty)te).getOBJState()); else if(te instanceof IHasObjProperty) extended = extended.withProperty(Properties.AnimationProperty, new OBJState(((IHasObjProperty)te).compileDisplayList(), true)); if(te instanceof IDynamicTexture) extended = extended.withProperty(IEProperties.OBJ_TEXTURE_REMAP, ((IDynamicTexture)te).getTextureReplacements()); if(te instanceof IOBJModelCallback) extended = extended.withProperty(IOBJModelCallback.PROPERTY, (IOBJModelCallback)te); if(te.hasCapability(CapabilityShader.SHADER_CAPABILITY, null)) extended = extended.withProperty(CapabilityShader.BLOCKSTATE_PROPERTY, te.getCapability(CapabilityShader.SHADER_CAPABILITY, null)); if(te instanceof IPropertyPassthrough && ((IExtendedBlockState)state).getUnlistedNames().contains(IEProperties.TILEENTITY_PASSTHROUGH)) extended = extended.withProperty(IEProperties.TILEENTITY_PASSTHROUGH, te); if(te instanceof TileEntityImmersiveConnectable && ((IExtendedBlockState)state).getUnlistedNames().contains(IEProperties.CONNECTIONS)) extended = extended.withProperty(IEProperties.CONNECTIONS, ((TileEntityImmersiveConnectable)te).genConnBlockstate()); } state = extended; } return state; } @Override public void onIEBlockPlacedBy(World world, BlockPos pos, IBlockState state, EnumFacing side, float hitX, float hitY, float hitZ, EntityLivingBase placer, ItemStack stack) { TileEntity tile = world.getTileEntity(pos); if(tile instanceof IDirectionalTile) { EnumFacing f = ((IDirectionalTile)tile).getFacingForPlacement(placer, pos, side, hitX, hitY, hitZ); ((IDirectionalTile)tile).setFacing(f); if(tile instanceof IAdvancedDirectionalTile) ((IAdvancedDirectionalTile)tile).onDirectionalPlacement(side, hitX, hitY, hitZ, placer); } if(tile instanceof IHasDummyBlocks) { ((IHasDummyBlocks)tile).placeDummies(pos, state, side, hitX, hitY, hitZ); } if(tile instanceof ITileDrop) { ((ITileDrop)tile).readOnPlacement(placer, stack); } } @Override public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) { TileEntity tile = world.getTileEntity(pos); if(tile instanceof IConfigurableSides && Utils.isHammer(heldItem) && !world.isRemote) { int iSide = player.isSneaking()?side.getOpposite().ordinal():side.ordinal(); if(((IConfigurableSides)tile).toggleSide(iSide, player)) return true; } if(tile instanceof IDirectionalTile && Utils.isHammer(heldItem) && ((IDirectionalTile)tile).canHammerRotate(side, hitX, hitY, hitZ, player) && !world.isRemote) { EnumFacing f = ((IDirectionalTile)tile).getFacing(); int limit = ((IDirectionalTile)tile).getFacingLimitation(); if(limit==0) f = EnumFacing.VALUES[(f.ordinal() + 1) % EnumFacing.VALUES.length]; else if(limit==1) f = player.isSneaking()?f.rotateAround(side.getAxis()).getOpposite():f.rotateAround(side.getAxis()); else if(limit == 2 || limit == 5) f = player.isSneaking()?f.rotateYCCW():f.rotateY(); ((IDirectionalTile)tile).setFacing(f); tile.markDirty(); world.notifyBlockUpdate(pos,state,state,3); world.addBlockEvent(tile.getPos(), tile.getBlockType(), 255, 0); return true; } if(tile instanceof IHammerInteraction && Utils.isHammer(heldItem) && !world.isRemote) { boolean b = ((IHammerInteraction)tile).hammerUseSide(side, player, hitX, hitY, hitZ); if(b) return b; } if(tile instanceof IPlayerInteraction) { boolean b = ((IPlayerInteraction)tile).interact(side, player, hand, heldItem, hitX, hitY, hitZ); if(b) return b; } if(tile instanceof IGuiTile && hand == EnumHand.MAIN_HAND && !player.isSneaking()) { TileEntity master = ((IGuiTile)tile).getGuiMaster(); if(!world.isRemote && master!=null && ((IGuiTile)master).canOpenGui(player)) CommonProxy.openGuiForTile(player,(TileEntity & IGuiTile)master); return true; } return false; } @Override public void neighborChanged(IBlockState state, World world, BlockPos pos, Block blockIn) { TileEntity tile = world.getTileEntity(pos); if(tile instanceof INeighbourChangeTile && !tile.getWorld().isRemote) ((INeighbourChangeTile)tile).onNeighborBlockChange(pos); } @Override public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos) { TileEntity te = world.getTileEntity(pos); if(te instanceof ILightValue) return ((ILightValue)te).getLightValue(); return 0; } public BlockIETileProvider setHasColours() { this.hasColours = true; return this; } @Override public boolean hasCustomBlockColours() { return hasColours; } @Override public int getRenderColour(IBlockState state, @Nullable IBlockAccess worldIn, @Nullable BlockPos pos, int tintIndex) { if(worldIn!=null && pos!=null) { TileEntity tile = worldIn.getTileEntity(pos); if(tile instanceof IColouredTile) return ((IColouredTile)tile).getRenderColour(tintIndex); } return 0xffffff; } @Override public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos) { if(world.getBlockState(pos).getBlock()!=this) return FULL_BLOCK_AABB; else { TileEntity te = world.getTileEntity(pos); if(te instanceof IBlockBounds) { float[] bounds = ((IBlockBounds)te).getBlockBounds(); if(bounds!=null) return new AxisAlignedBB(bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5]); } } return super.getBoundingBox(state, world, pos); } @Override public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB mask, List<AxisAlignedBB> list, Entity ent) { TileEntity te = world.getTileEntity(pos); if(te instanceof IAdvancedCollisionBounds) { List<AxisAlignedBB> bounds = ((IAdvancedCollisionBounds)te).getAdvancedColisionBounds(); if(bounds!=null && !bounds.isEmpty()) { for(AxisAlignedBB aabb : bounds) if(aabb!=null && mask.intersectsWith(aabb)) list.add(aabb); return; } } super.addCollisionBoxToList(state, world, pos, mask, list, ent); } @Override public RayTraceResult collisionRayTrace(IBlockState state, World world, BlockPos pos, Vec3d start, Vec3d end) { TileEntity te = world.getTileEntity(pos); if(te instanceof IAdvancedSelectionBounds) { List<AxisAlignedBB> list = ((IAdvancedSelectionBounds)te).getAdvancedSelectionBounds(); if(list!=null && !list.isEmpty()) { for(AxisAlignedBB aabb : list) { RayTraceResult mop = this.rayTrace(pos, start, end, aabb.offset(-pos.getX(),-pos.getY(),-pos.getZ())); if(mop!=null) return mop; } return null; } } return super.collisionRayTrace(state, world, pos, start, end); } // public RayTraceResult doRaytrace(World world, BlockPos pos, Vec3d start, Vec3d end) // { // start = start.addVector((double)(-pos.getX()), (double)(-pos.getY()), (double)(-pos.getZ())); // end = end.addVector((double)(-pos.getX()), (double)(-pos.getY()), (double)(-pos.getZ())); // Vec3d vec3 = start.getIntermediateWithXValue(end, this.minX); // Vec3d vec31 = start.getIntermediateWithXValue(end, this.maxX); // Vec3d vec32 = start.getIntermediateWithYValue(end, this.minY); // Vec3d vec33 = start.getIntermediateWithYValue(end, this.maxY); // Vec3d vec34 = start.getIntermediateWithZValue(end, this.minZ); // Vec3d vec35 = start.getIntermediateWithZValue(end, this.maxZ); // // if(!this.isVecInsideYZBounds(vec3)) // vec3 = null; // if(!this.isVecInsideYZBounds(vec31)) // vec31 = null; // if(!this.isVecInsideXZBounds(vec32)) // vec32 = null; // if(!this.isVecInsideXZBounds(vec33)) // vec33 = null; // if(!this.isVecInsideXYBounds(vec34)) // vec34 = null; // if(!this.isVecInsideXYBounds(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; // return new RayTraceResult(vec36.addVector((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()), enumfacing, pos); // } // } // protected boolean isVecInsideYZBounds(Vec3d point) // { // return point != null && (point.yCoord >= this.minY && point.yCoord <= this.maxY && point.zCoord >= this.minZ && point.zCoord <= this.maxZ); // } // protected boolean isVecInsideXZBounds(Vec3d point) // { // return point != null && (point.xCoord >= this.minX && point.xCoord <= this.maxX && point.zCoord >= this.minZ && point.zCoord <= this.maxZ); // } // protected boolean isVecInsideXYBounds(Vec3d point) // { // return point != null && (point.xCoord >= this.minX && point.xCoord <= this.maxX && point.yCoord >= this.minY && point.yCoord <= this.maxY); // } @Override public boolean hasComparatorInputOverride(IBlockState state) { return true; } @Override public int getComparatorInputOverride(IBlockState state, World world, BlockPos pos) { TileEntity te = world.getTileEntity(pos); if(te instanceof IEBlockInterfaces.IComparatorOverride) return ((IEBlockInterfaces.IComparatorOverride)te).getComparatorInputOverride(); return 0; } @Override public int getWeakPower(IBlockState blockState, IBlockAccess world, BlockPos pos, EnumFacing side) { TileEntity te = world.getTileEntity(pos); if(te instanceof IEBlockInterfaces.IRedstoneOutput) return ((IEBlockInterfaces.IRedstoneOutput) te).getWeakRSOutput(blockState, side); return 0; } @Override public int getStrongPower(IBlockState blockState, IBlockAccess world, BlockPos pos, EnumFacing side) { TileEntity te = world.getTileEntity(pos); if(te instanceof IEBlockInterfaces.IRedstoneOutput) return ((IEBlockInterfaces.IRedstoneOutput) te).getStrongRSOutput(blockState, side); return 0; } @Override public boolean canProvidePower(IBlockState state) { return true; } @Override public boolean canConnectRedstone(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) { TileEntity te = world.getTileEntity(pos); if(te instanceof IEBlockInterfaces.IRedstoneOutput) return ((IEBlockInterfaces.IRedstoneOutput) te).canConnectRedstone(state, side); return false; } @Override public void onEntityCollidedWithBlock(World world, BlockPos pos, IBlockState state, Entity entity) { TileEntity te = world.getTileEntity(pos); if(te instanceof TileEntityIEBase) ((TileEntityIEBase)te).onEntityCollision(world, entity); } }