Create

Create

86M Downloads

Make IEffectHandler#applyEffects pass FluidStack with real input fluid amout of 1 (mb) when needed.

MarbleGateKeeper opened this issue ยท 0 comments

commented

Current Behavior:

For Dev who depends on create on modding, OpenEndedPipe$IEffectHandler is used for creating custom fluid leaking effect on Open Ended Pipe (or simply leaking point). However, when fluid has no corresponding BlockState, which means that fluid is a virtual fluid, FluidStack be passed into OpenEndedPipe$IEffectHandler#applyEffects has always 1 (mb) amount,

In OpenEndedPipe$OpenEndFluidHandler#fill, when FluidHelper.hasBlockState(containedFluidStack.getFluid()) returns false, passed-in value resource will be reset as same fluid with amout of 1(mb).

FluidStack containedFluidStack = getFluid();
boolean hasBlockState = FluidHelper.hasBlockState(containedFluidStack.getFluid());
if (!containedFluidStack.isEmpty() && !containedFluidStack.isFluidEqual(resource))
setFluid(FluidStack.EMPTY);
if (wasPulling)
wasPulling = false;
if (canApplyEffects(resource) && !hasBlockState)
resource = FluidHelper.copyStackWithAmount(resource, 1);

Above behavior might be enough for PotionEffectHandler and MilkEffectHandler, since former one only needs nbt data of FluidStack and later one doesn't even need FluidStack itself. But for these who needs not only fluid data but amount itself, current design is not enough.

Example:

In our Create Addon Enchantment Industry, we add a virtual fluid called Liquid Experience, which obviously, represents experience. Player use various method to collect it form loots, experience nuggets and themselve's experience bar.
At leaking point, a reasonable behavior of liquid experience should be changing to experience orb that carries percisely leaking amount of experience. So we register corresponding IEffectHandler with following overrided OpenEndedPipe$IEffectHandler#applyEffects method:

    @Override
    public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) {
        var players = pipe.getWorld().getEntitiesOfClass(Player.class, pipe.getAOE(), LivingEntity::isAlive);
        var level = pipe.getWorld();
        var pos = pipe.getOutputPos();
        var pipePos = pipe.getPos();
        var speed = new Vec3(pos.getX() - pipePos.getX(), pos.getY() - pipePos.getY(), pos.getZ() - pipePos.getZ()).scale(0.2);
        var xpPos = VecHelper.getCenterOf(pos);
        int amount = fluid.getAmount();
        if (players.isEmpty()) {
            awardExperienceOrDrop(null, level, xpPos, speed, amount);
        } else {
            int partial = amount / players.size();
            int left = amount % players.size();
            players.forEach(player -> {
                CeiAdvancements.A_SHOWER_EXPERIENCE.getTrigger().trigger((ServerPlayer) player);
                awardExperienceOrDrop(player, level, xpPos, speed, partial);
            });
            if (left != 0) {
                var lucky = players.get(level.random.nextInt(players.size()));
                awardExperienceOrDrop(lucky, level, xpPos, speed, left);
            }
        }
    }

In our expectation, we obtains leaking amount from passed-in FluidStack and distribute exactly same amount as obtained of experience to experience orb or nearby player.
Obviously we cannot see expected behavior since all passed-in FluidStack has amout of 1 (mb).

And there is neither javadoc nor percise explaination on wiki/Attaching-TileEntity-Behaviours. It definitely casuses confusing when user want to implement some amount-related-functions, well, with tons of time spending on debugging and making a patch by Mixin.

Possible Solution?

In order to keep consistency of old code and also provides a solution for situation which indeed needs that "amount", we can
add a new method into OpenEndedPipe$IEffectHandler:

		default boolean isAmountRelated(){
			return false;
		}

And make corresponding place in OpenEndedPipe$OpenEndFluidHandler#fill.