diff --git a/src/main/java/gregtech/client/renderer/handler/GTExplosiveRenderer.java b/src/main/java/gregtech/client/renderer/handler/GTExplosiveRenderer.java new file mode 100644 index 00000000000..4b0efe1ae63 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/handler/GTExplosiveRenderer.java @@ -0,0 +1,81 @@ +package gregtech.client.renderer.handler; + +import gregtech.common.entities.EntityGTExplosive; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; + +@SideOnly(Side.CLIENT) +public class GTExplosiveRenderer extends Render { + + public GTExplosiveRenderer(RenderManager renderManager) { + super(renderManager); + this.shadowSize = 0.5F; + } + + @Override + public void doRender(@NotNull T entity, double x, double y, double z, float entityYaw, float partialTicks) { + BlockRendererDispatcher brd = Minecraft.getMinecraft().getBlockRendererDispatcher(); + GlStateManager.pushMatrix(); + GlStateManager.translate((float) x, (float) y + 0.5F, (float) z); + float f2; + if ((float) entity.getFuse() - partialTicks + 1.0F < 10.0F) { + f2 = 1.0F - ((float) entity.getFuse() - partialTicks + 1.0F) / 10.0F; + f2 = MathHelper.clamp(f2, 0.0F, 1.0F); + f2 *= f2; + f2 *= f2; + float f1 = 1.0F + f2 * 0.3F; + GlStateManager.scale(f1, f1, f1); + } + + f2 = (1.0F - ((float) entity.getFuse() - partialTicks + 1.0F) / 100.0F) * 0.8F; + this.bindEntityTexture(entity); + GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.translate(-0.5F, -0.5F, 0.5F); + + IBlockState state = entity.getExplosiveState(); + brd.renderBlockBrightness(state, entity.getBrightness()); + GlStateManager.translate(0.0F, 0.0F, 1.0F); + if (this.renderOutlines) { + GlStateManager.enableColorMaterial(); + GlStateManager.enableOutlineMode(this.getTeamColor(entity)); + brd.renderBlockBrightness(state, 1.0F); + GlStateManager.disableOutlineMode(); + GlStateManager.disableColorMaterial(); + } else if (entity.getFuse() / 5 % 2 == 0) { + GlStateManager.disableTexture2D(); + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.DST_ALPHA); + GlStateManager.color(1.0F, 1.0F, 1.0F, f2); + GlStateManager.doPolygonOffset(-3.0F, -3.0F); + GlStateManager.enablePolygonOffset(); + brd.renderBlockBrightness(state, 1.0F); + GlStateManager.doPolygonOffset(0.0F, 0.0F); + GlStateManager.disablePolygonOffset(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.disableBlend(); + GlStateManager.enableLighting(); + GlStateManager.enableTexture2D(); + } + + GlStateManager.popMatrix(); + super.doRender(entity, x, y, z, entityYaw, partialTicks); + } + + @Override + protected ResourceLocation getEntityTexture(@NotNull T entity) { + return TextureMap.LOCATION_BLOCKS_TEXTURE; + } +} diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index f8a956e201b..b9927847cd4 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -153,6 +153,8 @@ public static void registerBlocks(RegistryEvent.Register event) { registry.register(RUBBER_WOOD_DOOR); registry.register(TREATED_WOOD_DOOR); registry.register(BRITTLE_CHARCOAL); + registry.register(POWDERBARREL); + registry.register(ITNT); registry.register(METAL_SHEET); registry.register(LARGE_METAL_SHEET); registry.register(STUDS); @@ -273,6 +275,8 @@ public static void registerItems(RegistryEvent.Register event) { registry.register(createItemBlock(RUBBER_LOG, ItemBlock::new)); registry.register(createItemBlock(RUBBER_LEAVES, ItemBlock::new)); registry.register(createItemBlock(RUBBER_SAPLING, ItemBlock::new)); + registry.register(createItemBlock(POWDERBARREL, ItemBlock::new)); + registry.register(createItemBlock(ITNT, ItemBlock::new)); for (BlockCompressed block : COMPRESSED_BLOCKS) { registry.register(createItemBlock(block, b -> new MaterialItemBlock(b, OrePrefix.block))); diff --git a/src/main/java/gregtech/common/EventHandlers.java b/src/main/java/gregtech/common/EventHandlers.java index da32dd83ca5..588909961e5 100644 --- a/src/main/java/gregtech/common/EventHandlers.java +++ b/src/main/java/gregtech/common/EventHandlers.java @@ -14,6 +14,7 @@ import gregtech.api.util.GTUtility; import gregtech.api.util.VirtualTankRegistry; import gregtech.api.worldgen.bedrockFluids.BedrockFluidVeinSaveData; +import gregtech.common.entities.EntityGTExplosive; import gregtech.common.items.MetaItems; import gregtech.common.items.armor.IStepAssist; import gregtech.common.items.armor.PowerlessJetpack; @@ -26,6 +27,7 @@ import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.ai.attributes.IAttributeInstance; +import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.monster.EntityEnderman; import net.minecraft.entity.monster.EntityZombie; import net.minecraft.entity.player.EntityPlayer; @@ -48,6 +50,7 @@ import net.minecraftforge.event.entity.player.AdvancementEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.furnace.FurnaceFuelBurnTimeEvent; +import net.minecraftforge.event.world.ExplosionEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fml.common.Mod; @@ -373,4 +376,13 @@ public static void onFurnaceFuelBurnTime(FurnaceFuelBurnTimeEvent event) { event.setBurnTime(6400); } } + + @SubscribeEvent + public static void onExplosionDetonate(ExplosionEvent.Detonate event) { + if (event.getExplosion().exploder instanceof EntityGTExplosive explosive) { + if (explosive.dropsAllBlocks()) { + event.getAffectedEntities().removeIf(entity -> entity instanceof EntityItem); + } + } + } } diff --git a/src/main/java/gregtech/common/MetaEntities.java b/src/main/java/gregtech/common/MetaEntities.java index 00efb35f87d..965ce3bfb18 100644 --- a/src/main/java/gregtech/common/MetaEntities.java +++ b/src/main/java/gregtech/common/MetaEntities.java @@ -4,10 +4,13 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.handler.DynamiteRenderer; import gregtech.client.renderer.handler.GTBoatRenderer; +import gregtech.client.renderer.handler.GTExplosiveRenderer; import gregtech.client.renderer.handler.PortalRenderer; import gregtech.common.entities.DynamiteEntity; import gregtech.common.entities.GTBoatEntity; +import gregtech.common.entities.ITNTEntity; import gregtech.common.entities.PortalEntity; +import gregtech.common.entities.PowderbarrelEntity; import net.minecraft.client.Minecraft; import net.minecraftforge.fml.client.registry.RenderingRegistry; @@ -24,6 +27,10 @@ public static void init() { GregTechAPI.instance, 64, 5, true); EntityRegistry.registerModEntity(GTUtility.gregtechId("gtboat"), GTBoatEntity.class, "GTBoat", 3, GregTechAPI.instance, 64, 2, true); + EntityRegistry.registerModEntity(GTUtility.gregtechId("powderbarrel"), PowderbarrelEntity.class, "Powderbarrel", + 4, GregTechAPI.instance, 64, 3, true); + EntityRegistry.registerModEntity(GTUtility.gregtechId("itnt"), ITNTEntity.class, "ITNT", 5, + GregTechAPI.instance, 64, 3, true); } @SideOnly(Side.CLIENT) @@ -32,5 +39,7 @@ public static void initRenderers() { manager -> new DynamiteRenderer(manager, Minecraft.getMinecraft().getRenderItem())); RenderingRegistry.registerEntityRenderingHandler(PortalEntity.class, PortalRenderer::new); RenderingRegistry.registerEntityRenderingHandler(GTBoatEntity.class, GTBoatRenderer::new); + RenderingRegistry.registerEntityRenderingHandler(PowderbarrelEntity.class, GTExplosiveRenderer::new); + RenderingRegistry.registerEntityRenderingHandler(ITNTEntity.class, GTExplosiveRenderer::new); } } diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index ada71a669ac..1cacda968e6 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -24,6 +24,8 @@ import gregtech.client.renderer.pipe.LaserPipeRenderer; import gregtech.client.renderer.pipe.OpticalPipeRenderer; import gregtech.common.ConfigHolder; +import gregtech.common.blocks.explosive.BlockITNT; +import gregtech.common.blocks.explosive.BlockPowderbarrel; import gregtech.common.blocks.foam.BlockFoam; import gregtech.common.blocks.foam.BlockPetrifiedFoam; import gregtech.common.blocks.wood.BlockGregFence; @@ -164,6 +166,8 @@ private MetaBlocks() {} public static BlockFenceGate TREATED_WOOD_FENCE_GATE; public static BlockWoodenDoor RUBBER_WOOD_DOOR; public static BlockWoodenDoor TREATED_WOOD_DOOR; + public static BlockPowderbarrel POWDERBARREL; + public static BlockITNT ITNT; public static BlockBrittleCharcoal BRITTLE_CHARCOAL; @@ -312,6 +316,10 @@ public static void init() { RUBBER_WOOD_DOOR.setRegistryName("rubber_wood_door").setTranslationKey("rubber_wood_door"); TREATED_WOOD_DOOR = new BlockWoodenDoor(() -> MetaItems.TREATED_WOOD_DOOR.getStackForm()); TREATED_WOOD_DOOR.setRegistryName("treated_wood_door").setTranslationKey("treated_wood_door"); + POWDERBARREL = new BlockPowderbarrel(); + POWDERBARREL.setRegistryName("powderbarrel").setTranslationKey("powderbarrel"); + ITNT = new BlockITNT(); + ITNT.setRegistryName("itnt").setTranslationKey("itnt"); BRITTLE_CHARCOAL = new BlockBrittleCharcoal(); BRITTLE_CHARCOAL.setRegistryName("brittle_charcoal"); @@ -481,6 +489,8 @@ public static void registerItemModels() { new ModelResourceLocation(Objects.requireNonNull(TREATED_WOOD_FENCE_GATE.getRegistryName()), "inventory")); registerItemModel(BRITTLE_CHARCOAL); + registerItemModel(POWDERBARREL); + registerItemModel(ITNT); registerItemModel(METAL_SHEET); registerItemModel(LARGE_METAL_SHEET); diff --git a/src/main/java/gregtech/common/blocks/explosive/BlockGTExplosive.java b/src/main/java/gregtech/common/blocks/explosive/BlockGTExplosive.java new file mode 100644 index 00000000000..e18a97abbbf --- /dev/null +++ b/src/main/java/gregtech/common/blocks/explosive/BlockGTExplosive.java @@ -0,0 +1,175 @@ +package gregtech.common.blocks.explosive; + +import gregtech.common.creativetab.GTCreativeTabs; +import gregtech.common.entities.EntityGTExplosive; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityArrow; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.Explosion; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +@SuppressWarnings("deprecation") +public abstract class BlockGTExplosive extends Block { + + private final boolean canRedstoneActivate; + private final boolean explodeOnMine; + private final int fuseLength; + + /** + * @param canRedstoneActivate whether redstone signal can prime this explosive + * @param explodeOnMine whether mining this block should prime it (sneak mine to drop normally) + * @param fuseLength explosion countdown after priming. Vanilla TNT is 80. + */ + public BlockGTExplosive(Material materialIn, boolean canRedstoneActivate, boolean explodeOnMine, int fuseLength) { + super(materialIn); + this.canRedstoneActivate = canRedstoneActivate; + this.explodeOnMine = explodeOnMine; + this.fuseLength = fuseLength; + setCreativeTab(GTCreativeTabs.TAB_GREGTECH_TOOLS); + } + + protected abstract EntityGTExplosive createEntity(World world, BlockPos pos, EntityLivingBase exploder); + + @Override + public float getExplosionResistance(@NotNull Entity exploder) { + return 1.0f; + } + + @Override + public boolean canBeReplacedByLeaves(@NotNull IBlockState state, @NotNull IBlockAccess world, + @NotNull BlockPos pos) { + return false; + } + + @Override + public boolean isNormalCube(@NotNull IBlockState state) { + return true; + } + + @Override + public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, + @NotNull EntityLiving.SpawnPlacementType type) { + return false; + } + + @Override + public boolean canDropFromExplosion(@NotNull Explosion explosion) { + return false; + } + + public void explode(World world, BlockPos pos, EntityLivingBase exploder) { + if (!world.isRemote) { + EntityGTExplosive entity = createEntity(world, pos, exploder); + entity.setFuse(fuseLength); + world.spawnEntity(entity); + world.playSound(null, entity.posX, entity.posY, entity.posZ, SoundEvents.ENTITY_TNT_PRIMED, + SoundCategory.BLOCKS, 1.0f, 1.0f); + } + } + + @Override + public void onExplosionDestroy(@NotNull World world, @NotNull BlockPos pos, @NotNull Explosion explosion) { + if (!world.isRemote) { + EntityGTExplosive entity = createEntity(world, pos, explosion.getExplosivePlacedBy()); + entity.setFuse(world.rand.nextInt(fuseLength / 4) + fuseLength / 8); + world.spawnEntity(entity); + } + } + + @Override + public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @NotNull IBlockState state, + @NotNull EntityPlayer player, @NotNull EnumHand hand, @NotNull EnumFacing facing, + float hitX, float hitY, float hitZ) { + ItemStack stack = player.getHeldItem(hand); + if (!stack.isEmpty() && (stack.getItem() == Items.FLINT_AND_STEEL || stack.getItem() == Items.FIRE_CHARGE)) { + this.explode(world, pos, player); + world.setBlockState(pos, Blocks.AIR.getDefaultState(), 11); + if (stack.getItem() == Items.FLINT_AND_STEEL) { + stack.damageItem(1, player); + } else if (!player.capabilities.isCreativeMode) { + stack.shrink(1); + } + return true; + } + return super.onBlockActivated(world, pos, state, player, hand, facing, hitX, hitY, hitZ); + } + + @Override + public void dropBlockAsItemWithChance(@NotNull World world, @NotNull BlockPos pos, @NotNull IBlockState state, + float chance, int fortune) { + if (explodeOnMine) { + EntityPlayer player = this.harvesters.get(); + if (!player.isSneaking()) { + this.explode(world, pos, player); + return; + } + } + super.dropBlockAsItemWithChance(world, pos, state, chance, fortune); + } + + @Override + public void onEntityCollision(@NotNull World world, @NotNull BlockPos pos, @NotNull IBlockState state, + @NotNull Entity entity) { + if (!world.isRemote && entity instanceof EntityArrow arrow) { + if (arrow.isBurning()) { + this.explode(world, pos, arrow.shootingEntity instanceof EntityLivingBase living ? living : null); + world.setBlockToAir(pos); + } + } + } + + @Override + public void onBlockAdded(@NotNull World world, @NotNull BlockPos pos, @NotNull IBlockState state) { + super.onBlockAdded(world, pos, state); + if (canRedstoneActivate) { + if (world.isBlockPowered(pos)) { + explode(world, pos, null); + world.setBlockToAir(pos); + } + } + } + + @Override + public void neighborChanged(@NotNull IBlockState state, @NotNull World world, @NotNull BlockPos pos, + @NotNull Block block, @NotNull BlockPos fromPos) { + if (canRedstoneActivate) { + if (world.isBlockPowered(pos)) { + explode(world, pos, null); + world.setBlockToAir(pos); + } + } + } + + @Override + public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, + @NotNull ITooltipFlag flag) { + if (explodeOnMine) { + tooltip.add(I18n.format("tile.gt_explosive.breaking_tooltip")); + } + if (!canRedstoneActivate) { + tooltip.add(I18n.format("tile.gt_explosive.lighting_tooltip")); + } + } +} diff --git a/src/main/java/gregtech/common/blocks/explosive/BlockITNT.java b/src/main/java/gregtech/common/blocks/explosive/BlockITNT.java new file mode 100644 index 00000000000..91a9614d4c4 --- /dev/null +++ b/src/main/java/gregtech/common/blocks/explosive/BlockITNT.java @@ -0,0 +1,40 @@ +package gregtech.common.blocks.explosive; + +import gregtech.common.entities.EntityGTExplosive; +import gregtech.common.entities.ITNTEntity; + +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class BlockITNT extends BlockGTExplosive { + + public BlockITNT() { + super(Material.TNT, true, true, 40); + setHardness(0); + setSoundType(SoundType.PLANT); + } + + @Override + protected EntityGTExplosive createEntity(World world, BlockPos pos, EntityLivingBase exploder) { + float x = pos.getX() + 0.5F, y = pos.getY(), z = pos.getZ() + 0.5F; + return new ITNTEntity(world, x, y, z, exploder); + } + + @Override + public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, + @NotNull ITooltipFlag flag) { + tooltip.add(I18n.format("tile.itnt.drops_tooltip")); + super.addInformation(stack, world, tooltip, flag); + } +} diff --git a/src/main/java/gregtech/common/blocks/explosive/BlockPowderbarrel.java b/src/main/java/gregtech/common/blocks/explosive/BlockPowderbarrel.java new file mode 100644 index 00000000000..a2549ad7ee5 --- /dev/null +++ b/src/main/java/gregtech/common/blocks/explosive/BlockPowderbarrel.java @@ -0,0 +1,42 @@ +package gregtech.common.blocks.explosive; + +import gregtech.api.items.toolitem.ToolClasses; +import gregtech.common.blocks.material.GTBlockMaterials; +import gregtech.common.entities.EntityGTExplosive; +import gregtech.common.entities.PowderbarrelEntity; + +import net.minecraft.block.SoundType; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class BlockPowderbarrel extends BlockGTExplosive { + + public BlockPowderbarrel() { + super(GTBlockMaterials.POWDERBARREL, false, true, 100); + setHarvestLevel(ToolClasses.AXE, 1); + setHardness(0.5F); + setSoundType(SoundType.WOOD); + } + + @Override + protected EntityGTExplosive createEntity(World world, BlockPos pos, EntityLivingBase exploder) { + float x = pos.getX() + 0.5F, y = pos.getY(), z = pos.getZ() + 0.5F; + return new PowderbarrelEntity(world, x, y, z, exploder); + } + + @Override + public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, + @NotNull ITooltipFlag flag) { + tooltip.add(I18n.format("tile.powderbarrel.drops_tooltip")); + super.addInformation(stack, world, tooltip, flag); + } +} diff --git a/src/main/java/gregtech/common/blocks/material/GTBlockMaterials.java b/src/main/java/gregtech/common/blocks/material/GTBlockMaterials.java new file mode 100644 index 00000000000..213ba58fdd9 --- /dev/null +++ b/src/main/java/gregtech/common/blocks/material/GTBlockMaterials.java @@ -0,0 +1,18 @@ +package gregtech.common.blocks.material; + +import net.minecraft.block.material.MapColor; +import net.minecraft.block.material.Material; + +public class GTBlockMaterials { + + public static final Material POWDERBARREL = new PowderbarrelMaterial(); + + private static class PowderbarrelMaterial extends Material { + + public PowderbarrelMaterial() { + super(MapColor.STONE); + setAdventureModeExempt(); + setImmovableMobility(); + } + } +} diff --git a/src/main/java/gregtech/common/entities/EntityGTExplosive.java b/src/main/java/gregtech/common/entities/EntityGTExplosive.java new file mode 100644 index 00000000000..70233d7f17b --- /dev/null +++ b/src/main/java/gregtech/common/entities/EntityGTExplosive.java @@ -0,0 +1,136 @@ +package gregtech.common.entities; + +import gregtech.api.util.BlockUtility; +import gregtech.api.util.GregFakePlayer; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.MoverType; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.item.EntityTNTPrimed; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; + +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public abstract class EntityGTExplosive extends EntityTNTPrimed { + + public EntityGTExplosive(World world, double x, double y, double z, EntityLivingBase exploder) { + super(world, x, y, z, exploder); + } + + @SuppressWarnings("unused") + public EntityGTExplosive(World world) { + super(world); + } + + /** + * @return The strength of the explosive. + */ + protected abstract float getStrength(); + + /** + * @return Whether to drop all blocks, or use default logic + */ + public abstract boolean dropsAllBlocks(); + + /** + * @return The range of the explosive, if {@link #dropsAllBlocks} is true. + */ + protected int getRange() { + return 2; + } + + /** + * @return The block state of the block this explosion entity is created by. + */ + public abstract @NotNull IBlockState getExplosiveState(); + + @Override + public void onUpdate() { + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + if (!this.hasNoGravity()) { + this.motionY -= 0.03999999910593033D; + } + + this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ); + this.motionX *= 0.9800000190734863D; + this.motionY *= 0.9800000190734863D; + this.motionZ *= 0.9800000190734863D; + if (this.onGround) { + this.motionX *= 0.699999988079071D; + this.motionZ *= 0.699999988079071D; + this.motionY *= -0.5D; + } + + setFuse(this.getFuse() - 1); + if (this.getFuse() <= 0) { + this.setDead(); + if (!this.world.isRemote) { + this.explodeTNT(); + } + } else { + this.handleWaterMovement(); + this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, + 0.0D); + } + } + + protected void explodeTNT() { + this.world.createExplosion(this, this.posX, this.posY + (double) (this.height / 16.0F), this.posZ, + getStrength(), !dropsAllBlocks()); + + // If we don't drop all blocks, then skip the drop capture logic + if (!dropsAllBlocks()) return; + + // Create the fake explosion but don't destroy any blocks in water, per MC behavior + if (this.inWater) return; + + EntityPlayer player = GregFakePlayer.get((WorldServer) world); + + int range = getRange(); + for (BlockPos pos : BlockPos.getAllInBox(this.getPosition().add(-range, -range, -range), + this.getPosition().add(range, range, range))) { + IBlockState state = world.getBlockState(pos); + + if (state.getMaterial() == Material.AIR) continue; + if (state.getMaterial() == Material.WATER || state.getMaterial() == Material.LAVA) continue; + + float hardness = state.getBlockHardness(world, pos); + float resistance = state.getBlock().getExplosionResistance(player); + + if (hardness >= 0.0f && resistance < 100 && world.isBlockModifiable(player, pos)) { + List drops = attemptBreakBlockAndObtainDrops(pos, state, player); + + for (ItemStack stack : drops) { + EntityItem entity = new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), stack); + entity.setDefaultPickupDelay(); + world.spawnEntity(entity); + } + } + } + } + + private List attemptBreakBlockAndObtainDrops(BlockPos pos, IBlockState state, EntityPlayer player) { + if (state.getBlock().removedByPlayer(state, world, pos, player, true)) { + world.playEvent(null, 2001, pos, Block.getStateId(state)); + state.getBlock().onPlayerDestroy(world, pos, state); + + BlockUtility.startCaptureDrops(); + state.getBlock().harvestBlock(world, player, pos, state, world.getTileEntity(pos), ItemStack.EMPTY); + return BlockUtility.stopCaptureDrops(); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/gregtech/common/entities/ITNTEntity.java b/src/main/java/gregtech/common/entities/ITNTEntity.java new file mode 100644 index 00000000000..3fa60cf4860 --- /dev/null +++ b/src/main/java/gregtech/common/entities/ITNTEntity.java @@ -0,0 +1,41 @@ +package gregtech.common.entities; + +import gregtech.common.blocks.MetaBlocks; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; + +public class ITNTEntity extends EntityGTExplosive { + + public ITNTEntity(World world, double x, double y, double z, EntityLivingBase exploder) { + super(world, x, y, z, exploder); + } + + @SuppressWarnings("unused") + public ITNTEntity(World world) { + super(world); + } + + @Override + protected float getStrength() { + return 5.0F; + } + + @Override + public boolean dropsAllBlocks() { + return true; + } + + @Override + protected int getRange() { + return 3; + } + + @Override + public @NotNull IBlockState getExplosiveState() { + return MetaBlocks.ITNT.getDefaultState(); + } +} diff --git a/src/main/java/gregtech/common/entities/PowderbarrelEntity.java b/src/main/java/gregtech/common/entities/PowderbarrelEntity.java new file mode 100644 index 00000000000..39f1ed4df56 --- /dev/null +++ b/src/main/java/gregtech/common/entities/PowderbarrelEntity.java @@ -0,0 +1,36 @@ +package gregtech.common.entities; + +import gregtech.common.blocks.MetaBlocks; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; + +public class PowderbarrelEntity extends EntityGTExplosive { + + public PowderbarrelEntity(World world, double x, double y, double z, EntityLivingBase exploder) { + super(world, x, y, z, exploder); + } + + @SuppressWarnings("unused") + public PowderbarrelEntity(World world) { + super(world); + } + + @Override + protected float getStrength() { + return 3.5F; + } + + @Override + public boolean dropsAllBlocks() { + return true; + } + + @Override + public @NotNull IBlockState getExplosiveState() { + return MetaBlocks.POWDERBARREL.getDefaultState(); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/LighterBehaviour.java b/src/main/java/gregtech/common/items/behaviors/LighterBehaviour.java index 6dd8d6742c7..bdff9524d0d 100644 --- a/src/main/java/gregtech/common/items/behaviors/LighterBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/LighterBehaviour.java @@ -7,6 +7,7 @@ import gregtech.api.unification.material.Materials; import gregtech.api.util.GTUtility; import gregtech.api.util.GradientUtil; +import gregtech.common.blocks.explosive.BlockGTExplosive; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.block.Block; @@ -120,8 +121,13 @@ public EnumActionResult onItemUseFirst(@NotNull EntityPlayer player, @NotNull Wo SoundCategory.PLAYERS, 1.0F, GTValues.RNG.nextFloat() * 0.4F + 0.8F); IBlockState blockState = world.getBlockState(pos); Block block = blockState.getBlock(); - if (block instanceof BlockTNT) { - ((BlockTNT) block).explode(world, pos, blockState.withProperty(BlockTNT.EXPLODE, true), player); + if (block instanceof BlockTNT tnt) { + tnt.explode(world, pos, blockState.withProperty(BlockTNT.EXPLODE, true), player); + world.setBlockState(pos, Blocks.AIR.getDefaultState(), 11); + return EnumActionResult.SUCCESS; + } + if (block instanceof BlockGTExplosive powderbarrel) { + powderbarrel.explode(world, pos, player); world.setBlockState(pos, Blocks.AIR.getDefaultState(), 11); return EnumActionResult.SUCCESS; } diff --git a/src/main/java/gregtech/integration/forestry/bees/GTBeeDefinition.java b/src/main/java/gregtech/integration/forestry/bees/GTBeeDefinition.java index 97fed7a25c3..269e992be1b 100644 --- a/src/main/java/gregtech/integration/forestry/bees/GTBeeDefinition.java +++ b/src/main/java/gregtech/integration/forestry/bees/GTBeeDefinition.java @@ -5,6 +5,7 @@ import gregtech.api.unification.material.Materials; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.UnificationEntry; +import gregtech.common.blocks.MetaBlocks; import gregtech.common.items.MetaItems; import gregtech.integration.IntegrationUtil; import gregtech.integration.forestry.ForestryModule; @@ -821,8 +822,7 @@ public enum GTBeeDefinition implements IBeeDefinition { }), EXPLOSIVE(GTBranchDefinition.GT_INDUSTRIAL, "Explosionis", false, 0x7E270F, 0x747474, beeSpecies -> { - beeSpecies.addProduct(new ItemStack(Blocks.TNT), 0.2f); - // todo if we add a ITNT substitute, put it here instead of TNT + beeSpecies.addProduct(new ItemStack(MetaBlocks.ITNT), 0.2f); beeSpecies.setHumidity(EnumHumidity.ARID); beeSpecies.setTemperature(EnumTemperature.HELLISH); beeSpecies.setHasEffect(); diff --git a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java index 0b0d513a7f7..8b18ba7a811 100644 --- a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java @@ -336,6 +336,11 @@ private static void loadCraftingRecipes() { new UnificationEntry(OrePrefix.wireGtQuadruple, Osmium), 'P', new UnificationEntry(OrePrefix.plateDouble, Iridium), 'O', MetaItems.ENERGY_LAPOTRONIC_ORB.getStackForm()); + + ModHandler.addShapedRecipe("powderbarrel", new ItemStack(MetaBlocks.POWDERBARREL), "PSP", "GGG", "PGP", + 'P', new UnificationEntry(OrePrefix.plate, Wood), + 'S', new ItemStack(Items.STRING), + 'G', new UnificationEntry(OrePrefix.dust, Gunpowder)); } private static void registerFacadeRecipe(Material material, int facadeAmount) { diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java index 7871a518e8c..ebe5ed15505 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java @@ -3,6 +3,7 @@ import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.MarkerMaterials; import gregtech.api.unification.material.Materials; +import gregtech.common.blocks.MetaBlocks; import gregtech.common.items.MetaItems; import net.minecraft.init.Blocks; @@ -570,6 +571,13 @@ public static void init() { .outputs(new ItemStack(Blocks.TNT)) .duration(200).EUt(24).buildAndRegister(); + CHEMICAL_RECIPES.recipeBuilder() + .inputs(MetaItems.GELLED_TOLUENE.getStackForm(4)) + .fluidInputs(NitrationMixture.getFluid(200)) + .outputs(new ItemStack(MetaBlocks.ITNT)) + .fluidOutputs(DilutedSulfuricAcid.getFluid(150)) + .duration(80).EUt(VA[HV]).buildAndRegister(); + CHEMICAL_RECIPES.recipeBuilder() .input(dust, SodiumHydroxide, 6) .fluidInputs(Dichlorobenzene.getFluid(1000)) diff --git a/src/main/java/gregtech/loaders/recipe/handlers/MaterialRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/MaterialRecipeHandler.java index 74239ff12ae..cbdf94add16 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/MaterialRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/MaterialRecipeHandler.java @@ -13,6 +13,7 @@ import gregtech.api.unification.stack.UnificationEntry; import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; +import gregtech.common.blocks.MetaBlocks; import gregtech.common.items.MetaItems; import gregtech.loaders.recipe.CraftingComponent; @@ -90,14 +91,28 @@ public static void processDust(OrePrefix dustPrefix, Material mat, DustProperty .inputs(GTUtility.copy(4, dustStack)) .outputs(GTUtility.copy(3, gemStack)) .chancedOutput(dust, Materials.DarkAsh, 2500, 0) - .explosivesAmount(2) + .explosivesType(new ItemStack(MetaBlocks.POWDERBARREL, 8)) .buildAndRegister(); RecipeMaps.IMPLOSION_RECIPES.recipeBuilder() .inputs(GTUtility.copy(4, dustStack)) .outputs(GTUtility.copy(3, gemStack)) .chancedOutput(dust, Materials.DarkAsh, 2500, 0) - .explosivesType(MetaItems.DYNAMITE.getStackForm()) + .explosivesAmount(4) + .buildAndRegister(); + + RecipeMaps.IMPLOSION_RECIPES.recipeBuilder() + .inputs(GTUtility.copy(4, dustStack)) + .outputs(GTUtility.copy(3, gemStack)) + .chancedOutput(dust, Materials.DarkAsh, 2500, 0) + .explosivesType(MetaItems.DYNAMITE.getStackForm(2)) + .buildAndRegister(); + + RecipeMaps.IMPLOSION_RECIPES.recipeBuilder() + .inputs(GTUtility.copy(4, dustStack)) + .outputs(GTUtility.copy(3, gemStack)) + .chancedOutput(dust, Materials.DarkAsh, 2500, 0) + .explosivesType(new ItemStack(MetaBlocks.ITNT)) .buildAndRegister(); } diff --git a/src/main/resources/assets/gregtech/blockstates/itnt.json b/src/main/resources/assets/gregtech/blockstates/itnt.json new file mode 100644 index 00000000000..79c7d216ccb --- /dev/null +++ b/src/main/resources/assets/gregtech/blockstates/itnt.json @@ -0,0 +1,16 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "minecraft:cube_bottom_top", + "textures": { + "bottom": "minecraft:blocks/tnt_bottom", + "top": "minecraft:blocks/tnt_top", + "side": "gregtech:blocks/misc/itnt" + } + }, + "variants": { + "normal": [ + {} + ] + } +} diff --git a/src/main/resources/assets/gregtech/blockstates/powderbarrel.json b/src/main/resources/assets/gregtech/blockstates/powderbarrel.json new file mode 100644 index 00000000000..60d676619f5 --- /dev/null +++ b/src/main/resources/assets/gregtech/blockstates/powderbarrel.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "minecraft:cube_all", + "textures": { + "all": "gregtech:blocks/misc/powderbarrel" + } + }, + "variants": { + "normal": [ + {} + ] + } +} diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 12a9bba8f0d..38436e8da3d 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -2348,6 +2348,17 @@ tile.treated_wood_fence.name=Treated Wood Fence tile.rubber_wood_fence_gate.name=Rubber Wood Fence Gate tile.treated_wood_fence_gate.name=Treated Wood Fence Gate +tile.gt_explosive.breaking_tooltip=Primes explosion when mined, sneak mine to pick back up +tile.gt_explosive.lighting_tooltip=Cannot be lit with Redstone + +tile.powderbarrel.name=Powderbarrel +tile.powderbarrel.drops_tooltip=Slightly larger than TNT, drops all destroyed Blocks as Items +entity.Powderbarrel.name=Powderbarrel + +tile.itnt.name=Industrial TNT +tile.itnt.drops_tooltip=Much larger than TNT, drops all destroyed Blocks as Items +entity.ITNT.name=Industrial TNT + tile.brittle_charcoal.name=Brittle Charcoal tile.brittle_charcoal.tooltip.1=Produced by the Charcoal Pile Igniter. tile.brittle_charcoal.tooltip.2=Mine this to get Charcoal. diff --git a/src/main/resources/assets/gregtech/textures/blocks/misc/itnt.png b/src/main/resources/assets/gregtech/textures/blocks/misc/itnt.png new file mode 100644 index 00000000000..a167e1676b7 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/misc/itnt.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/misc/powderbarrel.png b/src/main/resources/assets/gregtech/textures/blocks/misc/powderbarrel.png new file mode 100644 index 00000000000..b5624295e93 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/misc/powderbarrel.png differ diff --git a/src/main/resources/gregtech_at.cfg b/src/main/resources/gregtech_at.cfg index 343dd1b65f5..76892c9fc05 100644 --- a/src/main/resources/gregtech_at.cfg +++ b/src/main/resources/gregtech_at.cfg @@ -81,3 +81,6 @@ protected net.minecraft.entity.item.EntityBoat field_184473_aH # lastYd # EntityItem public net.minecraft.entity.item.EntityItem field_145804_b # pickupDelay + +# Explosion +public net.minecraft.world.Explosion field_77283_e # exploder