Update Battery Bank code

This commit is contained in:
DBotThePony 2022-01-03 16:34:42 +07:00
parent 9001147627
commit d1ea084516
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 339 additions and 362 deletions

View File

@ -1,101 +1,103 @@
package ru.dbotthepony.mc.otm.block; package ru.dbotthepony.mc.otm.block
import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.MethodsReturnNonnullByDefault
import net.minecraft.core.BlockPos; import javax.annotation.ParametersAreNonnullByDefault
import net.minecraft.core.Direction; import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.properties.BooleanProperty
import net.minecraft.world.level.block.EntityBlock; import ru.dbotthepony.mc.otm.block.BlockBatteryBank
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.core.Direction
import net.minecraft.world.phys.shapes.BooleanOp; import ru.dbotthepony.mc.otm.block.entity.BlockEntityBatteryBank
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.level.BlockGetter
import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.level.Level
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.level.block.Block
import ru.dbotthepony.mc.otm.Registry; import net.minecraft.world.phys.shapes.CollisionContext
import ru.dbotthepony.mc.otm.block.entity.BlockEntityBatteryBank; import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.shapes.BlockShapes; import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.shapes.BlockShapes
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public class BlockBatteryBank extends BlockMatteryRotatable implements EntityBlock { class BlockBatteryBank : BlockMatteryRotatable(), EntityBlock {
public static final BooleanProperty[] BATTERY_SLOTS_PROPS = new BooleanProperty[] { override fun getStateForPlacement(context: BlockPlaceContext): BlockState {
BooleanProperty.create("battery_0"), var state = super.getStateForPlacement(context)!!
BooleanProperty.create("battery_1"),
BooleanProperty.create("battery_2"),
BooleanProperty.create("battery_3"),
BooleanProperty.create("battery_4"),
BooleanProperty.create("battery_5"),
BooleanProperty.create("battery_6"),
BooleanProperty.create("battery_7"),
BooleanProperty.create("battery_8"),
BooleanProperty.create("battery_9"),
BooleanProperty.create("battery_10"),
BooleanProperty.create("battery_11"),
};
@Nullable for (prop in BATTERY_SLOTS_PROPS)
@Override state = state.setValue(prop, false)
public BlockState getStateForPlacement(BlockPlaceContext context) {
var state = super.getStateForPlacement(context);
for (var prop : BATTERY_SLOTS_PROPS) return state
state = state.setValue(prop, false);
return state;
} }
@Nullable override fun <T : BlockEntity?> getTicker(
@Override level: Level,
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState p_153213_, BlockEntityType<T> type) { p_153213_: BlockState,
return level.isClientSide || type != Registry.BlockEntities.BATTERY_BANK ? null : BlockEntityBatteryBank::tick; type: BlockEntityType<T>
): BlockEntityTicker<T>? {
if (level.isClientSide || type !== Registry.BlockEntities.BATTERY_BANK)
return null
return BlockEntityTicker { _, _, _, tile -> if (tile is BlockEntityBatteryBank) tile.tick() }
} }
@Override override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) { builder.add(*BATTERY_SLOTS_PROPS)
builder.add(BATTERY_SLOTS_PROPS); super.createBlockStateDefinition(builder)
super.createBlockStateDefinition(builder);
} }
@Nullable override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity? {
@Override return BlockEntityBatteryBank(blockPos, blockState)
public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new BlockEntityBatteryBank(blockPos, blockState);
} }
private static final List<VoxelShape> SHAPES; override fun getShape(
p_60555_: BlockState,
static { p_60556_: BlockGetter,
var def = BlockShapes.BATTERY_BANK.computeShape(); p_60557_: BlockPos,
p_60558_: CollisionContext
SHAPES = List.of( ): VoxelShape {
def, return SHAPES[p_60555_.getValue(FACING).ordinal]
def,
def,
BlockShapes.BATTERY_BANK.rotate(Direction.NORTH).computeShape(),
BlockShapes.BATTERY_BANK.rotate(Direction.WEST).computeShape(),
BlockShapes.BATTERY_BANK.rotate(Direction.EAST).computeShape()
);
} }
@Override override fun faceToPlayer(context: BlockPlaceContext): Boolean {
@SuppressWarnings("deprecation") return false
public VoxelShape getShape(BlockState p_60555_, BlockGetter p_60556_, BlockPos p_60557_, CollisionContext p_60558_) {
return SHAPES.get(p_60555_.getValue(FACING).ordinal());
} }
@Override companion object {
public boolean faceToPlayer(BlockPlaceContext context) { @JvmField
return false; val BATTERY_SLOTS_PROPS = arrayOf(
BooleanProperty.create("battery_0"),
BooleanProperty.create("battery_1"),
BooleanProperty.create("battery_2"),
BooleanProperty.create("battery_3"),
BooleanProperty.create("battery_4"),
BooleanProperty.create("battery_5"),
BooleanProperty.create("battery_6"),
BooleanProperty.create("battery_7"),
BooleanProperty.create("battery_8"),
BooleanProperty.create("battery_9"),
BooleanProperty.create("battery_10"),
BooleanProperty.create("battery_11")
)
private val SHAPES: List<VoxelShape>
init {
val def = BlockShapes.BATTERY_BANK.computeShape()
SHAPES = java.util.List.of(
def,
def,
def,
BlockShapes.BATTERY_BANK.rotate(Direction.NORTH).computeShape(),
BlockShapes.BATTERY_BANK.rotate(Direction.WEST).computeShape(),
BlockShapes.BATTERY_BANK.rotate(Direction.EAST).computeShape()
)
}
} }
} }

