diff --git a/src/main/java/net/id/paradiselost/blocks/ParadiseLostBlocks.java b/src/main/java/net/id/paradiselost/blocks/ParadiseLostBlocks.java index 0c0716378..d30696998 100644 --- a/src/main/java/net/id/paradiselost/blocks/ParadiseLostBlocks.java +++ b/src/main/java/net/id/paradiselost/blocks/ParadiseLostBlocks.java @@ -370,7 +370,7 @@ private static Settings flower() { public static final OreBlock CHERINE_ORE = add("cherine_ore", new OreBlock(of(Material.STONE).requiresTool().strength(3f), UniformIntProvider.create(0, 2))); public static final OreBlock OLVITE_ORE = add("olvite_ore", new OreBlock(of(Material.STONE).requiresTool().strength(3f), UniformIntProvider.create(1, 3))); public static final OreBlock SURTRUM = add("surtrum", new SurtrumOreBlock(of(Material.STONE).sounds(BlockSoundGroup.NETHER_GOLD_ORE).requiresTool().strength(9f, 20f), UniformIntProvider.create(2, 5))); - public static final Block METAMORPHIC_SHELL = add("metamorphic_shell", new Block(of(Material.STONE).sounds(BlockSoundGroup.TUFF).requiresTool().strength(40f, 15f))); + public static final Block METAMORPHIC_SHELL = add("metamorphic_shell", new Block(of(Material.STONE).sounds(BlockSoundGroup.TUFF).requiresTool().strength(40f, 6f))); public static final PoofBlock SURTRUM_AIR = add("surtrum_air", new PoofBlock(of(Material.FIRE).sounds(BlockSoundGroup.NETHER_GOLD_ORE))); public static final FloatingBlock LEVITA_ORE = add("levita_ore", new FloatingBlock(false, of(Material.STONE).requiresTool().strength(4f), UniformIntProvider.create(4, 7))); public static final Block CHERINE_BLOCK = add("cherine_block", new Block(of(Material.METAL).requiresTool().strength(3f, -1f).sounds(BlockSoundGroup.STONE))); diff --git a/src/main/java/net/id/paradiselost/blocks/mechanical/NitraBlock.java b/src/main/java/net/id/paradiselost/blocks/mechanical/NitraBlock.java index cc4aa1cc8..0da476a1e 100644 --- a/src/main/java/net/id/paradiselost/blocks/mechanical/NitraBlock.java +++ b/src/main/java/net/id/paradiselost/blocks/mechanical/NitraBlock.java @@ -1,6 +1,26 @@ package net.id.paradiselost.blocks.mechanical; +import net.id.paradiselost.world.ExplosionExtensions; import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.ProjectileEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.sound.SoundEvents; +import net.minecraft.stat.Stats; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.event.GameEvent; +import net.minecraft.world.explosion.Explosion; +import org.jetbrains.annotations.Nullable; public class NitraBlock extends Block { @@ -8,4 +28,81 @@ public NitraBlock(Settings settings) { super(settings); } + public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean notify) { + if (!oldState.isOf(state.getBlock())) { + if (world.isReceivingRedstonePower(pos)) { + ignite(world, pos, 2F); + world.removeBlock(pos, false); + } + + } + } + + public void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { + if (world.isReceivingRedstonePower(pos)) { + ignite(world, pos, 2F); + world.removeBlock(pos, false); + } + + } + + public void onDestroyedByExplosion(World world, BlockPos pos, Explosion explosion) { + float sourcePower = ((ExplosionExtensions) explosion).getPower(); + if (!world.isClient && sourcePower > 0.5F) { + System.out.println(sourcePower); + ignite(world, pos, sourcePower - 0.5F); + } + } + + public static void ignite(World world, BlockPos pos, float power) { + ignite(world, pos, power, null); + } + + private static void ignite(World world, BlockPos pos, float power, @Nullable LivingEntity igniter) { + Explosion explosion = new Explosion(world, igniter, null, null, pos.getX(), pos.getY()+0.5D, pos.getZ(), power, false, Explosion.DestructionType.BREAK); + if (!world.isClient) { + explosion.collectBlocksAndDamageEntities(); + world.emitGameEvent(igniter, GameEvent.PRIME_FUSE, pos); + } + ((ExplosionExtensions) explosion).affectWorld(true, SoundEvents.ENTITY_GENERIC_EXPLODE); + } + + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + ItemStack itemStack = player.getStackInHand(hand); + if (!itemStack.isOf(Items.FLINT_AND_STEEL) && !itemStack.isOf(Items.FIRE_CHARGE)) { + return super.onUse(state, world, pos, player, hand, hit); + } else { + ignite(world, pos, 2F, player); + world.setBlockState(pos, Blocks.AIR.getDefaultState(), 11); + Item item = itemStack.getItem(); + if (!player.isCreative()) { + if (itemStack.isOf(Items.FLINT_AND_STEEL)) { + itemStack.damage(1, player, (playerx) -> { + playerx.sendToolBreakStatus(hand); + }); + } else { + itemStack.decrement(1); + } + } + + player.incrementStat(Stats.USED.getOrCreateStat(item)); + return ActionResult.success(world.isClient); + } + } + + public void onProjectileHit(World world, BlockState state, BlockHitResult hit, ProjectileEntity projectile) { + if (!world.isClient) { + BlockPos blockPos = hit.getBlockPos(); + Entity entity = projectile.getOwner(); + if (projectile.isOnFire() && projectile.canModifyAt(world, blockPos)) { + ignite(world, blockPos, 2F, entity instanceof LivingEntity ? (LivingEntity)entity : null); + world.removeBlock(blockPos, false); + } + } + + } + + public boolean shouldDropItemsOnExplosion(Explosion explosion) { + return false; + } } diff --git a/src/main/java/net/id/paradiselost/mixin/world/ExplosionMixin.java b/src/main/java/net/id/paradiselost/mixin/world/ExplosionMixin.java new file mode 100644 index 000000000..58daf5789 --- /dev/null +++ b/src/main/java/net/id/paradiselost/mixin/world/ExplosionMixin.java @@ -0,0 +1,178 @@ +package net.id.paradiselost.mixin.world; + +import com.mojang.datafixers.util.Pair; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectListIterator; +import net.id.paradiselost.world.ExplosionExtensions; +import net.minecraft.block.AbstractFireBlock; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.Entity; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffect; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContext; +import net.minecraft.loot.context.LootContextParameters; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.Util; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.World; +import net.minecraft.world.explosion.Explosion; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(Explosion.class) +public abstract class ExplosionMixin extends Object implements ExplosionExtensions { + + @Shadow + @Final + private boolean createFire; + + @Shadow + @Final + private double x; + @Shadow + @Final + private double y; + @Shadow + @Final + private double z; + + @Shadow + @Final + private Entity entity; + + @Shadow + @Final + private float power; + + @Shadow + @Final + private Random random; + + @Shadow + @Final + private World world; + + @Shadow + @Final + private Explosion.DestructionType destructionType; + + @Shadow + @Final + private ObjectArrayList affectedBlocks; + + @Shadow + public abstract LivingEntity getCausingEntity(); + + public float getPower() { + return this.power; + } + + public void affectWorld(boolean particles, SoundEvent customSound) { + if (this.world.isClient) { + this.world.playSound(this.x, this.y, this.z, customSound, SoundCategory.BLOCKS, 4.0F, (1.0F + (this.world.random.nextFloat() - this.world.random.nextFloat()) * 0.2F) * 0.7F, false); + } + + boolean bl = this.destructionType != Explosion.DestructionType.NONE; + if (particles) { + if (!(this.power < 2.0F) && bl) { + this.world.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0, 0.0, 0.0); + } else { + this.world.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0, 0.0, 0.0); + } + } + + if (bl) { + ObjectArrayList> objectArrayList = new ObjectArrayList(); + boolean bl2 = this.getCausingEntity() instanceof PlayerEntity; + Util.shuffle(this.affectedBlocks, this.world.random); + ObjectListIterator var5 = this.affectedBlocks.iterator(); + + while(var5.hasNext()) { + BlockPos blockPos = (BlockPos)var5.next(); + BlockState blockState = this.world.getBlockState(blockPos); + Block block = blockState.getBlock(); + if (!blockState.isAir()) { + BlockPos blockPos2 = blockPos.toImmutable(); + this.world.getProfiler().push("explosion_blocks"); + if (block.shouldDropItemsOnExplosion((Explosion) (Object)this)) { + World var11 = this.world; + if (var11 instanceof ServerWorld) { + ServerWorld serverWorld = (ServerWorld)var11; + BlockEntity blockEntity = blockState.hasBlockEntity() ? this.world.getBlockEntity(blockPos) : null; + LootContext.Builder builder = (new LootContext.Builder(serverWorld)).random(this.world.random).parameter(LootContextParameters.ORIGIN, Vec3d.ofCenter(blockPos)).parameter(LootContextParameters.TOOL, ItemStack.EMPTY).optionalParameter(LootContextParameters.BLOCK_ENTITY, blockEntity).optionalParameter(LootContextParameters.THIS_ENTITY, this.entity); + if (this.destructionType == Explosion.DestructionType.DESTROY) { + builder.parameter(LootContextParameters.EXPLOSION_RADIUS, this.power); + } + + blockState.onStacksDropped(serverWorld, blockPos, ItemStack.EMPTY, bl2); + blockState.getDroppedStacks(builder).forEach((stack) -> { + tryMergeStack(objectArrayList, stack, blockPos2); + }); + } + } + + this.world.setBlockState(blockPos, Blocks.AIR.getDefaultState(), 3); + block.onDestroyedByExplosion(this.world, blockPos, (Explosion) (Object)this); + this.world.getProfiler().pop(); + } + } + + var5 = objectArrayList.iterator(); + + while(var5.hasNext()) { + Pair pair = (Pair)var5.next(); + Block.dropStack(this.world, (BlockPos)pair.getSecond(), (ItemStack)pair.getFirst()); + } + } + + if (this.createFire) { + ObjectListIterator var13 = this.affectedBlocks.iterator(); + + while(var13.hasNext()) { + BlockPos blockPos3 = (BlockPos)var13.next(); + if (this.random.nextInt(3) == 0 && this.world.getBlockState(blockPos3).isAir() && this.world.getBlockState(blockPos3.down()).isOpaqueFullCube(this.world, blockPos3.down())) { + this.world.setBlockState(blockPos3, AbstractFireBlock.getState(this.world, blockPos3)); + } + } + } + + } + + private static void tryMergeStack(ObjectArrayList> stacks, ItemStack stack, BlockPos pos) { + int i = stacks.size(); + + for(int j = 0; j < i; ++j) { + Pair pair = (Pair)stacks.get(j); + ItemStack itemStack = (ItemStack)pair.getFirst(); + if (ItemEntity.canMerge(itemStack, stack)) { + ItemStack itemStack2 = ItemEntity.merge(itemStack, stack, 16); + stacks.set(j, Pair.of(itemStack2, (BlockPos)pair.getSecond())); + if (stack.isEmpty()) { + return; + } + } + } + + stacks.add(Pair.of(stack, pos)); + } + + +} diff --git a/src/main/java/net/id/paradiselost/world/ExplosionExtensions.java b/src/main/java/net/id/paradiselost/world/ExplosionExtensions.java new file mode 100644 index 000000000..41982b00b --- /dev/null +++ b/src/main/java/net/id/paradiselost/world/ExplosionExtensions.java @@ -0,0 +1,10 @@ +package net.id.paradiselost.world; + +import net.minecraft.sound.SoundEvent; + +public interface ExplosionExtensions { + + float getPower(); + + void affectWorld(boolean particles, SoundEvent customSound); +} diff --git a/src/main/resources/assets/paradise_lost/textures/item/nitra_bulb.png b/src/main/resources/assets/paradise_lost/textures/item/nitra_bulb.png index bad2833de..b3c71cf63 100644 Binary files a/src/main/resources/assets/paradise_lost/textures/item/nitra_bulb.png and b/src/main/resources/assets/paradise_lost/textures/item/nitra_bulb.png differ diff --git a/src/main/resources/paradise_lost.mixins.json b/src/main/resources/paradise_lost.mixins.json index feece1f62..9d215eeb7 100644 --- a/src/main/resources/paradise_lost.mixins.json +++ b/src/main/resources/paradise_lost.mixins.json @@ -29,6 +29,7 @@ "server.PlayerManagerMixin", "server.ServerPlayerEntityMixin", "server.ServerPlayNetworkHandlerMixin", + "world.ExplosionMixin", "util.DefaultedRegistryMixin", "util.NbtCompoundAccessor", "util.RarityMixin",