package com.thebrokenrail.energonrelics.energy.core; import com.thebrokenrail.energonrelics.config.HardcodedConfig; import com.thebrokenrail.energonrelics.EnergonRelics; import com.thebrokenrail.energonrelics.component.NetworkComponent; import com.thebrokenrail.energonrelics.energy.core.util.Action; import com.thebrokenrail.energonrelics.energy.core.util.EnergyProvider; import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Tickable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; public class EnergyProviderBlockEntity extends BlockEntity implements EnergyProvider, BlockEntityClientSerializable, Tickable { private final ArrayList pendingPropagatedActions = new ArrayList<>(); private static final List scheduledTicks = new ArrayList<>(); public static void tickScheduled() { Collections.shuffle(scheduledTicks); for (EnergyProviderBlockEntity provider : scheduledTicks) { provider.serverTick(); } scheduledTicks.clear(); } public EnergyProviderBlockEntity(BlockEntityType type) { super(type); } @Override public final void addPropagatedAction(Action.PropagatedAction action) { if (isEnergyProvider()) { pendingPropagatedActions.add(action); } else { throw new UnsupportedOperationException(); } } @Override public final boolean isNetwork(int network) { return isEnergyProvider() && EnergonRelics.NETWORK_CHIP_ITEM.getID(stack) == network; } @Override public final boolean isWithinDistance(Vec3d pos) { return getPos().isWithinDistance(pos, HardcodedConfig.POWER_RANGE); } private ItemStack stack = ItemStack.EMPTY; @Override public CompoundTag toTag(CompoundTag tag) { super.toTag(tag); if (isEnergyProvider()) { tag.put("NetworkChip", stack.toTag(new CompoundTag())); } return tag; } @Override public void fromTag(BlockState state, CompoundTag tag) { super.fromTag(state, tag); if (isEnergyProvider()) { stack = ItemStack.fromTag(tag.getCompound("NetworkChip")); } else { stack = ItemStack.EMPTY; } } public boolean isEnergyProvider() { return false; } protected void handlePropagatedAction(Action.PropagatedAction action) { throw new UnsupportedOperationException(); } private void tickPropagatedActions() { if (isEnergyProvider()) { for (Action.PropagatedAction action : pendingPropagatedActions) { handlePropagatedAction(action); } NetworkComponent component = NetworkComponent.getInstance((ServerWorld) Objects.requireNonNull(getWorld())); List sources = component.getSourcePos(EnergonRelics.NETWORK_CHIP_ITEM.getID(stack)); if (!sources.contains(getPos())) { takeStack(); } } pendingPropagatedActions.clear(); } protected void serverTick() { tickPropagatedActions(); } @Override public final void tick() { if (hasWorld() && !Objects.requireNonNull(getWorld()).isClient()) { scheduledTicks.add(this); } } public ItemStack takeStack() { ItemStack newStack = stack.copy(); stack = ItemStack.EMPTY; markDirty(); return newStack; } public void placeStack(ItemStack newStack) { stack = newStack.copy(); markDirty(); } public boolean hasStack() { return !stack.isEmpty(); } @Override public void fromClientTag(CompoundTag compoundTag) { fromTag(Blocks.AIR.getDefaultState(), compoundTag); } @Override public CompoundTag toClientTag(CompoundTag compoundTag) { return toTag(compoundTag); } @Override public void markDirty() { super.markDirty(); sync(); } }