Fluids in barrels and crucibles now affect mobs

This commit is contained in:
thedarkcolour 2024-06-08 16:47:49 -07:00
parent e531abf6cc
commit 5b0ba2ef31
No known key found for this signature in database
GPG Key ID: 6599A8E0516C8F38
10 changed files with 153 additions and 26 deletions

View File

@ -19,6 +19,8 @@
package thedarkcolour.exdeorum.block;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -33,7 +35,10 @@ import thedarkcolour.exdeorum.registry.EBlockEntities;
import java.util.function.Supplier;
public abstract class AbstractCrucibleBlock extends EBlock {
public abstract class AbstractCrucibleBlock extends ETankBlock {
public static final float CRUCIBLE_FLUID_BOTTOM = 4.0f / 16f;
public static final float CRUCIBLE_FLUID_TOP = 14.0f / 16f;
public AbstractCrucibleBlock(Properties properties, Supplier<? extends BlockEntityType<?>> blockEntityType) {
super(properties, blockEntityType);
}
@ -57,4 +62,10 @@ public abstract class AbstractCrucibleBlock extends EBlock {
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState pState, BlockEntityType<T> type) {
return (type == EBlockEntities.WATER_CRUCIBLE.get() || type == EBlockEntities.LAVA_CRUCIBLE.get()) ? (BlockEntityTicker<T>) new AbstractCrucibleBlockEntity.Ticker() : null;
}
@Override
protected boolean isEntityInFluid(Level level, BlockPos pos, Entity entity, float fillRatio) {
var fluidTop = Mth.lerp(fillRatio, CRUCIBLE_FLUID_BOTTOM, CRUCIBLE_FLUID_TOP);
return entity.getY() < pos.getY() + fluidTop && entity.getBoundingBox().maxY > pos.getY() + CRUCIBLE_FLUID_BOTTOM;
}
}

View File

@ -19,6 +19,8 @@
package thedarkcolour.exdeorum.block;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
@ -26,6 +28,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
@ -34,11 +37,14 @@ import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.blockentity.BarrelBlockEntity;
import thedarkcolour.exdeorum.registry.EBlockEntities;
public class BarrelBlock extends EBlock {
public class BarrelBlock extends ETankBlock {
public static final float BARREL_FLUID_BOTTOM = 1f / 16f;
public static final float BARREL_FLUID_TOP = 14f / 16f;
public static final VoxelShape SHAPE = Shapes.join(
box(1, 0, 1, 15, 16, 15),
box(2, 1, 2, 14, 16, 14),
BooleanOp.ONLY_FIRST
box(1, 0, 1, 15, 16, 15),
box(2, 1, 2, 14, 16, 14),
BooleanOp.ONLY_FIRST
);
public BarrelBlock(Properties properties) {
@ -87,4 +93,10 @@ public class BarrelBlock extends EBlock {
}
}
}
@Override
protected boolean isEntityInFluid(Level level, BlockPos pos, Entity entity, float fillRatio) {
var fluidTop = Mth.lerp(fillRatio, BARREL_FLUID_BOTTOM, BARREL_FLUID_TOP);
return entity.getBoundingBox().intersects(pos.getX() + 0.125, pos.getY() + BARREL_FLUID_BOTTOM, pos.getZ() + 0.125, pos.getX() + 0.875, pos.getY() + fluidTop, pos.getZ() + 0.875);
}
}

View File

@ -0,0 +1,71 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.fluids.FluidStack;
import thedarkcolour.exdeorum.blockentity.ETankBlockEntity;
import thedarkcolour.exdeorum.registry.EFluids;
import java.util.function.Supplier;
// Base class for blocks that hold fluids (crucible, barrel)
public abstract class ETankBlock extends EBlock {
public ETankBlock(Properties properties, Supplier<? extends BlockEntityType<?>> blockEntityType) {
super(properties, blockEntityType);
}
@Override
public void entityInside(BlockState state, Level level, BlockPos pos, Entity entity) {
if (!level.isClientSide && level.getBlockEntity(pos) instanceof ETankBlockEntity blockEntity) {
var tank = blockEntity.getTank();
var fluid = tank.getFluid();
if (!fluid.isEmpty() && isEntityInFluid(level, pos, entity, (float) fluid.getAmount() / tank.getCapacity())) {
entityInFluidLogic(level, entity, fluid);
}
}
}
protected abstract boolean isEntityInFluid(Level level, BlockPos pos, Entity entity, float fillRatio);
// Only call this on the server
public static void entityInFluidLogic(Level level, Entity entity, FluidStack fluid) {
var fluidType = fluid.getFluid();
if (fluidType == Fluids.LAVA) {
entity.lavaHurt();
} else if (fluidType == EFluids.WITCH_WATER.get()) {
WitchWaterBlock.witchWaterEntityEffects(level, entity);
} else if (fluidType.getFluidType().canExtinguish(entity)) {
entity.extinguishFire();
} else if (entity instanceof LivingEntity living && ForgeMod.MILK.isPresent() && fluidType == ForgeMod.MILK.get()) {
living.curePotionEffects(new ItemStack(Items.MILK_BUCKET));
}
}
}

View File

@ -49,7 +49,14 @@ public class WitchWaterBlock extends LiquidBlock {
@Override
public void entityInside(BlockState pState, Level level, BlockPos pPos, Entity entity) {
if (!level.isClientSide && entity.isAlive()) {
if (!level.isClientSide) {
witchWaterEntityEffects(level, entity);
}
}
// Only call on server
public static void witchWaterEntityEffects(Level level, Entity entity) {
if (entity.isAlive()) {
var entityType = entity.getType();
if (EConfig.SERVER.allowWitchWaterEntityConversion.get()) {
@ -70,7 +77,7 @@ public class WitchWaterBlock extends LiquidBlock {
zombieVillager.setTradeOffers(villager.getOffers().createTag());
zombieVillager.setVillagerXp(villager.getVillagerXp());
net.minecraftforge.event.ForgeEventFactory.onLivingConvert(villager, zombieVillager);
ForgeEventFactory.onLivingConvert(villager, zombieVillager);
villager.discard();
}

View File

@ -63,7 +63,7 @@ import java.util.HashMap;
import java.util.function.Consumer;
@SuppressWarnings("deprecation")
public abstract class AbstractCrucibleBlockEntity extends EBlockEntity {
public abstract class AbstractCrucibleBlockEntity extends ETankBlockEntity {
public static final Lazy<HashMap<Item, Block>> MELT_OVERRIDES = Lazy.concurrentOf(() -> {
var map = new HashMap<Item, Block>();
addMeltOverrides(map);
@ -248,6 +248,7 @@ public abstract class AbstractCrucibleBlockEntity extends EBlockEntity {
return this.solids;
}
@Override
public FluidTank getTank() {
return this.tank;
}

View File

@ -67,7 +67,7 @@ import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe;
import thedarkcolour.exdeorum.registry.EBlockEntities;
import thedarkcolour.exdeorum.registry.ESounds;
public class BarrelBlockEntity extends EBlockEntity {
public class BarrelBlockEntity extends ETankBlockEntity {
private static final int MOSS_SPREAD_RANGE = 2;
private static final int MAX_CAPACITY = 1000;
@ -209,6 +209,7 @@ public class BarrelBlockEntity extends EBlockEntity {
this.item.setStackInSlot(0, item);
}
@Override
public IFluidTank getTank() {
return this.tank;
}

View File

@ -0,0 +1,33 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.blockentity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.fluids.IFluidTank;
// Base class for blocks that hold fluids (crucible, barrel)
public abstract class ETankBlockEntity extends EBlockEntity {
public ETankBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
public abstract IFluidTank getTank();
}

View File

@ -36,6 +36,7 @@ import net.minecraft.world.item.ItemDisplayContext;
import net.minecraftforge.client.model.data.ModelData;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.block.BarrelBlock;
import thedarkcolour.exdeorum.blockentity.BarrelBlockEntity;
import thedarkcolour.exdeorum.client.RenderUtil;
@ -81,7 +82,7 @@ public class BarrelRenderer implements BlockEntityRenderer<BarrelBlockEntity> {
var level = barrel.getLevel();
var pos = barrel.getBlockPos();
var percentage = fluidStack.getAmount() / 1000.0f;
var y = Mth.lerp(percentage, 1.0f, 14.0f) / 16f;
var y = Mth.lerp(percentage, BarrelBlock.BARREL_FLUID_BOTTOM, BarrelBlock.BARREL_FLUID_TOP);
var inputFluidColor = RenderUtil.getFluidColor(fluid, level, pos);
// Split into RGB components
var r = (inputFluidColor >> 16) & 0xff;
@ -98,7 +99,7 @@ public class BarrelRenderer implements BlockEntityRenderer<BarrelBlockEntity> {
}
if (barrel.transparent) {
RenderUtil.renderFluidCuboid(buffers, stack, level, pos, 1 / 16f, y, 2.0f, light, r, g, b, fluid);
RenderUtil.renderFluidCuboid(buffers, stack, level, pos, BarrelBlock.BARREL_FLUID_BOTTOM, y, 2.0f, light, r, g, b, fluid);
} else {
RenderUtil.renderFlatFluidSprite(buffers, stack, level, pos, y, 2.0f, light, r, g, b, fluid);
}
@ -129,7 +130,7 @@ public class BarrelRenderer implements BlockEntityRenderer<BarrelBlockEntity> {
g = (int) Mth.lerp(compostProgress, g, 169); // default green is
b = (int) Mth.lerp(compostProgress, b, 109); // default green is
RenderUtil.renderFlatSpriteLerp(builder, stack, barrel.compost / 1000.0f, r, g, b, sprite, light, 2.0f, 1.0f, 14.0f);
RenderUtil.renderFlatSpriteLerp(builder, stack, barrel.compost / 1000.0f, r, g, b, sprite, light, 2.0f, BarrelBlock.BARREL_FLUID_BOTTOM, BarrelBlock.BARREL_FLUID_TOP);
}
}
}

View File

@ -24,6 +24,7 @@ import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.util.Mth;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import thedarkcolour.exdeorum.block.AbstractCrucibleBlock;
import thedarkcolour.exdeorum.blockentity.AbstractCrucibleBlockEntity;
import thedarkcolour.exdeorum.client.RenderUtil;
@ -46,14 +47,14 @@ public class CrucibleRenderer implements BlockEntityRenderer<AbstractCrucibleBlo
if (liquid != 0) {
var fluid = fluidStack.getFluid();
var color = RenderUtil.getFluidColor(fluid, level, pos);
float y = Mth.lerp(liquid, 4.0f, 14.0f) / 16f;
float y = Mth.lerp(liquid, AbstractCrucibleBlock.CRUCIBLE_FLUID_BOTTOM, AbstractCrucibleBlock.CRUCIBLE_FLUID_TOP);
int r = (color >> 16) & 0xff;
int g = (color >> 8) & 0xff;
int b = color & 0xff;
if (crucible.transparent) {
RenderUtil.renderFluidCuboid(buffers, stack, level, pos, 4 / 16f, y, 2.0f, light, r, g, b, fluid);
RenderUtil.renderFluidCuboid(buffers, stack, level, pos, AbstractCrucibleBlock.CRUCIBLE_FLUID_BOTTOM, y, 2.0f, light, r, g, b, fluid);
} else {
RenderUtil.renderFlatFluidSprite(buffers, stack, level, pos, y, 2.0f, light, r, g, b, fluid);
}
@ -72,7 +73,7 @@ public class CrucibleRenderer implements BlockEntityRenderer<AbstractCrucibleBlo
if (color == -1) color = 0xffffff;
// todo 3D solids for transparent crucibles
face.renderFlatSpriteLerp(buffers, stack, solids, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, light, 2.0f, 4.0f, 14.0f);
face.renderFlatSpriteLerp(buffers, stack, solids, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, light, 2.0f, AbstractCrucibleBlock.CRUCIBLE_FLUID_BOTTOM, AbstractCrucibleBlock.CRUCIBLE_FLUID_TOP);
}
}
});

View File

@ -51,15 +51,4 @@ public class PorcelainMilkBucket extends MilkBucketItem {
public @Nullable ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundTag nbt) {
return new PorcelainBucket.CapabilityProvider(stack);
}
private static class CapabilityProvider extends PorcelainBucket.CapabilityProvider {
public CapabilityProvider(@NotNull ItemStack container) {
super(container);
}
@Override
public boolean isFluidValid(int tank, @NotNull FluidStack stack) {
return ForgeMod.MILK.isPresent();
}
}
}