View File

@ -1,167 +1,165 @@
package ru.dbotthepony.mc.otm.block.entity; package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.MethodsReturnNonnullByDefault
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos
import net.minecraft.core.Direction; import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.CapabilityEnergy
import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.energy.IEnergyStorage
import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.items.CapabilityItemHandler
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler
import net.minecraftforge.items.IItemHandler; import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.Registry; import ru.dbotthepony.mc.otm.block.BlockBatteryBank
import ru.dbotthepony.mc.otm.block.BlockBatteryBank; import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable
import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable; import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage; import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.capability.extractEnergy
import ru.dbotthepony.mc.otm.container.MatteryContainer; import ru.dbotthepony.mc.otm.capability.receiveEnergy
import ru.dbotthepony.mc.otm.core.Fraction; import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.menu.BatteryBankMenu; import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.ifHas
import javax.annotation.Nonnull; import ru.dbotthepony.mc.otm.menu.BatteryBankMenu
import javax.annotation.Nullable; import ru.dbotthepony.mc.otm.set
import javax.annotation.ParametersAreNonnullByDefault; import ru.dbotthepony.mc.otm.unaryMinus
import java.math.BigDecimal; import javax.annotation.ParametersAreNonnullByDefault
import java.util.Optional;
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
public class BlockEntityBatteryBank extends BlockEntityMattery { class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMattery(Registry.BlockEntities.BATTERY_BANK, p_155229_, p_155230_) {
// 6 на 2 // 6 на 2
public final MatteryContainer battery_container = new MatteryContainer(this::setChanged, 6 * 2) { val container: MatteryContainer = object : MatteryContainer(this::setChanged, 6 * 2) {
@Override override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
public void setChanged(int slot, ItemStack new_state, ItemStack old_state) { super.setChanged(slot, new_state, old_state)
super.setChanged(slot, new_state, old_state);
val level = level
if (level != null) { if (level != null) {
var state = getBlockState(); var state = blockState
for (int i = 0; i < BlockBatteryBank.BATTERY_SLOTS_PROPS.length; i++) { for (i in BlockBatteryBank.BATTERY_SLOTS_PROPS.indices) {
state = state.setValue(BlockBatteryBank.BATTERY_SLOTS_PROPS[i], getItem(i).getCapability(CapabilityEnergy.ENERGY).isPresent()); state = state.setValue(BlockBatteryBank.BATTERY_SLOTS_PROPS[i], getItem(i).getCapability(CapabilityEnergy.ENERGY).isPresent)
} }
if (state != getBlockState()) { if (state !== blockState) {
level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS); level.setBlock(blockPos, state, Block.UPDATE_CLIENTS)
} }
} }
} }
};
private final LazyOptional<IItemHandler> item_handler_resolver = LazyOptional.of(() -> battery_container.handler(
(slot, stack) -> stack.getCapability(CapabilityEnergy.ENERGY).isPresent(),
(slot, amount, stack) -> true
));
public record BatteryBankDistribution(Fraction[] distribution, Fraction max_throughput) {
} }
public class BatteryBankEnergy implements IMatteryEnergyStorage { private val itemHandler = container.handler(
private final BankMode mode; { slot: Int, stack: ItemStack -> stack.getCapability(CapabilityEnergy.ENERGY).isPresent },
{ slot: Int, amount: Int, stack: ItemStack? -> true }
)
public BatteryBankEnergy(BankMode mode) { private data class BatteryBankDistribution(val distribution: Array<Fraction>, val maxThroughput: Fraction)
this.mode = mode; private enum class BankMode { RECEIVE, EXTRACT, BIDIRECTIONAL }
}
public enum BankMode { private inner class BatteryBankEnergy(private val mode: BankMode) : IMatteryEnergyStorage {
RECEIVE, override fun canExtract() = mode != BankMode.RECEIVE
EXTRACT, override fun canReceive() = mode != BankMode.EXTRACT
BIDIRECTIONAL
}
@Override override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
public boolean canExtract() {
return mode == BankMode.EXTRACT || mode == BankMode.BIDIRECTIONAL;
}
@Override
public boolean canReceive() {
return mode == BankMode.RECEIVE || mode == BankMode.BIDIRECTIONAL;
}
@Nonnull
@Override
public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) {
if (mode == BankMode.RECEIVE) if (mode == BankMode.RECEIVE)
return Fraction.ZERO; return Fraction.ZERO
return extractEnergyInner(howMuch, simulate); return extractEnergyInner(howMuch, simulate)
} }
BatteryBankDistribution getDistribution(boolean mode) { /**
Fraction[] distribution = new Fraction[battery_container.getContainerSize()]; * [mode] = true на приём, false на отдачу
Fraction summ = Fraction.ZERO; */
fun getDistribution(mode: Boolean): BatteryBankDistribution {
val distribution = Array(container.containerSize) { Fraction.ZERO }
var summ = Fraction.ZERO
for (int i = 0; i < battery_container.getContainerSize(); i++) { for (i in 0 until container.containerSize) {
ItemStack stack = battery_container.getItem(i); val stack = container.getItem(i)
if (!stack.isEmpty()) { if (!stack.isEmpty) {
Optional<IMatteryEnergyStorage> cap = stack.getCapability(MatteryCapability.ENERGY).resolve(); stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
val diff: Fraction
if (cap.isPresent()) { if (mode) {
Fraction diff = mode ? cap.get().receiveEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true) : cap.get().extractEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true); diff = it.receiveEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true)
distribution[i] = diff; } else {
summ = summ.plus(diff); diff = it.extractEnergyOuter(MatteryCapability.LONG_MAX_VALUE, true)
} else { }
Optional<IEnergyStorage> cap2 = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (cap2.isPresent()) { distribution[i] = diff
Fraction diff = new Fraction(mode ? cap2.get().receiveEnergy(Integer.MAX_VALUE, true) : cap2.get().extractEnergy(Integer.MAX_VALUE, true)); summ += diff
distribution[i] = diff; } else {
summ = summ.plus(diff); val diff: Int
if (mode) {
diff = it.receiveEnergy(MatteryCapability.LONG_MAX_VALUE, true)
} else {
diff = it.extractEnergy(MatteryCapability.LONG_MAX_VALUE, true)
}
distribution[i] = Fraction(diff)
summ += distribution[i]
} }
} }
} else {
distribution[i] = Fraction.ZERO;
} }
} }
if (summ.compareTo(Fraction.ZERO) != 0) { if (!summ.isZero()) {
for (int i = 0; i < battery_container.getContainerSize(); i++) { for (i in 0 until container.containerSize) {
distribution[i] = distribution[i].div(summ); distribution[i] = distribution[i] / summ
} }
} }
return new BatteryBankDistribution(distribution, summ); return BatteryBankDistribution(distribution, summ)
} }
private Fraction distributeEnergy(boolean mode, Fraction howMuch, boolean simulate) { private fun distributeEnergy(mode: Boolean, howMuch: Fraction, simulate: Boolean): Fraction {
BatteryBankDistribution distribution = getDistribution(mode); val distribution = getDistribution(mode)
if (distribution.max_throughput.compareTo(Fraction.ZERO) == 0) if (distribution.maxThroughput.isZero())
return Fraction.ZERO; return Fraction.ZERO
Fraction[] distList = distribution.distribution; val distList: Array<Fraction> = distribution.distribution
Fraction summ = Fraction.ZERO; var summ = Fraction.ZERO
for (int i = 0; i < battery_container.getContainerSize(); i++) { for (i in 0 until container.containerSize) {
if (!distList[i].equals(Fraction.ZERO)) { if (!distList[i].isZero()) {
ItemStack stack = battery_container.getItem(i); val stack = container.getItem(i)
if (!stack.isEmpty()) { if (!stack.isEmpty) {
Optional<IMatteryEnergyStorage> cap = stack.getCapability(MatteryCapability.ENERGY).resolve(); stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
val diff: Fraction
if (cap.isPresent()) { if (mode) {
Fraction diff = mode ? cap.get().receiveEnergyOuter(howMuch.times(distList[i]), simulate) : cap.get().extractEnergyOuter(howMuch.times(distList[i]), simulate); diff = it.receiveEnergyOuter(howMuch * distList[i], simulate)
summ = summ.plus(diff); } else {
} else { diff = it.extractEnergyOuter(howMuch * distList[i], simulate)
Optional<IEnergyStorage> cap2 = stack.getCapability(CapabilityEnergy.ENERGY).resolve(); }
if (cap2.isPresent()) { summ += diff
Fraction diff = mode ? MatteryCapability.floodFE(cap2.get(), howMuch.times(distList[i]), simulate) : MatteryCapability.drainFE(cap2.get(), howMuch.times(distList[i]), simulate); } else {
summ = summ.plus(diff); val diff: Int
if (mode) {
diff = it.receiveEnergy(howMuch * distList[i], simulate)
} else {
diff = it.extractEnergy(howMuch * distList[i], simulate)
}
summ += Fraction(diff)
} }
} }
} }
@ -169,214 +167,191 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
} }
if (!simulate && !summ.isZero()) { if (!simulate && !summ.isZero()) {
setChangedLight(); setChangedLight()
} }
return summ; return summ
} }
@Nonnull override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
@Override return distributeEnergy(false, howMuch, simulate)
public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) {
return distributeEnergy(false, howMuch, simulate);
} }
@Nonnull override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
@Override
public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) {
if (mode == BankMode.EXTRACT) if (mode == BankMode.EXTRACT)
return Fraction.ZERO; return Fraction.ZERO
return receiveEnergyInner(howMuch, simulate); return receiveEnergyInner(howMuch, simulate)
} }
@Nonnull override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
@Override return distributeEnergy(true, howMuch, simulate)
public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) {
return distributeEnergy(true, howMuch, simulate);
} }
@Nonnull override fun getBatteryLevel(): Fraction {
@Override var result = Fraction.ZERO
public Fraction getBatteryLevel() {
Fraction result = Fraction.ZERO;
for (int i = 0; i < battery_container.getContainerSize(); i++) { for (i in 0 until container.containerSize) {
ItemStack stack = battery_container.getItem(i); val stack = container.getItem(i)
if (!stack.isEmpty()) { if (!stack.isEmpty) {
Optional<IMatteryEnergyStorage> cap = stack.getCapability(MatteryCapability.ENERGY).resolve(); stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
if (cap.isPresent()) { result += it.batteryLevel
result = result.plus(cap.get().getBatteryLevel()); } else {
} else { result += it.energyStored
Optional<IEnergyStorage> cap2 = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (cap2.isPresent()) {
result = result.plus(cap2.get().getEnergyStored());
} }
} }
} }
} }
return result; return result
} }
@Nonnull override fun getMaxBatteryLevel(): Fraction {
@Override var result = Fraction.ZERO
public Fraction getMaxBatteryLevel() {
Fraction result = Fraction.ZERO;
for (int i = 0; i < battery_container.getContainerSize(); i++) { for (i in 0 until container.containerSize) {
ItemStack stack = battery_container.getItem(i); val stack = container.getItem(i)
if (!stack.isEmpty()) { if (!stack.isEmpty) {
Optional<IMatteryEnergyStorage> cap = stack.getCapability(MatteryCapability.ENERGY).resolve(); stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
if (cap.isPresent()) { result += it.maxBatteryLevel
result = result.plus(cap.get().getMaxBatteryLevel()); } else {
} else { result += it.maxEnergyStored
Optional<IEnergyStorage> cap2 = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (cap2.isPresent()) {
result = result.plus(cap2.get().getMaxEnergyStored());
} }
} }
} }
} }
return result; return result
} }
} }
public final BatteryBankEnergy energy_receiver = new BatteryBankEnergy(BatteryBankEnergy.BankMode.RECEIVE); private val energyReceiver = BatteryBankEnergy(BankMode.RECEIVE)
private LazyOptional<BatteryBankEnergy> energy_receiver_resolver = LazyOptional.of(() -> energy_receiver); private var resolverEnergyReceive = LazyOptional.of { energyReceiver }
private val energyExtractor = BatteryBankEnergy(BankMode.EXTRACT)
private var resolverEnergyExtractor = LazyOptional.of { energyExtractor }
private val energy = BatteryBankEnergy(BankMode.BIDIRECTIONAL)
private var resolverEnergy = LazyOptional.of { energy }
private var resolverItemHandler = LazyOptional.of { itemHandler }
public final BatteryBankEnergy energy_extractor = new BatteryBankEnergy(BatteryBankEnergy.BankMode.EXTRACT); private var valid = true
private LazyOptional<BatteryBankEnergy> energy_extractor_resolver = LazyOptional.of(() -> energy_extractor);
public final BatteryBankEnergy energy = new BatteryBankEnergy(BatteryBankEnergy.BankMode.BIDIRECTIONAL); override fun saveAdditional(nbt: CompoundTag) {
private LazyOptional<BatteryBankEnergy> energy_resolver = LazyOptional.of(() -> energy); super.saveAdditional(nbt)
nbt["battery_bank"] = container.serializeNBT()
protected boolean valid = true;
public BlockEntityBatteryBank(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.BATTERY_BANK, p_155229_, p_155230_);
} }
@Override override fun load(nbt: CompoundTag) {
public void saveAdditional(CompoundTag nbt) { nbt.ifHas("battery_bank") {
super.saveAdditional(nbt); container.deserializeNBT(it)
nbt.put("battery_bank", battery_container.serializeNBT());
}
@Override
public void load(CompoundTag nbt) {
battery_container.deserializeNBT(nbt.get("battery_bank"));
super.load(nbt);
}
private final TranslatableComponent MACHINE_NAME = new TranslatableComponent("block.overdrive_that_matters.battery_bank");
@Override
protected Component getDefaultDisplayName() {
return MACHINE_NAME;
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) {
return new BatteryBankMenu(containerID, inventory, this, this.battery_container);
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
energy_receiver_resolver.invalidate();
energy_extractor_resolver.invalidate();
energy_resolver.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
energy_receiver_resolver = LazyOptional.of(() -> energy_receiver);
energy_extractor_resolver = LazyOptional.of(() -> energy_extractor);
energy_resolver = LazyOptional.of(() -> energy);
}
@Override
public void setLevel(Level p_155231_) {
super.setLevel(p_155231_);
tickOnceServer(this::checkSurroundings);
}
@Nonnull
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (valid && (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY)) {
if (side == null)
return energy_resolver.cast();
if (side == getBlockState().getValue(BlockMatteryRotatable.FACING))
return energy_extractor_resolver.cast();
return energy_receiver_resolver.cast();
} }
if (valid && cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) super.load(nbt)
return item_handler_resolver.cast();
return super.getCapability(cap, side);
} }
protected LazyOptional<IMatteryEnergyStorage> output_cap_mte = LazyOptional.empty(); companion object {
protected LazyOptional<IEnergyStorage> output_cap_fe = LazyOptional.empty(); private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.battery_bank")
protected void _checkSurroundings() {
if (level instanceof ServerLevel level)
checkSurroundings(level);
} }
public void checkSurroundings(Level level) { override fun getDefaultDisplayName(): Component {
if (isRemoved()) return MACHINE_NAME
return; }
final var get_entity = level.getBlockEntity(getBlockPos().offset(getBlockState().getValue(BlockMatteryRotatable.FACING).getNormal())); override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
return BatteryBankMenu(containerID, inventory, this, container)
}
if (get_entity == null) { override fun invalidateCaps() {
output_cap_mte = LazyOptional.empty(); super.invalidateCaps()
output_cap_fe = LazyOptional.empty(); valid = false
return; resolverEnergyReceive.invalidate()
resolverEnergyExtractor.invalidate()
resolverEnergy.invalidate()
resolverItemHandler.invalidate()
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolverEnergyReceive = LazyOptional.of { energyReceiver }
resolverEnergyExtractor = LazyOptional.of { energyExtractor }
resolverEnergy = LazyOptional.of { energy }
resolverItemHandler = LazyOptional.of { itemHandler }
}
override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_)
tickOnceServer { level: Level -> checkSurroundings(level) }
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap === MatteryCapability.ENERGY || cap === CapabilityEnergy.ENERGY) {
if (side == null) return resolverEnergy.cast()
if (side == blockState.getValue(BlockMatteryRotatable.FACING))
return resolverEnergyExtractor.cast()
else
return resolverEnergyReceive.cast()
}
if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return resolverItemHandler.cast()
}
} }
output_cap_mte = getAndBind(output_cap_mte, get_entity, MatteryCapability.ENERGY, getBlockState().getValue(BlockMatteryRotatable.FACING).getOpposite(), this::_checkSurroundings); return super.getCapability(cap,side)
output_cap_fe = getAndBind(output_cap_fe, get_entity, CapabilityEnergy.ENERGY, getBlockState().getValue(BlockMatteryRotatable.FACING).getOpposite(), this::_checkSurroundings);
} }
public static <T extends BlockEntity> void tick(Level level, BlockPos blockPos, BlockState blockState, T t) { private var outputCapability = LazyOptional.empty<IEnergyStorage>()
if (t instanceof BlockEntityBatteryBank tile) {
if (tile.isBlockedByRedstone())
return;
if (tile.output_cap_mte.isPresent()) { fun checkSurroundings(level: Level) {
final var cap = tile.output_cap_mte.resolve().get(); if (isRemoved) return
if (cap.canReceive()) { val tile = level.getBlockEntity(blockPos.offset(blockState.getValue(BlockMatteryRotatable.FACING).normal))
BatteryBankDistribution distribution = tile.energy.getDistribution(false);
Fraction diff = cap.receiveEnergyOuter(distribution.max_throughput, true); if (tile == null) {
diff = tile.energy.extractEnergyOuter(diff, false); outputCapability = LazyOptional.empty()
cap.receiveEnergyOuter(diff, false); return
}
outputCapability = getAndBind(
outputCapability,
tile,
CapabilityEnergy.ENERGY,
-blockState.getValue(BlockMatteryRotatable.FACING)
) {
val level = this.level
if (level is ServerLevel)
checkSurroundings(level)
}
}
fun tick() {
if (isBlockedByRedstone)
return
outputCapability.ifPresent {
val (_, maxThroughput) = energy.getDistribution(false)
if (maxThroughput.isZero())
return@ifPresent
if (it is IMatteryEnergyStorage) {
val diff = it.receiveEnergyOuter(maxThroughput, false)
if (!diff.isZero()) {
energy.extractEnergyInner(diff, false)
} }
} else if (tile.output_cap_fe.isPresent()) { } else {
final var cap = tile.output_cap_fe.resolve().get(); val diff = it.receiveEnergy(maxThroughput, false)
if (cap.canReceive()) { if (diff != 0) {
BatteryBankDistribution distribution = tile.energy.getDistribution(false); energy.extractEnergyInner(diff, false)
Fraction diff = MatteryCapability.floodFE(cap, distribution.max_throughput, true);
diff = tile.energy.extractEnergyOuter(diff, false);
MatteryCapability.floodFE(cap, diff, false);
} }
} }
} }