package gregtech.api.multitileentity; import static gregtech.api.enums.GT_Values.OFFX; import static gregtech.api.enums.GT_Values.OFFY; import static gregtech.api.enums.GT_Values.OFFZ; import static gregtech.api.util.GT_Util.LAST_BROKEN_TILEENTITY; import static gregtech.api.util.GT_Util.getTileEntity; import static gregtech.api.util.GT_Util.setTileEntity; import java.util.ArrayList; import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.stats.StatList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.IIcon; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.StatCollector; import net.minecraft.world.Explosion; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.event.ForgeEventFactory; import com.cricketcraft.chisel.api.IFacade; import cpw.mods.fml.common.Optional; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.GregTech_API; import gregtech.api.enums.ItemList; import gregtech.api.enums.Textures; import gregtech.api.interfaces.IDebugableBlock; import gregtech.api.interfaces.tileentity.IDebugableTileEntity; import gregtech.api.metatileentity.BaseTileEntity; import gregtech.api.metatileentity.CoverableTileEntity; import gregtech.api.multitileentity.interfaces.IMultiTileEntity; import gregtech.api.objects.XSTR; import gregtech.api.util.GT_Log; import gregtech.api.util.GT_Util; import gregtech.common.covers.CoverInfo; import gregtech.common.render.GT_MultiTile_Renderer; /* * MultiTileEntityBlock ported from GT6 */ @Optional.Interface(iface = "com.cricketcraft.chisel.api.IFacade", modid = "ChiselAPI") public class MultiTileEntityBlock extends Block implements IDebugableBlock, ITileEntityProvider, IFacade { private static boolean LOCK = false; private boolean registered = false, normalCube; protected String internalName, toolName, materialName, modID; public String getName() { return String.join( ".", "gt.block.multiblock", materialName, stepSound.soundName, toolName, Boolean.toString(opaque), Boolean.toString(normalCube)); } public MultiTileEntityBlock(Material material) { super(material); if (GregTech_API.sPreloadFinished) throw new IllegalStateException("Blocks can only be initialized within preInit!"); } public MultiTileEntityBlock tool(String toolName) { this.toolName = toolName.toLowerCase(); return this; } public MultiTileEntityBlock sound(SoundType soundtype) { setStepSound(soundtype); return this; } public MultiTileEntityBlock opaque(Boolean opaque) { this.opaque = opaque; return this; } public MultiTileEntityBlock normalCube(Boolean normalCube) { this.normalCube = normalCube; return this; } public MultiTileEntityBlock modID(String modID) { this.modID = modID; return this; } public MultiTileEntityBlock materialName(String materialName) { this.materialName = materialName; return this; } public MultiTileEntityBlock register() { if (registered) throw new IllegalStateException("Block already registered " + internalName); if (GregTech_API.sPreloadFinished) throw new IllegalStateException("Blocks can only be initialized within preInit!"); registered = true; internalName = getName(); lightOpacity = isOpaqueCube() ? 255 : 0; GameRegistry.registerBlock(this, ItemBlock.class, internalName); return this; } @Override public final void breakBlock(World world, int x, int y, int z, Block block, int metadata) { final TileEntity tileEntity = getTileEntity(world, x, y, z, true); if (tileEntity != null) LAST_BROKEN_TILEENTITY.set(tileEntity); if (tileEntity == null || !tileEntity.shouldRefresh(this, block, metadata, metadata, world, x, y, z)) return; if (tileEntity instanceof IMultiTileEntity mute) mute.onBlockBroken(); // spotless:off // if (aTileEntity instanceof IMTE_HasMultiBlockMachineRelevantData // && ((IMTE_HasMultiBlockMachineRelevantData) aTileEntity).hasMultiBlockMachineRelevantData()) // GregTech_API.causeMachineUpdate(world, x, y, z); // spotless:on world.removeTileEntity(x, y, z); super.breakBlock(world, x, y, z, block, metadata); } @Override public ArrayList getDebugInfo(EntityPlayer aPlayer, int x, int y, int z, int aLogLevel) { final TileEntity tileEntity = aPlayer.worldObj.getTileEntity(x, y, z); if (tileEntity instanceof IDebugableTileEntity mte) { return mte.getDebugInfo(aPlayer, aLogLevel); } return new ArrayList<>(); } @Override public int getRenderType() { return GT_MultiTile_Renderer.INSTANCE == null ? super.getRenderType() : GT_MultiTile_Renderer.INSTANCE.getRenderId(); } @Override public final float getBlockHardness(World world, int x, int y, int z) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity ? ((IMultiTileEntity) tileEntity).getBlockHardness() : 1.0F; } @SideOnly(Side.CLIENT) @Override public IIcon getIcon(IBlockAccess aIBlockAccess, int x, int y, int z, int ordinalSide) { return Textures.BlockIcons.MACHINE_LV_SIDE.getIcon(); } @SideOnly(Side.CLIENT) @Override public IIcon getIcon(int ordinalSide, int meta) { return Textures.BlockIcons.MACHINE_LV_SIDE.getIcon(); } @Override @SuppressWarnings("unchecked") public final void addCollisionBoxesToList(World world, int x, int y, int z, AxisAlignedBB aAABB, List aList, Entity aEntity) { final TileEntity tileEntity = world.getTileEntity(x, y, z); if (tileEntity instanceof IMultiTileEntity) ((IMultiTileEntity) tileEntity).addCollisionBoxesToList(aAABB, aList, aEntity); else super.addCollisionBoxesToList(world, x, y, z, aAABB, aList, aEntity); } @Override public final AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity mte ? mte.getCollisionBoundingBoxFromPool() : tileEntity == null ? null : super.getCollisionBoundingBoxFromPool(world, x, y, z); } @Override public final AxisAlignedBB getSelectedBoundingBoxFromPool(World world, int x, int y, int z) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity mte ? mte.getSelectedBoundingBoxFromPool() : super.getSelectedBoundingBoxFromPool(world, x, y, z); } @Override public void setBlockBoundsBasedOnState(IBlockAccess blockAccess, int x, int y, int z) { final TileEntity tileEntity = blockAccess.getTileEntity(x, y, z); if (tileEntity instanceof IMultiTileEntity mte) { mte.setBlockBoundsBasedOnState(this); return; } super.setBlockBoundsBasedOnState(blockAccess, x, y, z); } @Override public final boolean isOpaqueCube() { return opaque; } @Override public final void onNeighborChange(IBlockAccess world, int x, int y, int z, int aTileX, int aTileY, int aTileZ) { final TileEntity tileEntity = world.getTileEntity(x, y, z); if (!LOCK) { LOCK = true; if (tileEntity instanceof BaseTileEntity) ((BaseTileEntity) tileEntity).onAdjacentBlockChange(aTileX, aTileY, aTileZ); LOCK = false; } } @Override public void onNeighborBlockChange(World world, int x, int y, int z, Block block) { final TileEntity tileEntity = world.getTileEntity(x, y, z); if (!LOCK) { LOCK = true; if (tileEntity instanceof BaseTileEntity bte) bte.onAdjacentBlockChange(x, y, z); LOCK = false; } if (tileEntity instanceof IMultiTileEntity change) change.onNeighborBlockChange(world, block); if (tileEntity == null) world.setBlockToAir(x, y, z); } @Override public final void onBlockAdded(World world, int x, int y, int z) { final TileEntity tileEntity = world.getTileEntity(x, y, z); if (tileEntity instanceof IMultiTileEntity mte) mte.onBlockAdded(); } @Override public float getPlayerRelativeBlockHardness(EntityPlayer aPlayer, World world, int x, int y, int z) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity mte && mte.privateAccess() && !((IMultiTileEntity) tileEntity).playerOwnsThis(aPlayer, true) ? -1.0F : super.getPlayerRelativeBlockHardness(aPlayer, world, x, y, z); } @Override public final void onBlockClicked(World world, int x, int y, int z, EntityPlayer aPlayer) { final TileEntity tileEntity = world.getTileEntity(x, y, z); if (tileEntity instanceof IMultiTileEntity mte) mte.onLeftClick(aPlayer); else super.onBlockClicked(world, x, y, z, aPlayer); } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer aPlayer, int ordinalSide, float aHitX, float aHitY, float aHitZ) { final TileEntity tileEntity = world.getTileEntity(x, y, z); if (aPlayer != null && ItemList.TC_Thaumometer.isStackEqual(aPlayer.getHeldItem(), true, true)) return false; return tileEntity instanceof IMultiTileEntity mte && mte.onBlockActivated(aPlayer, ForgeDirection.getOrientation(ordinalSide), aHitX, aHitY, aHitZ); } @Override public final int isProvidingWeakPower(IBlockAccess world, int x, int y, int z, int ordinalSide) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity power ? power.isProvidingWeakPower(ForgeDirection.getOrientation(ordinalSide)) : super.isProvidingWeakPower(world, x, y, z, ordinalSide); } @Override public final int isProvidingStrongPower(IBlockAccess world, int x, int y, int z, int ordinalSide) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity power ? power.isProvidingStrongPower(ForgeDirection.getOrientation(ordinalSide)) : super.isProvidingStrongPower(world, x, y, z, ordinalSide); } @Override public final boolean shouldCheckWeakPower(IBlockAccess world, int x, int y, int z, int ordinalSide) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity power ? power.shouldCheckWeakPower(ForgeDirection.getOrientation(ordinalSide)) : isNormalCube(world, x, y, z); } @Override public final boolean getWeakChanges(IBlockAccess world, int x, int y, int z) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity changes ? changes.getWeakChanges() : super.getWeakChanges(world, x, y, z); } @Override public final void harvestBlock(World world, EntityPlayer aPlayer, int x, int y, int z, int meta) { if (aPlayer == null) aPlayer = harvesters.get(); aPlayer.addStat(StatList.mineBlockStatArray[getIdFromBlock(this)], 1); aPlayer.addExhaustion(0.025F); final boolean aSilkTouch = EnchantmentHelper.getSilkTouchModifier(aPlayer); final int aFortune = EnchantmentHelper.getFortuneModifier(aPlayer); float aChance = 1.0F; final TileEntity tileEntity = getTileEntity(world, x, y, z, true); if (!(tileEntity instanceof IMultiTileEntity mte)) { return; } final ArrayList tList = mte.getDrops(aFortune, aSilkTouch); aChance = ForgeEventFactory .fireBlockHarvesting(tList, world, this, x, y, z, meta, aFortune, aChance, aSilkTouch, aPlayer); for (final ItemStack tStack : tList) if (XSTR.XSTR_INSTANCE.nextFloat() <= aChance) dropBlockAsItem(world, x, y, z, tStack); } @Override public final boolean shouldSideBeRendered(IBlockAccess world, int x, int y, int z, int ordinalSide) { final TileEntity tileEntity = world .getTileEntity(x - OFFX[ordinalSide], y - OFFY[ordinalSide], z - OFFZ[ordinalSide]); return tileEntity instanceof IMultiTileEntity mte ? mte.shouldSideBeRendered(ForgeDirection.getOrientation(ordinalSide)) : super.shouldSideBeRendered(world, x, y, z, ordinalSide); } @Override public Block getFacade(IBlockAccess world, int x, int y, int z, int ordinalSide) { final TileEntity tTileEntity = world.getTileEntity(x, y, z); if (tTileEntity instanceof CoverableTileEntity tile) { final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide); if (ordinalSide != -1) { final Block facadeBlock = tile.getCoverInfoAtSide(side) .getFacadeBlock(); if (facadeBlock != null) return facadeBlock; } else { // we do not allow more than one type of facade per block, so no need to check every side // see comment in gregtech.common.covers.GT_Cover_FacadeBase.isCoverPlaceable for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) { final Block facadeBlock = tile.getCoverInfoAtSide(tSide) .getFacadeBlock(); if (facadeBlock != null) { return facadeBlock; } } } } return Blocks.air; } @Override public int getFacadeMetadata(IBlockAccess world, int x, int y, int z, int ordinalSide) { final TileEntity tTileEntity = world.getTileEntity(x, y, z); if (tTileEntity instanceof CoverableTileEntity tile) { final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide); if (ordinalSide != -1) { final CoverInfo coverInfo = tile.getCoverInfoAtSide(side); final Block facadeBlock = coverInfo.getFacadeBlock(); if (facadeBlock != null) return coverInfo.getFacadeMeta(); } else { // we do not allow more than one type of facade per block, so no need to check every side // see comment in gregtech.common.covers.GT_Cover_FacadeBase.isCoverPlaceable for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) { final CoverInfo coverInfo = tile.getCoverInfoAtSide(tSide); final Block facadeBlock = coverInfo.getFacadeBlock(); if (facadeBlock != null) { return coverInfo.getFacadeMeta(); } } } } return 0; } @Override protected boolean canSilkHarvest() { return false; } @Override public final String getLocalizedName() { return StatCollector.translateToLocal(internalName + ".name"); } @Override public final String getUnlocalizedName() { return internalName; } @Override public final boolean onBlockEventReceived(World world, int x, int y, int z, int aID, int aData) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity == null || tileEntity.receiveClientEvent(aID, aData); } @Override public final void getSubBlocks(Item aItem, CreativeTabs aCreativeTab, List aList) { /**/ } @Override public boolean hasComparatorInputOverride() { return true; } @Override public final int getComparatorInputOverride(World world, int x, int y, int z, int ordinalSide) { final TileEntity tileEntity = world.getTileEntity(x, y, z); if (tileEntity instanceof IMultiTileEntity mute) { if (mute.hasComparatorInputOverride()) return mute.getComparatorInputOverride(ForgeDirection.getOrientation(ordinalSide)); else return mute.isProvidingWeakPower( ForgeDirection.getOrientation(ordinalSide) .getOpposite()); } return super.getComparatorInputOverride(world, x, y, z, ordinalSide); } @Override public final void registerBlockIcons(IIconRegister aIconRegister) { /* Do Nothing */ } @Override public final boolean isSideSolid(IBlockAccess world, int x, int y, int z, ForgeDirection side) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity mute ? mute.isSideSolid(side) : opaque; } @Override public boolean removedByPlayer(World world, EntityPlayer aPlayer, int x, int y, int z, boolean aWillHarvest) { final TileEntity tileEntity = GT_Util.getTileEntity(world, x, y, z, true); if (tileEntity != null) LAST_BROKEN_TILEENTITY.set(tileEntity); return super.removedByPlayer(world, aPlayer, x, y, z, aWillHarvest); } @Override public int getFlammability(IBlockAccess world, int x, int y, int z, ForgeDirection face) { return 0; } @Override public int getFireSpreadSpeed(IBlockAccess world, int x, int y, int z, ForgeDirection face) { return GregTech_API.sMachineFlammable && (world.getBlockMetadata(x, y, z) == 0) ? 100 : 0; } @Override public boolean hasTileEntity(int meta) { return true; } @Override public final ArrayList getDrops(World world, int x, int y, int z, int aUnusableMetaData, int aFortune) { final TileEntity tileEntity = getTileEntity(world, x, y, z, true); if (tileEntity instanceof IMultiTileEntity mute) return mute.getDrops(aFortune, false); return new ArrayList<>(); } @Override public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess world, int x, int y, int z) { return false; } @Override public final float getExplosionResistance(Entity aExploder, World world, int x, int y, int z, double aExplosionX, double aExplosionY, double aExplosionZ) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity mute ? mute.getExplosionResistance(aExploder, aExplosionX, aExplosionY, aExplosionZ) : 1.0F; } @Override public final void onBlockExploded(World world, int x, int y, int z, Explosion aExplosion) { if (world.isRemote) return; final TileEntity tileEntity = getTileEntity(world, x, y, z, true); if (tileEntity != null) LAST_BROKEN_TILEENTITY.set(tileEntity); if (tileEntity instanceof IMultiTileEntity mute) { GT_Log.exp.printf( "Explosion at : %d | %d | %d DIMID: %s due to near explosion!%n", x, y, z, world.provider.dimensionId); mute.onExploded(aExplosion); } else world.setBlockToAir(x, y, z); } @Override public final boolean canConnectRedstone(IBlockAccess world, int x, int y, int z, int ordinalSide) { return true; } @Override public final boolean recolourBlock(World world, int x, int y, int z, ForgeDirection side, int color) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity mute && mute.recolourBlock(side, (byte) color); } @Override public final String getHarvestTool(int meta) { return toolName; } @Override public int getHarvestLevel(int meta) { return meta % 4; } @Override public final boolean isToolEffective(String toolType, int meta) { return getHarvestTool(meta).equals(toolType); } @Override public final ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z, EntityPlayer aPlayer) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity mte ? mte.getPickBlock(target) : null; } @Override public final ItemStack getPickBlock(MovingObjectPosition target, World world, int x, int y, int z) { final TileEntity tileEntity = world.getTileEntity(x, y, z); return tileEntity instanceof IMultiTileEntity mte ? mte.getPickBlock(target) : null; } @Nullable public final IMultiTileEntity receiveMultiTileEntityData(@Nonnull IBlockAccess world, int x, int y, int z, int registryId, int aID) { if (!(world instanceof World)) return null; TileEntity tileEntity = world.getTileEntity(x, y, z); if (!(tileEntity instanceof IMultiTileEntity mute) || mute.getMultiTileEntityRegistryID() != registryId || mute.getMultiTileEntityID() != aID) { final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(registryId); if (tRegistry == null) return null; tileEntity = tRegistry.getNewTileEntity((World) world, x, y, z, aID); if (!(tileEntity instanceof IMultiTileEntity)) return null; setTileEntity((World) world, x, y, z, tileEntity, false); } return (IMultiTileEntity) tileEntity; } public void receiveCoverData(IMultiTileEntity mute, int aCover0, int aCover1, int aCover2, int aCover3, int aCover4, int aCover5) { boolean updated; updated = mute.setCoverIDAtSideNoUpdate(ForgeDirection.DOWN, aCover0); updated |= mute.setCoverIDAtSideNoUpdate(ForgeDirection.UP, aCover1); updated |= mute.setCoverIDAtSideNoUpdate(ForgeDirection.NORTH, aCover2); updated |= mute.setCoverIDAtSideNoUpdate(ForgeDirection.SOUTH, aCover3); updated |= mute.setCoverIDAtSideNoUpdate(ForgeDirection.WEST, aCover4); updated |= mute.setCoverIDAtSideNoUpdate(ForgeDirection.EAST, aCover5); if (updated) { mute.issueBlockUpdate(); } } @Override public final TileEntity createTileEntity(World world, int meta) { return null; } @Override public TileEntity createNewTileEntity(World world, int i) { return null; } }