diff --git a/src/datagen/java/com/github/elenterius/biomancy/datagen/models/ModBlockStateProvider.java b/src/datagen/java/com/github/elenterius/biomancy/datagen/models/ModBlockStateProvider.java index 35f5f90d9..fa80222e2 100644 --- a/src/datagen/java/com/github/elenterius/biomancy/datagen/models/ModBlockStateProvider.java +++ b/src/datagen/java/com/github/elenterius/biomancy/datagen/models/ModBlockStateProvider.java @@ -16,6 +16,8 @@ import com.github.elenterius.biomancy.init.ModBlocks; import net.minecraft.core.Direction; import net.minecraft.data.PackOutput; +import net.minecraft.data.models.model.TextureMapping; +import net.minecraft.data.models.model.TextureSlot; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.level.block.*; @@ -151,14 +153,32 @@ protected void registerStatesAndModels() { particleOnly(ModBlocks.ACID_FLUID_BLOCK, new ResourceLocation("biomancy:block/acid_flat")); - cauldron(ModBlocks.ACID_CAULDRON,new ResourceLocation("biomancy:fluid/acid_overlay")); + layeredCauldron(ModBlocks.ACID_CAULDRON); } - public void cauldron(RegistryObject block, ResourceLocation fluidTexture) { - BlockModelBuilder model = models().withExistingParent(path(block.get()),"minecraft:block/lava_cauldron") - .texture("content",fluidTexture); + public void layeredCauldron(RegistryObject registryObject) { + T block = registryObject.get(); + String path = path(block); + + TextureMapping textureMapping = TextureMapping.cauldron(TextureMapping.getBlockTexture(Blocks.WATER, "_still")); + TextureSlot[] texturesSlots = {TextureSlot.CONTENT, TextureSlot.INSIDE, TextureSlot.TOP, TextureSlot.BOTTOM, TextureSlot.SIDE, TextureSlot.PARTICLE}; - simpleBlock(block.get(),model); + ModelFile modelLevel1 = getTemplateModelWithTextures(path + "_level_1", new ResourceLocation("minecraft:block/template_cauldron_level1"), texturesSlots, textureMapping).renderType("translucent"); + ModelFile modelLevel2 = getTemplateModelWithTextures(path + "_level_2", new ResourceLocation("minecraft:block/template_cauldron_level2"), texturesSlots, textureMapping).renderType("translucent"); + ModelFile modelFull = getTemplateModelWithTextures(path + "_full", new ResourceLocation("minecraft:block/template_cauldron_full"), texturesSlots, textureMapping).renderType("translucent"); + + getVariantBuilder(block) + .partialState().with(LayeredCauldronBlock.LEVEL, 1).modelForState().modelFile(modelLevel1).addModel() + .partialState().with(LayeredCauldronBlock.LEVEL, 2).modelForState().modelFile(modelLevel2).addModel() + .partialState().with(LayeredCauldronBlock.LEVEL, 3).modelForState().modelFile(modelFull).addModel(); + } + + private BlockModelBuilder getTemplateModelWithTextures(String name, ResourceLocation template, TextureSlot[] texturesSlots, TextureMapping textureMapping) { + BlockModelBuilder modelBuilder = models().withExistingParent(name, template); + for (TextureSlot textureSlot : texturesSlots) { + modelBuilder.texture(textureSlot.getId(), textureMapping.get(textureSlot)); + } + return modelBuilder; } public void particleOnly(RegistryObject block, ResourceLocation particleTexture) { diff --git a/src/generated/resources/assets/biomancy/blockstates/acid_cauldron.json b/src/generated/resources/assets/biomancy/blockstates/acid_cauldron.json index 969de861e..eb307c8b7 100644 --- a/src/generated/resources/assets/biomancy/blockstates/acid_cauldron.json +++ b/src/generated/resources/assets/biomancy/blockstates/acid_cauldron.json @@ -1,7 +1,13 @@ { "variants": { - "": { - "model": "biomancy:block/acid_cauldron" + "level=1": { + "model": "biomancy:block/acid_cauldron_level_1" + }, + "level=2": { + "model": "biomancy:block/acid_cauldron_level_2" + }, + "level=3": { + "model": "biomancy:block/acid_cauldron_full" } } } \ No newline at end of file diff --git a/src/generated/resources/assets/biomancy/models/block/acid_cauldron.json b/src/generated/resources/assets/biomancy/models/block/acid_cauldron.json deleted file mode 100644 index d8959ae4a..000000000 --- a/src/generated/resources/assets/biomancy/models/block/acid_cauldron.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:block/lava_cauldron", - "textures": { - "content": "biomancy:fluid/acid_overlay" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/biomancy/models/block/acid_cauldron_full.json b/src/generated/resources/assets/biomancy/models/block/acid_cauldron_full.json new file mode 100644 index 000000000..d88206679 --- /dev/null +++ b/src/generated/resources/assets/biomancy/models/block/acid_cauldron_full.json @@ -0,0 +1,12 @@ +{ + "parent": "minecraft:block/template_cauldron_full", + "render_type": "minecraft:translucent", + "textures": { + "bottom": "minecraft:block/cauldron_bottom", + "content": "minecraft:block/water_still", + "inside": "minecraft:block/cauldron_inner", + "particle": "minecraft:block/cauldron_side", + "side": "minecraft:block/cauldron_side", + "top": "minecraft:block/cauldron_top" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/biomancy/models/block/acid_cauldron_level_1.json b/src/generated/resources/assets/biomancy/models/block/acid_cauldron_level_1.json new file mode 100644 index 000000000..9c5f26848 --- /dev/null +++ b/src/generated/resources/assets/biomancy/models/block/acid_cauldron_level_1.json @@ -0,0 +1,12 @@ +{ + "parent": "minecraft:block/template_cauldron_level1", + "render_type": "minecraft:translucent", + "textures": { + "bottom": "minecraft:block/cauldron_bottom", + "content": "minecraft:block/water_still", + "inside": "minecraft:block/cauldron_inner", + "particle": "minecraft:block/cauldron_side", + "side": "minecraft:block/cauldron_side", + "top": "minecraft:block/cauldron_top" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/biomancy/models/block/acid_cauldron_level_2.json b/src/generated/resources/assets/biomancy/models/block/acid_cauldron_level_2.json new file mode 100644 index 000000000..90db92d69 --- /dev/null +++ b/src/generated/resources/assets/biomancy/models/block/acid_cauldron_level_2.json @@ -0,0 +1,12 @@ +{ + "parent": "minecraft:block/template_cauldron_level2", + "render_type": "minecraft:translucent", + "textures": { + "bottom": "minecraft:block/cauldron_bottom", + "content": "minecraft:block/water_still", + "inside": "minecraft:block/cauldron_inner", + "particle": "minecraft:block/cauldron_side", + "side": "minecraft:block/cauldron_side", + "top": "minecraft:block/cauldron_top" + } +} \ No newline at end of file diff --git a/src/main/java/com/github/elenterius/biomancy/block/cauldron/AcidCauldron.java b/src/main/java/com/github/elenterius/biomancy/block/cauldron/AcidCauldron.java index 965adb343..0ab2f5785 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/cauldron/AcidCauldron.java +++ b/src/main/java/com/github/elenterius/biomancy/block/cauldron/AcidCauldron.java @@ -1,66 +1,73 @@ package com.github.elenterius.biomancy.block.cauldron; -import com.github.elenterius.biomancy.fluid.AcidFluid; -import com.github.elenterius.biomancy.init.ModFluids; -import com.github.elenterius.biomancy.init.ModItems; +import com.github.elenterius.biomancy.init.AcidInteractions; import net.minecraft.core.BlockPos; -import net.minecraft.core.cauldron.CauldronInteraction; +import net.minecraft.sounds.SoundSource; +import net.minecraft.stats.Stats; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; +import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.AbstractCauldronBlock; +import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LayeredCauldronBlock; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; import net.minecraft.world.phys.BlockHitResult; -import net.minecraftforge.common.SoundActions; -import net.minecraftforge.registries.ForgeRegistries; -import org.jetbrains.annotations.NotNull; -import java.util.Map; -import java.util.Objects; +public class AcidCauldron extends LayeredCauldronBlock { -public class AcidCauldron extends AbstractCauldronBlock { - public AcidCauldron() { - super(Properties.copy(Blocks.CAULDRON),getInteractions()); + public AcidCauldron(Properties properties) { + super(properties, precipitation -> false, AcidInteractions.ACID_CAULDRON); } - private static Map getInteractions() { - Map map = CauldronInteraction.newInteractionMap(); - map.put(Items.BUCKET, (pBlockState, pLevel, pPos, pPlayer, pHand, pEmptyStack) -> CauldronInteraction.fillBucket(pBlockState, pLevel, pPos, pPlayer, pHand, pEmptyStack, ModItems.ACID_BUCKET.get().getDefaultInstance(), (_stack)->true, Objects.requireNonNull(ModFluids.ACID_TYPE.get().getSound(SoundActions.BUCKET_FILL)))); - return map; + @Override + protected boolean canReceiveStalactiteDrip(Fluid fluid) { + return false; } @Override public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) { - if (!(entity instanceof LivingEntity)) return; - AcidFluid.onEntityInside((LivingEntity)entity); + if (entity instanceof LivingEntity livingEntity && isEntityInsideContent(state, pos, entity)) { + if (livingEntity.tickCount % 5 != 0) return; + AcidInteractions.handleEntityInsideAcid(livingEntity); + } } @Override - public boolean isFull(BlockState pState) { - return true; + protected void handleEntityOnFireInside(BlockState state, Level level, BlockPos pos) { + //do nothing + } + + @Override + public void handlePrecipitation(BlockState state, Level level, BlockPos pos, Biome.Precipitation precipitation) { + //do nothing } @Override public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - //No idea why, but MC freaks out without this line. super.use() should cover it, but it doesn't so... - if (getInteractions().containsKey(player.getItemInHand(hand).getItem())) return getInteractions().get(player.getItemInHand(hand).getItem()).interact(state,level,pos,player,hand,player.getItemInHand(hand)); + ItemStack stack = player.getItemInHand(hand); + + if (stack.getItem() instanceof BlockItem blockItem) { + Block block = blockItem.getBlock(); + Block convertedBlock = AcidInteractions.convertBlock(block); + if (convertedBlock != null) { + if (!level.isClientSide()) { + player.setItemInHand(hand, new ItemStack(convertedBlock.asItem(), stack.getCount())); + player.awardStat(Stats.USE_CAULDRON); + + SoundType soundType = block.getSoundType(block.defaultBlockState(), level, pos, null); + level.playSound(null, pos, soundType.getHitSound(), SoundSource.BLOCKS, soundType.volume, soundType.pitch); + level.levelEvent(LevelEvent.LAVA_FIZZ, pos, 0); + } - //An attempt to allow the player to do all the erosion interactions inside the cauldron. - //It mostly works, copper being a weird exception. - Block block = ForgeRegistries.BLOCKS.getValue(ForgeRegistries.ITEMS.getKey(player.getItemInHand(hand).getItem())); - if (!Objects.isNull(block)) { - BlockState eroded = AcidFluid.getEroded(block.defaultBlockState()); - if (!Objects.isNull(eroded)) { - player.setItemInHand(hand,new ItemStack(eroded.getBlock().asItem(),player.getItemInHand(hand).getCount())); - return InteractionResult.SUCCESS; + return InteractionResult.sidedSuccess(level.isClientSide()); } } diff --git a/src/main/java/com/github/elenterius/biomancy/block/cauldron/package-info.java b/src/main/java/com/github/elenterius/biomancy/block/cauldron/package-info.java new file mode 100644 index 000000000..cf8bd1c2e --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/block/cauldron/package-info.java @@ -0,0 +1,7 @@ +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package com.github.elenterius.biomancy.block.cauldron; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/com/github/elenterius/biomancy/entity/projectile/AcidBlobProjectile.java b/src/main/java/com/github/elenterius/biomancy/entity/projectile/AcidBlobProjectile.java index 4a1a2d6d2..81ba443a7 100644 --- a/src/main/java/com/github/elenterius/biomancy/entity/projectile/AcidBlobProjectile.java +++ b/src/main/java/com/github/elenterius/biomancy/entity/projectile/AcidBlobProjectile.java @@ -1,5 +1,6 @@ package com.github.elenterius.biomancy.entity.projectile; +import com.github.elenterius.biomancy.block.cauldron.AcidCauldron; import com.github.elenterius.biomancy.block.veins.FleshVeinsBlock; import com.github.elenterius.biomancy.init.ModBlocks; import com.github.elenterius.biomancy.init.ModEntityTypes; @@ -13,6 +14,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LayeredCauldronBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import software.bernie.geckolib.animatable.GeoEntity; @@ -42,6 +44,10 @@ public void setCanPlaceAcidFluid(boolean flag) { canPlaceAcidFluid = flag; } + public boolean canPlaceAcidFluid() { + return canPlaceAcidFluid; + } + @Override public void readAdditionalSaveData(CompoundTag tag) { super.readAdditionalSaveData(tag); @@ -64,6 +70,15 @@ protected void onHitBlock(BlockHitResult result) { super.onHitBlock(result); } + @Override + protected void onInsideBlock(BlockState state) { + if (!level().isClientSide && canPlaceAcidFluid) { + if (state.getBlock() == Blocks.CAULDRON || (state.getBlock() instanceof AcidCauldron cauldron && !cauldron.isFull(state))) { + level().setBlockAndUpdate(blockPosition(), ModBlocks.ACID_CAULDRON.get().defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3)); + } + } + } + private boolean placeAcidFluid(BlockHitResult result) { BlockPos pos = result.getBlockPos(); BlockPos posRelative = pos.relative(result.getDirection()); diff --git a/src/main/java/com/github/elenterius/biomancy/event/LivingEventHandler.java b/src/main/java/com/github/elenterius/biomancy/event/LivingEventHandler.java index 01eac44c8..d571c8cfb 100644 --- a/src/main/java/com/github/elenterius/biomancy/event/LivingEventHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/event/LivingEventHandler.java @@ -1,7 +1,7 @@ package com.github.elenterius.biomancy.event; import com.github.elenterius.biomancy.BiomancyMod; -import com.github.elenterius.biomancy.fluid.AcidFluid; +import com.github.elenterius.biomancy.init.AcidInteractions; import com.github.elenterius.biomancy.init.ModEnchantments; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.living.LivingEvent; @@ -16,7 +16,7 @@ private LivingEventHandler() {} @SubscribeEvent public static void onLivingTick(final LivingEvent.LivingTickEvent event) { - AcidFluid.onEntityInside(event.getEntity()); + AcidInteractions.handleEntityInsideAcidFluid(event.getEntity()); } @SubscribeEvent diff --git a/src/main/java/com/github/elenterius/biomancy/fluid/AcidFluid.java b/src/main/java/com/github/elenterius/biomancy/fluid/AcidFluid.java index b928e1616..775b718f4 100644 --- a/src/main/java/com/github/elenterius/biomancy/fluid/AcidFluid.java +++ b/src/main/java/com/github/elenterius/biomancy/fluid/AcidFluid.java @@ -1,17 +1,14 @@ package com.github.elenterius.biomancy.fluid; import com.github.elenterius.biomancy.block.veins.FleshVeinsBlock; -import com.github.elenterius.biomancy.init.ModBlocks; -import com.github.elenterius.biomancy.init.ModFluids; +import com.github.elenterius.biomancy.init.AcidInteractions; import com.github.elenterius.biomancy.init.tags.ModBlockTags; -import com.github.elenterius.biomancy.util.CombatUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; @@ -20,62 +17,15 @@ import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.fluids.ForgeFlowingFluid; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; public abstract class AcidFluid extends ForgeFlowingFluid { - protected static final Map NORMAL_TO_ERODED_BLOCK_CONVERSION = Map.of( - Blocks.GRASS_BLOCK, Blocks.DIRT.defaultBlockState(), - Blocks.COBBLESTONE, Blocks.GRAVEL.defaultBlockState(), - Blocks.STONE_BRICKS, Blocks.CRACKED_STONE_BRICKS.defaultBlockState(), - Blocks.DEEPSLATE_BRICKS, Blocks.CRACKED_DEEPSLATE_BRICKS.defaultBlockState(), - Blocks.DEEPSLATE_TILES, Blocks.CRACKED_DEEPSLATE_TILES.defaultBlockState(), - Blocks.POLISHED_BLACKSTONE_BRICKS, Blocks.CRACKED_POLISHED_BLACKSTONE_BRICKS.defaultBlockState(), - Blocks.NETHER_BRICKS, Blocks.CRACKED_NETHER_BRICKS.defaultBlockState() - ); - protected AcidFluid(Properties properties) { super(properties); } - public static void onEntityInside(LivingEntity livingEntity) { - if (livingEntity.isSpectator()) return; - if (livingEntity.tickCount % 5 != 0) return; - if (!livingEntity.isInFluidType(ModFluids.ACID_TYPE.get()) && !livingEntity.getFeetBlockState().is(ModBlocks.ACID_CAULDRON.get())) return; - - if (!livingEntity.level().isClientSide) { - CombatUtil.applyAcidEffect(livingEntity, 4); - } - else if (livingEntity.tickCount % 10 == 0 && livingEntity.getRandom().nextFloat() < 0.4f) { - Level level = livingEntity.level(); - RandomSource random = livingEntity.getRandom(); - Vec3 pos = livingEntity.position(); - double height = livingEntity.getBoundingBox().getYsize() * 0.5f; - - level.playLocalSound(pos.x, pos.y, pos.z, SoundEvents.LAVA_EXTINGUISH, SoundSource.BLOCKS, 0.5f, 2.6f + (random.nextFloat() - random.nextFloat()) * 0.8f, false); - for (int i = 0; i < 4; i++) { - level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x + random.nextDouble(), pos.y + random.nextDouble() * height, pos.z + random.nextDouble(), 0, 0.1d, 0); - } - } - } - - @Nullable - public static BlockState getEroded(BlockState state) { - if (state instanceof WeatheringCopper && WeatheringCopper.getNext(state.getBlock()).isPresent()) { - return WeatheringCopper.getNext(state.getBlock()).get().defaultBlockState(); - } else if (state.is(ModBlockTags.ACID_DESTRUCTIBLE)) { - return Blocks.AIR.defaultBlockState(); - } else if (NORMAL_TO_ERODED_BLOCK_CONVERSION.containsKey(state.getBlock())) { - return NORMAL_TO_ERODED_BLOCK_CONVERSION.get(state.getBlock()); - } - return null; - } - @Override protected boolean canPassThrough(BlockGetter level, Fluid fluid, BlockPos fromPos, BlockState fromBlockState, Direction direction, BlockPos toPos, BlockState toBlockState, FluidState toFluidState) { return toBlockState.getBlock() instanceof FleshVeinsBlock || super.canPassThrough(level, fluid, fromPos, fromBlockState, direction, toPos, toBlockState, toFluidState); @@ -163,10 +113,10 @@ protected boolean destroyBlock(Level level, BlockPos liquidPos, Block block, Blo } protected boolean erodeBlock(Level level, BlockPos liquidPos, Block block, BlockState blockState, BlockPos pos) { - if (!NORMAL_TO_ERODED_BLOCK_CONVERSION.containsKey(block)) return false; + if (!AcidInteractions.NORMAL_TO_ERODED_BLOCK_CONVERSION.containsKey(block)) return false; SoundType soundType = block.getSoundType(blockState, level, pos, null); - level.setBlockAndUpdate(pos, ForgeEventFactory.fireFluidPlaceBlockEvent(level, pos, liquidPos, NORMAL_TO_ERODED_BLOCK_CONVERSION.get(block))); + level.setBlockAndUpdate(pos, ForgeEventFactory.fireFluidPlaceBlockEvent(level, pos, liquidPos, AcidInteractions.NORMAL_TO_ERODED_BLOCK_CONVERSION.get(block))); level.playSound(null, pos, soundType.getBreakSound(), SoundSource.BLOCKS, soundType.volume, soundType.pitch); level.levelEvent(LevelEvent.LAVA_FIZZ, pos, 0); return true; diff --git a/src/main/java/com/github/elenterius/biomancy/fluid/TintedFluidType.java b/src/main/java/com/github/elenterius/biomancy/fluid/TintedFluidType.java index 816f247d2..0086e6d6d 100644 --- a/src/main/java/com/github/elenterius/biomancy/fluid/TintedFluidType.java +++ b/src/main/java/com/github/elenterius/biomancy/fluid/TintedFluidType.java @@ -109,4 +109,9 @@ public void renderOverlay(Minecraft mc, PoseStack poseStack) { } }); } + + public int getTintColor() { + return colorARGB; + } + } diff --git a/src/main/java/com/github/elenterius/biomancy/init/AcidInteractions.java b/src/main/java/com/github/elenterius/biomancy/init/AcidInteractions.java new file mode 100644 index 000000000..852372496 --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/init/AcidInteractions.java @@ -0,0 +1,160 @@ +package com.github.elenterius.biomancy.init; + +import com.github.elenterius.biomancy.init.tags.ModBlockTags; +import com.github.elenterius.biomancy.util.CombatUtil; +import net.minecraft.core.cauldron.CauldronInteraction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.stats.Stats; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ItemUtils; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LayeredCauldronBlock; +import net.minecraft.world.level.block.WeatheringCopper; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.SoundActions; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Objects; + +public final class AcidInteractions { + + public static final Map ACID_CAULDRON = CauldronInteraction.newInteractionMap(); + + public static final Map NORMAL_TO_ERODED_BLOCK_CONVERSION = Map.of( + Blocks.GRASS_BLOCK, Blocks.DIRT.defaultBlockState(), + Blocks.COBBLESTONE, Blocks.GRAVEL.defaultBlockState(), + Blocks.STONE_BRICKS, Blocks.CRACKED_STONE_BRICKS.defaultBlockState(), + Blocks.DEEPSLATE_BRICKS, Blocks.CRACKED_DEEPSLATE_BRICKS.defaultBlockState(), + Blocks.DEEPSLATE_TILES, Blocks.CRACKED_DEEPSLATE_TILES.defaultBlockState(), + Blocks.POLISHED_BLACKSTONE_BRICKS, Blocks.CRACKED_POLISHED_BLACKSTONE_BRICKS.defaultBlockState(), + Blocks.NETHER_BRICKS, Blocks.CRACKED_NETHER_BRICKS.defaultBlockState() + ); + + private AcidInteractions() {} + + static void register() { + registerCauldronInteractions(); + } + + private static void registerCauldronInteractions() { + final CauldronInteraction fillWithAcid = (state, level, pos, player, hand, stack) -> { + SoundEvent sound = Objects.requireNonNullElse(ModFluids.ACID_TYPE.get().getSound(SoundActions.BUCKET_EMPTY), SoundEvents.BUCKET_EMPTY); + return CauldronInteraction.emptyBucket(level, pos, player, hand, stack, ModBlocks.ACID_CAULDRON.get().defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), sound); + }; + + CauldronInteraction.EMPTY.put(ModItems.ACID_BUCKET.get(), fillWithAcid); + + //we wrap the original potion interaction to retain its behavior while injecting our own logic + final CauldronInteraction originalPotionInteraction = Objects.requireNonNull(CauldronInteraction.EMPTY.get(Items.POTION)); + CauldronInteraction.EMPTY.put(Items.POTION, (state, level, pos, player, hand, stack) -> { + if (PotionUtils.getPotion(stack) != ModPotions.GASTRIC_JUICE.get()) { + return originalPotionInteraction.interact(state, level, pos, player, hand, stack); + } + + if (!level.isClientSide) { + player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE))); + player.awardStat(Stats.USE_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(stack.getItem())); + level.setBlockAndUpdate(pos, ModBlocks.ACID_CAULDRON.get().defaultBlockState()); + level.playSound(null, pos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1f, 1f); + level.gameEvent(player, GameEvent.FLUID_PLACE, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + }); + + ACID_CAULDRON.put(ModItems.ACID_BUCKET.get(), fillWithAcid); + ACID_CAULDRON.put(Items.BUCKET, (state, level, pos, player, hand, stack) -> { + SoundEvent sound = Objects.requireNonNullElse(ModFluids.ACID_TYPE.get().getSound(SoundActions.BUCKET_FILL), SoundEvents.BUCKET_FILL); + return CauldronInteraction.fillBucket(state, level, pos, player, hand, stack, ModItems.ACID_BUCKET.get().getDefaultInstance(), AcidInteractions::isCauldronFull, sound); + }); + ACID_CAULDRON.put(Items.GLASS_BOTTLE, (state, level, pos, player, hand, stack) -> { + if (!level.isClientSide) { + player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, PotionUtils.setPotion(new ItemStack(Items.POTION), ModPotions.GASTRIC_JUICE.get()))); + player.awardStat(Stats.USE_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(stack.getItem())); + LayeredCauldronBlock.lowerFillLevel(state, level, pos); + level.playSound(null, pos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1f, 1f); + level.gameEvent(player, GameEvent.FLUID_PICKUP, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + }); + ACID_CAULDRON.put(Items.POTION, (state, level, pos, player, hand, stack) -> { + if (!isCauldronFull(state) && PotionUtils.getPotion(stack) == ModPotions.GASTRIC_JUICE.get()) { + if (!level.isClientSide) { + player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE))); + player.awardStat(Stats.USE_CAULDRON); + player.awardStat(Stats.ITEM_USED.get(stack.getItem())); + level.setBlockAndUpdate(pos, state.cycle(LayeredCauldronBlock.LEVEL)); + level.playSound(null, pos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1f, 1f); + level.gameEvent(player, GameEvent.FLUID_PLACE, pos); + } + + return InteractionResult.sidedSuccess(level.isClientSide); + } + + return InteractionResult.PASS; + }); + } + + private static boolean isCauldronFull(BlockState state) { + return state.getValue(LayeredCauldronBlock.LEVEL) == 3; + } + + @SuppressWarnings("deprecation") + @Nullable + public static Block convertBlock(Block block) { + if (block instanceof WeatheringCopper && WeatheringCopper.getNext(block).isPresent()) { + return WeatheringCopper.getNext(block).get(); + } + else if (block.builtInRegistryHolder().is(ModBlockTags.ACID_DESTRUCTIBLE)) { + return Blocks.AIR; + } + else if (NORMAL_TO_ERODED_BLOCK_CONVERSION.containsKey(block)) { + return NORMAL_TO_ERODED_BLOCK_CONVERSION.get(block).getBlock(); + } + return null; + } + + public static void handleEntityInsideAcidFluid(LivingEntity livingEntity) { + if (livingEntity.isSpectator()) return; + if (livingEntity.tickCount % 5 != 0) return; + + if (!livingEntity.isInFluidType(ModFluids.ACID_TYPE.get())) return; + + handleEntityInsideAcid(livingEntity); + } + + public static void handleEntityInsideAcid(LivingEntity livingEntity) { + if (!livingEntity.level().isClientSide) { + CombatUtil.applyAcidEffect(livingEntity, 4); + } + else if (livingEntity.tickCount % 10 == 0 && livingEntity.getRandom().nextFloat() < 0.4f) { + Level level = livingEntity.level(); + RandomSource random = livingEntity.getRandom(); + Vec3 pos = livingEntity.position(); + double height = livingEntity.getBoundingBox().getYsize() * 0.5f; + + level.playLocalSound(pos.x, pos.y, pos.z, SoundEvents.LAVA_EXTINGUISH, SoundSource.BLOCKS, 0.5f, 2.6f + (random.nextFloat() - random.nextFloat()) * 0.8f, false); + for (int i = 0; i < 4; i++) { + level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x + random.nextDouble(), pos.y + random.nextDouble() * height, pos.z + random.nextDouble(), 0, 0.1d, 0); + } + } + } + +} diff --git a/src/main/java/com/github/elenterius/biomancy/init/CommonSetupHandler.java b/src/main/java/com/github/elenterius/biomancy/init/CommonSetupHandler.java index cec7328a8..006017bc6 100644 --- a/src/main/java/com/github/elenterius/biomancy/init/CommonSetupHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/init/CommonSetupHandler.java @@ -39,6 +39,8 @@ public static void onSetup(final FMLCommonSetupEvent event) { registerDispenserBehaviors(); ModRecipes.registerComposterRecipes(); + AcidInteractions.register(); + //dumpBiomeTemperatureAndHumidity(); }); diff --git a/src/main/java/com/github/elenterius/biomancy/init/ModBlocks.java b/src/main/java/com/github/elenterius/biomancy/init/ModBlocks.java index 7ebc0c069..5b198c679 100644 --- a/src/main/java/com/github/elenterius/biomancy/init/ModBlocks.java +++ b/src/main/java/com/github/elenterius/biomancy/init/ModBlocks.java @@ -137,7 +137,7 @@ public final class ModBlocks { public static final RegistryObject FLESH_DOOR = register("flesh_door", FleshDoorBlock::new); public static final RegistryObject FULL_FLESH_DOOR = register("full_flesh_door", FullFleshDoorBlock::new); public static final RegistryObject TENDON_CHAIN = register("tendon_chain", properties -> new FleshChainBlock(properties.noOcclusion())); - public static final RegistryObject ACID_CAULDRON = register("acid_cauldron", AcidCauldron::new); + public static final RegistryObject ACID_CAULDRON = register("acid_cauldron", () -> new AcidCauldron(copyProperties(Blocks.CAULDRON))); private ModBlocks() {} diff --git a/src/main/java/com/github/elenterius/biomancy/init/ModFluids.java b/src/main/java/com/github/elenterius/biomancy/init/ModFluids.java index 400886161..fa26494ba 100644 --- a/src/main/java/com/github/elenterius/biomancy/init/ModFluids.java +++ b/src/main/java/com/github/elenterius/biomancy/init/ModFluids.java @@ -27,7 +27,7 @@ public final class ModFluids { public static final DeferredRegister FLUID_TYPES = DeferredRegister.create(ForgeRegistries.Keys.FLUID_TYPES, BiomancyMod.MOD_ID); public static final DeferredRegister FLUIDS = DeferredRegister.create(ForgeRegistries.FLUIDS, BiomancyMod.MOD_ID); - public static final RegistryObject ACID_TYPE = registerTintedType("acid", 0xFF_39FF14, properties -> properties.density(1024).viscosity(1024)); + public static final RegistryObject ACID_TYPE = registerTintedType("acid", 0xFF_39FF14, properties -> properties.density(1024).viscosity(1024)); public static final Supplier ACID_FLUID_PROPERTIES = () -> new ForgeFlowingFluid .Properties(ACID_TYPE, ModFluids.ACID, ModFluids.FLOWING_ACID) .slopeFindDistance(2) @@ -54,7 +54,7 @@ private static RegistryObject register(String name, Supplie return FLUIDS.register(name, factory); } - private static RegistryObject registerTintedType(String name, int colorARGB, UnaryOperator operator) { + private static RegistryObject registerTintedType(String name, int colorARGB, UnaryOperator operator) { return FLUID_TYPES.register(name, () -> new TintedFluidType(operator.apply(createFluidTypeProperties()), colorARGB)); } diff --git a/src/main/java/com/github/elenterius/biomancy/init/ModItems.java b/src/main/java/com/github/elenterius/biomancy/init/ModItems.java index 0b6046a53..77713de94 100644 --- a/src/main/java/com/github/elenterius/biomancy/init/ModItems.java +++ b/src/main/java/com/github/elenterius/biomancy/init/ModItems.java @@ -11,7 +11,6 @@ import com.github.elenterius.biomancy.item.weapon.RavenousClawsItem; import com.github.elenterius.biomancy.item.weapon.gun.CausticGunbladeItem; import com.github.elenterius.biomancy.item.weapon.gun.DevArmCannonItem; -import net.minecraft.core.cauldron.CauldronInteraction; import net.minecraft.util.Mth; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; @@ -21,12 +20,10 @@ import net.minecraft.world.item.*; import net.minecraft.world.level.block.Block; import net.minecraftforge.common.ForgeSpawnEggItem; -import net.minecraftforge.common.SoundActions; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegistryObject; -import java.util.Objects; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; @@ -227,14 +224,7 @@ public static Stream> findEntries(Class cl } private static RegistryObject registerItem(String name, Function factory) { - RegistryObject ret = ITEMS.register(name, () -> factory.apply(createProperties())); - if (name.equals("biomancy:acid_bucket")) { - //Register Cauldron filling for Acid - CauldronInteraction.EMPTY.put(ret.get(),(state, level, pos, player, hand, stack)->{ - return CauldronInteraction.emptyBucket(level,pos,player,hand,stack, ModBlocks.ACID_CAULDRON.get().defaultBlockState(), Objects.requireNonNull(ModFluids.ACID.get().getFluidType().getSound(SoundActions.BUCKET_EMPTY))); - }); - } - return ret; + return ITEMS.register(name, () -> factory.apply(createProperties())); } private static RegistryObject registerSimpleBlockItem(RegistryObject blockHolder) { diff --git a/src/main/java/com/github/elenterius/biomancy/init/client/ClientSetupHandler.java b/src/main/java/com/github/elenterius/biomancy/init/client/ClientSetupHandler.java index 394b33e9d..6f5ec27b8 100644 --- a/src/main/java/com/github/elenterius/biomancy/init/client/ClientSetupHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/init/client/ClientSetupHandler.java @@ -163,6 +163,7 @@ public static void onItemColorRegistry(final RegisterColorHandlersEvent.Item eve public static void onBlockColorRegistry(final RegisterColorHandlersEvent.Block event) { event.register(VialHolderBlock::getTintColor, ModBlocks.VIAL_HOLDER.get()); event.register(BiometricMembraneBlock::getTintColor, ModBlocks.BIOMETRIC_MEMBRANE.get()); + event.register((state, level, pos, tintIndex) -> tintIndex == 0 ? ModFluids.ACID_TYPE.get().getTintColor() : 0xFF_FFFFFF, ModBlocks.ACID_CAULDRON.get()); } @SubscribeEvent diff --git a/src/main/java/com/github/elenterius/biomancy/mixin/AbstractCauldronBlockMixin.java b/src/main/java/com/github/elenterius/biomancy/mixin/AbstractCauldronBlockMixin.java deleted file mode 100644 index f8cb18da7..000000000 --- a/src/main/java/com/github/elenterius/biomancy/mixin/AbstractCauldronBlockMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.github.elenterius.biomancy.mixin; - -import com.github.elenterius.biomancy.init.ModBlocks; -import com.github.elenterius.biomancy.init.ModFluids; -import com.github.elenterius.biomancy.init.ModItems; -import net.minecraft.core.BlockPos; -import net.minecraft.core.cauldron.CauldronInteraction; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.AbstractCauldronBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraftforge.common.SoundActions; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Objects; - -@Mixin(value= AbstractCauldronBlock.class) -public abstract class AbstractCauldronBlockMixin { - @Inject(at=@At("TAIL"),method="Lnet/minecraft/world/level/block/AbstractCauldronBlock;use(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/BlockHitResult;)Lnet/minecraft/world/InteractionResult;", cancellable = true) - public void biomancy$use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit, CallbackInfoReturnable cir) { - //Allow the Acid bucket to fill Cauldrons. I have no idea why this should require a mixin, beyond "Just Vanilla Things". - if (player.getItemInHand(hand).getItem().equals(ModItems.ACID_BUCKET.get())) { - cir.setReturnValue(CauldronInteraction.emptyBucket(level,pos,player,hand,player.getItemInHand(hand), ModBlocks.ACID_CAULDRON.get().defaultBlockState(), Objects.requireNonNull(ModFluids.ACID_TYPE.get().getSound(SoundActions.BUCKET_FILL)))); - } - } -} diff --git a/src/main/resources/mixins.biomancy.json b/src/main/resources/mixins.biomancy.json index b334a67fd..cc8d476d3 100644 --- a/src/main/resources/mixins.biomancy.json +++ b/src/main/resources/mixins.biomancy.json @@ -8,7 +8,7 @@ "defaultRequire": 1 }, "mixins": [ - "AbstractCauldronBlockMixin", "AgeableMobAccessor", "AreaEffectCloudMixin", "ArmorStandAccessor", "ArrowMixin", "BiomeAccessor", "DamageSourceAccessor", + "AgeableMobAccessor", "AreaEffectCloudMixin", "ArmorStandAccessor", "ArrowMixin", "BiomeAccessor", "DamageSourceAccessor", "EntityAccessor", "IntegerPropertyAccessor", "LivingEntityAccessor", "LivingEntityMixin", "MobEffectInstanceAccessor", "MobEffectInstanceMixin", "MobEntityAccessor", "PhantomMixin", "PlayerMixin", "ServerLevelAccessor", "ServerLevelMixin", "SlimeAccessor", "SuspiciousStewItemAccessor", "SwordItemMixinAccessor", "TadpoleAccessor", "TextureSlotAccessor", "ThrownPotionMixin", "UnbreakingEnchantmentMixin", "WallBlockMixin",