150 lines
4.8 KiB
Java
150 lines
4.8 KiB
Java
package li.cil.oc2.common.blockentity;
|
|
|
|
import li.cil.oc2.api.bus.device.object.Callback;
|
|
import li.cil.oc2.api.bus.device.object.NamedDevice;
|
|
import li.cil.oc2.common.Config;
|
|
import li.cil.oc2.common.Constants;
|
|
import li.cil.oc2.common.capabilities.Capabilities;
|
|
import li.cil.oc2.common.energy.FixedEnergyStorage;
|
|
import li.cil.oc2.common.util.ChunkUtils;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntitySelector;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.phys.AABB;
|
|
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
|
import net.minecraftforge.energy.IEnergyStorage;
|
|
import net.minecraftforge.items.IItemHandler;
|
|
|
|
import javax.annotation.Nullable;
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
import java.util.function.Predicate;
|
|
|
|
import static java.util.Collections.singletonList;
|
|
|
|
public final class ChargerBlockEntity extends ModBlockEntity implements NamedDevice {
|
|
private static final Predicate<Entity> ENTITY_PREDICATE =
|
|
EntitySelector.NO_SPECTATORS
|
|
.and(EntitySelector.ENTITY_STILL_ALIVE);
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
private final FixedEnergyStorage energy = new FixedEnergyStorage(Config.chargerEnergyStorage);
|
|
private boolean isCharging;
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
ChargerBlockEntity(final BlockPos pos, final BlockState state) {
|
|
super(BlockEntities.CHARGER.get(), pos, state);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
public static void tick(final Level ignoredLevel, final BlockPos ignoredPos, final BlockState ignoredState, final ChargerBlockEntity charger) {
|
|
charger.tick();
|
|
}
|
|
|
|
private void tick() {
|
|
if (level == null) {
|
|
return;
|
|
}
|
|
|
|
isCharging = false;
|
|
chargeBlock();
|
|
chargeEntities();
|
|
|
|
if (isCharging) {
|
|
ChunkUtils.setLazyUnsaved(level, getBlockPos());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void saveAdditional(final CompoundTag tag) {
|
|
super.saveAdditional(tag);
|
|
|
|
tag.put(Constants.ENERGY_TAG_NAME, energy.serializeNBT());
|
|
}
|
|
|
|
@Override
|
|
public void load(final CompoundTag tag) {
|
|
super.load(tag);
|
|
|
|
energy.deserializeNBT(tag.getCompound(Constants.ENERGY_TAG_NAME));
|
|
}
|
|
|
|
@Callback
|
|
public boolean isCharging() {
|
|
return isCharging;
|
|
}
|
|
|
|
@Override
|
|
public Collection<String> getDeviceTypeNames() {
|
|
return singletonList("charger");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
@Override
|
|
protected void collectCapabilities(final CapabilityCollector collector, @Nullable final Direction direction) {
|
|
collector.offer(Capabilities.ENERGY_STORAGE, energy);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
private void chargeBlock() {
|
|
assert level != null;
|
|
|
|
if (energy.getEnergyStored() == 0) {
|
|
return;
|
|
}
|
|
|
|
final BlockEntity blockEntity = level.getBlockEntity(getBlockPos().above());
|
|
if (blockEntity != null) {
|
|
chargeCapabilityProvider(blockEntity);
|
|
}
|
|
}
|
|
|
|
private void chargeEntities() {
|
|
assert level != null;
|
|
|
|
if (energy.getEnergyStored() == 0) {
|
|
return;
|
|
}
|
|
|
|
final List<Entity> entities = level.getEntities((Entity) null, new AABB(getBlockPos().above()), ENTITY_PREDICATE);
|
|
for (final Entity entity : entities) {
|
|
chargeCapabilityProvider(entity);
|
|
}
|
|
}
|
|
|
|
private void chargeCapabilityProvider(final ICapabilityProvider capabilityProvider) {
|
|
capabilityProvider.getCapability(Capabilities.ENERGY_STORAGE, Direction.DOWN).ifPresent(this::charge);
|
|
capabilityProvider.getCapability(Capabilities.ITEM_HANDLER, Direction.DOWN).ifPresent(this::chargeItems);
|
|
}
|
|
|
|
private void chargeItems(final IItemHandler itemHandler) {
|
|
for (int slot = 0; slot < itemHandler.getSlots(); slot++) {
|
|
final ItemStack stack = itemHandler.getStackInSlot(slot);
|
|
if (!stack.isEmpty()) {
|
|
stack.getCapability(Capabilities.ENERGY_STORAGE).ifPresent(this::charge);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void charge(final IEnergyStorage energyStorage) {
|
|
assert level != null;
|
|
|
|
final int amount = Math.min(energy.getEnergyStored(), Config.chargerEnergyPerTick);
|
|
final boolean simulate = level.isClientSide;
|
|
if (energy.extractEnergy(energyStorage.receiveEnergy(amount, simulate), simulate) > 0) {
|
|
isCharging = true;
|
|
}
|
|
}
|
|
}
|