EnergonRelics/src/main/java/com/thebrokenrail/energonrelics/energy/core/EnergyReceiverBlockEntity.java

148 lines
4.7 KiB
Java

package com.thebrokenrail.energonrelics.energy.core;
import com.thebrokenrail.energonrelics.component.NetworkComponent;
import com.thebrokenrail.energonrelics.energy.core.util.Action;
import com.thebrokenrail.energonrelics.energy.core.util.EnergyProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.IntArrayTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Tickable;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public abstract class EnergyReceiverBlockEntity extends EnergyProviderBlockEntity implements Tickable {
private class SelfProvider implements EnergyProvider {
@Override
public void addPropagatedAction(Action.PropagatedAction action) {
pendingActionsFromSelf.add(action);
}
@Override
public boolean isNetwork(int network) {
return true;
}
@Override
public boolean isWithinDistance(Vec3d pos) {
return true;
}
}
public EnergyReceiverBlockEntity(BlockEntityType<?> type) {
super(type);
}
private final List<Action.PropagatedAction> pendingActions = new ArrayList<>();
private final List<Action.PropagatedAction> pendingActionsFromSelf = new ArrayList<>();
private final EnergyProvider selfProvider = new SelfProvider();
private final List<EnergyProvider> providers = new ArrayList<>();
private final List<Integer> networks = new ArrayList<>();
private long totalCost = 0;
protected void propagateAction(Action.PropagatedAction action) {
totalCost = totalCost + action.amountOwed();
action.expandPayments(providers.size());
pendingActions.add(action);
}
protected void addAction(Action action) {
propagateAction(new Action.PropagatedActionImpl(action, getWorld(), getPos(), getCachedState().getBlock()));
}
@Override
public void serverTick() {
if (hasWorld() && !Objects.requireNonNull(getWorld()).isClient()) {
// Every Action Must Be Paid At Least Once For a Failure State To Occur
for (Action.PropagatedAction action : pendingActionsFromSelf) {
action.pay(0);
}
pendingActionsFromSelf.clear();
ServerWorld world = (ServerWorld) getWorld();
NetworkComponent component = NetworkComponent.getInstance(world);
providers.clear();
// At Least One Energy Provider Is Always Required
providers.add(selfProvider);
for (int network : networks) {
List<EnergyProvider> potentialProviders = component.getSource(world, network);
for (EnergyProvider provider : potentialProviders) {
Vec3d pos = new Vec3d(getPos().getX() + 0.5d, getPos().getY() + 0.5d, getPos().getZ() + 0.5d);
if (provider.isWithinDistance(pos)) {
providers.add(provider);
}
}
}
totalCost = 0;
pendingActions.clear();
tickEnergy();
super.serverTick();
for (Action.PropagatedAction action : pendingActions) {
for (EnergyProvider provider : providers) {
provider.addPropagatedAction(action);
}
}
}
}
public long getTotalCost() {
return totalCost;
}
@Override
protected void handlePropagatedAction(Action.PropagatedAction action) {
// Propagate Action To Energy Providers
if (isEnergyProviderActive()) {
propagateAction(action);
} else {
action.pay(0);
}
}
@Override
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
tag.put("Networks", new IntArrayTag(networks));
return tag;
}
@Override
public void fromTag(BlockState state, CompoundTag tag) {
super.fromTag(state, tag);
int[] networksArray = tag.getIntArray("Networks");
networks.clear();
for (int network : networksArray) {
networks.add(network);
}
}
protected boolean isEnergyProviderActive() {
throw new UnsupportedOperationException();
}
protected abstract void tickEnergy();
public void toggle(int network) {
if (contains(network)) {
networks.removeAll(Collections.singletonList(network));
} else {
networks.add(network);
}
markDirty();
}
public boolean contains(int network) {
return networks.contains(network);
}
}