package com.thebrokenrail.energonrelics.api.energy; import net.minecraft.block.BlockState; import net.minecraft.state.property.Property; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; /** * Action That Can Be Performed With Energy */ 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; /** * Create Action * @param cost Cost In Energon * @param success Success Function * @param fail Failure Function */ public Action(long cost, ActionFunction success, ActionFunction fail) { this.cost = cost; this.success = success; this.fail = fail; } /** * Create Action That Changes Block State Property * @param cost Cost In Energon * @param property Block State Property * @param successValue Value To Set On Success * @param failureValue Value To Set On Failure * @param Block State Property Type * @return New Action */ public static > Action createBlockStatePropertyAction(long cost, Property property, T successValue, T failureValue) { return new Action(cost, (world, pos, state) -> { if (state.contains(property) && !state.get(property).equals(successValue)) { world.setBlockState(pos, state.with(property, successValue)); } }, (world, pos, state) -> { if (state.contains(property) && !state.get(property).equals(failureValue)) { world.setBlockState(pos, state.with(property, failureValue)); } }); } /** * Action That Has Been Propagated */ 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 BlockState state; private int expectedPayments = 1; private int payments = 0; private long amountPaid = 0; public PropagatedActionImpl(Action action, World world, BlockPos pos, BlockState state) { this.action = action; this.world = world; this.pos = pos; this.state = state; } @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++; if (state != null) { if (amountOwed() <= 0) { action.success.run(world, pos, state); } else if (payments >= expectedPayments) { action.fail.run(world, pos, state); } } } } }