package com.thebrokenrail.energonrelics.energy.core.util; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.state.property.Property; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class Action { public interface ActionFunction { void run(World world, BlockPos pos, BlockState state); } private final long cost; private final ActionFunction success; private final ActionFunction fail; public Action(long cost, ActionFunction success, ActionFunction fail) { this.cost = cost; this.success = success; this.fail = fail; } public static > Action createBlockStatePropertyAction(long cost, Property property, T successValue, T failureValue) { return new Action(cost, (world, pos, state) -> { if (!state.get(property).equals(successValue)) { world.setBlockState(pos, state.with(property, successValue)); } }, (world, pos, state) -> { if (!state.get(property).equals(failureValue)) { world.setBlockState(pos, state.with(property, failureValue)); } }); } public interface PropagatedAction { void expandPayments(int amount); long amountOwed(); void pay(long amount); } public static class PropagatedActionImpl implements PropagatedAction { private final Action action; private final World world; private final BlockPos pos; private final Block block; private int expectedPayments = 1; private int payments = 0; private long amountPaid = 0; public PropagatedActionImpl(Action action, World world, BlockPos pos, Block block) { super(); this.action = action; this.world = world; this.pos = pos; this.block = block; } @Override public void expandPayments(int amount) { if (amount < 1) { throw new UnsupportedOperationException(); } expectedPayments = expectedPayments - 1 + amount; } @Override public long amountOwed() { return action.cost - amountPaid; } @Override public void pay(long amount) { amountPaid = amountPaid + amount; payments++; BlockState state = world.getBlockState(pos); if (state != null && state.getBlock() == block) { if (amountOwed() <= 0) { action.success.run(world, pos, state); } else if (payments >= expectedPayments) { action.fail.run(world, pos, state); } } } } }