Fix old capabilities pointers being valid after invalidating them

This commit is contained in:
DBotThePony 2021-09-12 17:45:04 +07:00
parent e6b7308c3b
commit 44bb2c6c93
Signed by: DBot
GPG Key ID: DCC23B5715498507
19 changed files with 286 additions and 111 deletions

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
@ -36,6 +37,8 @@ import ru.dbotthepony.mc.otm.network.MatteryNetworking;
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@ -46,6 +49,8 @@ import java.util.stream.Collectors;
// The value here should match an entry in the META-INF/mods.toml file
@Mod(OverdriveThatMatters.MOD_ID)
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class OverdriveThatMatters {
// Directly reference a log4j logger.
public static final String MOD_ID = "overdrive_that_matters";

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.world.Container;
import net.minecraft.world.Containers;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
@ -47,7 +46,7 @@ public class BlockCargoCrate extends BlockMatteryRotatable implements EntityBloc
BlockEntity blockentity = level.getBlockEntity(block_pos);
if (blockentity instanceof BlockEntityCargoCrate crate) {
Containers.dropContents(level, block_pos, crate.slots);
Containers.dropContents(level, block_pos, crate.container);
level.updateNeighbourForOutputSignal(block_pos, this);
}

View File

@ -53,29 +53,29 @@ public class BlockEntityAndroidStation extends BlockEntityMatteryPowered impleme
if (tile.isBlockedByRedstone())
return;
BlockPos pos = tile.getBlockPos();
final var pos = tile.getBlockPos();
List<LivingEntity> entities = tile.getLevel().getEntitiesOfClass(LivingEntity.class, new AABB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 2, pos.getZ() + 1));
for (LivingEntity ent : entities) {
Optional<IAndroidCapability> resolver = ent.getCapability(MatteryCapability.ANDROID).resolve();
final var resolver = ent.getCapability(MatteryCapability.ANDROID).resolve();
if (resolver.isEmpty())
continue;
IAndroidCapability capability = resolver.get();
final var capability = resolver.get();
if (!capability.isAndroid())
continue;
BigDecimal missing = capability.getMissingPower();
final var missing = capability.getMissingPower();
if (missing.compareTo(BigDecimal.ZERO) == 1) {
BigDecimal extract = tile.energy.extractEnergyInner(missing, true);
if (missing.compareTo(BigDecimal.ZERO) > 0) {
final var extract = tile.energy.extractEnergyInner(missing, true);
if (extract.compareTo(BigDecimal.ZERO) == 1) {
BigDecimal received = capability.receiveEnergyOuter(extract, true);
if (extract.compareTo(BigDecimal.ZERO) > 0) {
final var received = capability.receiveEnergyOuter(extract, true);
if (received.compareTo(BigDecimal.ZERO) == 1) {
if (received.compareTo(BigDecimal.ZERO) > 0) {
tile.energy.extractEnergyInner(extract, false);
capability.receiveEnergyOuter(extract, false);
}

View File

@ -6,6 +6,7 @@ import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
@ -66,21 +67,13 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
}
public static class BatteryBankEnergy implements IMatteryEnergyStorage {
public record BatteryBankEnergy(BlockEntityBatteryBank tile, BankMode mode) implements IMatteryEnergyStorage {
public enum BankMode {
RECEIVE,
EXTRACT,
BIDIRECTIONAL
}
private final BlockEntityBatteryBank tile;
private final BankMode mode;
BatteryBankEnergy(BlockEntityBatteryBank tile, BankMode mode) {
this.tile = tile;
this.mode = mode;
}
@Override
public boolean canExtract() {
return mode == BankMode.EXTRACT || mode == BankMode.BIDIRECTIONAL;
@ -246,13 +239,13 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
}
public final BatteryBankEnergy energy_receiver = new BatteryBankEnergy(this, BatteryBankEnergy.BankMode.RECEIVE);
public final LazyOptional<BatteryBankEnergy> energy_receiver_resolver = LazyOptional.of(() -> energy_receiver);
private LazyOptional<BatteryBankEnergy> energy_receiver_resolver = LazyOptional.of(() -> energy_receiver);
public final BatteryBankEnergy energy_extractor = new BatteryBankEnergy(this, BatteryBankEnergy.BankMode.EXTRACT);
public final LazyOptional<BatteryBankEnergy> energy_extractor_resolver = LazyOptional.of(() -> energy_extractor);
private LazyOptional<BatteryBankEnergy> energy_extractor_resolver = LazyOptional.of(() -> energy_extractor);
public final BatteryBankEnergy energy = new BatteryBankEnergy(this, BatteryBankEnergy.BankMode.BIDIRECTIONAL);
public final LazyOptional<BatteryBankEnergy> energy_resolver = LazyOptional.of(() -> energy);
private LazyOptional<BatteryBankEnergy> energy_resolver = LazyOptional.of(() -> energy);
protected boolean valid = true;
@ -289,12 +282,24 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
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
@ -315,34 +320,52 @@ public class BlockEntityBatteryBank extends BlockEntityMattery {
return super.getCapability(cap, side);
}
protected LazyOptional<IMatteryEnergyStorage> output_cap_mte = LazyOptional.empty();
protected LazyOptional<IEnergyStorage> output_cap_fe = LazyOptional.empty();
protected void _checkSurroundings() {
if (level instanceof ServerLevel level)
checkSurroundings(level);
}
public void checkSurroundings(Level level) {
if (isRemoved())
return;
final var get_entity = level.getBlockEntity(getBlockPos().offset(getBlockState().getValue(BlockMatteryRotatable.FACING).getNormal()));
if (get_entity == null) {
output_cap_mte = LazyOptional.empty();
output_cap_fe = LazyOptional.empty();
return;
}
output_cap_mte = getAndBind(output_cap_mte, get_entity, MatteryCapability.ENERGY, getBlockState().getValue(BlockMatteryRotatable.FACING).getOpposite(), this::_checkSurroundings);
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) {
if (t instanceof BlockEntityBatteryBank tile) {
if (tile.isBlockedByRedstone())
return;
BlockEntity get_entity = level.getBlockEntity(blockPos.offset(tile.getBlockState().getValue(BlockMatteryRotatable.FACING).getNormal()));
if (tile.output_cap_mte.isPresent()) {
final var cap = tile.output_cap_mte.resolve().get();
if (get_entity != null) {
Optional<IMatteryEnergyStorage> cap = get_entity.getCapability(MatteryCapability.ENERGY, tile.getBlockState().getValue(BlockMatteryRotatable.FACING).getOpposite()).resolve();
if (cap.isPresent()) {
if (cap.get().canReceive()) {
if (cap.canReceive()) {
BatteryBankDistribution distribution = tile.energy.getDistribution(false);
BigDecimal diff = cap.get().receiveEnergyOuter(distribution.max_throughput, true);
BigDecimal diff = cap.receiveEnergyOuter(distribution.max_throughput, true);
diff = tile.energy.extractEnergyOuter(diff, false);
cap.get().receiveEnergyOuter(diff, false);
cap.receiveEnergyOuter(diff, false);
}
} else {
Optional<IEnergyStorage> cap2 = get_entity.getCapability(CapabilityEnergy.ENERGY, tile.getBlockState().getValue(BlockMatteryRotatable.FACING).getOpposite()).resolve();
} else if (tile.output_cap_fe.isPresent()) {
final var cap = tile.output_cap_fe.resolve().get();
if (cap2.isPresent()) {
if (cap2.get().canReceive()) {
if (cap.canReceive()) {
BatteryBankDistribution distribution = tile.energy.getDistribution(false);
BigDecimal diff = MatteryCapability.floodFE(cap2.get(), distribution.max_throughput, true);
BigDecimal diff = MatteryCapability.floodFE(cap, distribution.max_throughput, true);
diff = tile.energy.extractEnergyOuter(diff, false);
MatteryCapability.floodFE(cap2.get(), diff, false);
}
}
MatteryCapability.floodFE(cap, diff, false);
}
}
}

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.block.entity;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
@ -9,13 +10,17 @@ import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.BlockCargoCrate;
import ru.dbotthepony.mc.otm.container.MatteryContainer;
import ru.dbotthepony.mc.otm.container.MatteryContainerHandler;
import ru.dbotthepony.mc.otm.menu.CargoCrateMenu;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
@ -37,22 +42,44 @@ public class BlockEntityCargoCrate extends BlockEntityMattery {
}
}
public final MatteryContainer slots = new MatteryContainer(this::setChanged, 9 * 6);
public final MatteryContainer container = new MatteryContainer(this::setChanged, 9 * 6);
public final MatteryContainerHandler item_handler = container.handler();
public BlockEntityCargoCrate(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.CARGO_CRATE, p_155229_, p_155230_);
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
item_handler.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
item_handler.revive();
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return item_handler.get().cast();
return super.getCapability(cap, side);
}
@Override
public CompoundTag save(CompoundTag nbt) {
nbt.put("slots", slots.serializeNBT());
nbt.put("slots", container.serializeNBT());
return super.save(nbt);
}
@Override
public void load(CompoundTag nbt) {
super.load(nbt);
slots.deserializeNBT(nbt.get("slots"));
container.deserializeNBT(nbt.get("slots"));
}
@Override

View File

@ -25,6 +25,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerCapability;
import ru.dbotthepony.mc.otm.container.MatteryContainer;
import ru.dbotthepony.mc.otm.container.MatteryContainerHandler;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu;
@ -71,22 +72,7 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
}
};
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.BIDIRECTIONAL, new BigDecimal(4)) {
@Nonnull
@Override
public MatterDirection getDirection() {
return work_flow ? MatterDirection.RECEIVE : MatterDirection.EXTRACT;
}
};
private static final BigDecimal MATTER_EXCHANGE_RATE = new BigDecimal("0.04");
private static final BigDecimal ENERGY_CONSUMPTION = new BigDecimal(20);
private final LazyOptional<MatterHandlerCapability> matter_resolver = LazyOptional.of(() -> matter);
private final LazyOptional<IMatterGridCell> cell_resolver = LazyOptional.of(() -> this);
private final LazyOptional<IItemHandler> handler_resolver = LazyOptional.of(() -> {
return work_slots.handler((slot, stack) -> {
public final MatteryContainerHandler work_slots_handler = work_slots.handler((slot, stack) -> {
if (work_flow) {
return slot < 3 && stack.getCapability(MatteryCapability.MATTER).isPresent();
}
@ -99,7 +85,19 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
return slot < 3;
});
});
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.BIDIRECTIONAL, new BigDecimal(4)) {
@Nonnull
@Override
public MatterDirection getDirection() {
return work_flow ? MatterDirection.RECEIVE : MatterDirection.EXTRACT;
}
};
private static final BigDecimal MATTER_EXCHANGE_RATE = new BigDecimal("0.04");
private static final BigDecimal ENERGY_CONSUMPTION = new BigDecimal(20);
private LazyOptional<IMatterGridCell> cell_resolver = LazyOptional.of(() -> this);
protected BigDecimal initial_capacity;
protected ItemStack last_work_stack;
@ -142,12 +140,18 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
work_slots_handler.invalidate();
matter.invalidate();
cell_resolver.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
work_slots_handler.revive();
matter.revive();
cell_resolver = LazyOptional.of(() -> this);
}
@Nonnull
@ -155,11 +159,11 @@ public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implemen
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (valid) {
if (cap == MatteryCapability.MATTER) {
return matter_resolver.cast();
return matter.get().cast();
}
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return handler_resolver.cast();
return work_slots_handler.get().cast();
}
if (cap == MatteryCapability.MATTER_CELL) {

View File

@ -31,19 +31,21 @@ public class BlockEntityMatterCable extends BlockEntity implements IMatterGridCe
private MatterGrid grid;
private final LazyOptional<IMatterGridCell> resolver_grid = LazyOptional.of(() -> this);
private LazyOptional<IMatterGridCell> resolver_grid = LazyOptional.of(() -> this);
private boolean valid = true;
@Override
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
resolver_grid.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
resolver_grid = LazyOptional.of(() -> this);
}
@Nonnull

View File

@ -146,7 +146,7 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
}
};
private final LazyOptional<IMatterHandler> resolver = LazyOptional.of(() -> matter);
private LazyOptional<IMatterHandler> resolver = LazyOptional.of(() -> matter);
public final MatteryContainer matter_container = new MatteryContainer(this::setChanged, 6 * 2) {
@Override
@ -202,15 +202,19 @@ public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implement
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
resolver.invalidate();
resolver_grid.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
resolver = LazyOptional.of(() -> matter);
resolver_grid = LazyOptional.of(() -> this);
}
private final LazyOptional<IMatterGridCell> resolver_grid = LazyOptional.of(() -> this);
private LazyOptional<IMatterGridCell> resolver_grid = LazyOptional.of(() -> this);
@Nonnull
@Override

View File

@ -42,7 +42,7 @@ public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implem
private static final TranslatableComponent MACHINE_NAME = new TranslatableComponent("block.overdrive_that_matters.matter_decomposer");
private boolean valid = true;
public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.EXTRACT, new BigDecimal("20"));
private final LazyOptional<IMatterHandler> matter_resolver = LazyOptional.of(() -> matter);
private LazyOptional<IMatterHandler> matter_resolver = LazyOptional.of(() -> matter);
// вход, выход
public final MatteryContainer item_container = new MatteryContainer(this::setChanged, 2);
@ -96,15 +96,19 @@ public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implem
public void reviveCaps() {
valid = true;
super.reviveCaps();
matter_resolver = LazyOptional.of(() -> matter);
resolver_grid = LazyOptional.of(() -> this);
}
@Override
public void invalidateCaps() {
valid = false;
super.invalidateCaps();
matter_resolver.invalidate();
resolver_grid.invalidate();
}
private final LazyOptional<IMatterGridCell> resolver_grid = LazyOptional.of(() -> this);
private LazyOptional<IMatterGridCell> resolver_grid = LazyOptional.of(() -> this);
@Nonnull
@Override

View File

@ -63,15 +63,17 @@ public class BlockEntityMatterPanel extends BlockEntityMattery implements IMatte
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
resolver.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
resolver = LazyOptional.of(() -> this);
}
private final LazyOptional<BlockEntityMatterPanel> resolver = LazyOptional.of(() -> this);
private LazyOptional<BlockEntityMatterPanel> resolver = LazyOptional.of(() -> this);
@Nonnull
@Override

View File

@ -15,7 +15,6 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.entity.worker.BlockEntityMatteryWorker;
import ru.dbotthepony.mc.otm.block.entity.worker.MachineJob;
@ -24,6 +23,7 @@ import ru.dbotthepony.mc.otm.block.entity.worker.WorkTickContext;
import ru.dbotthepony.mc.otm.capability.*;
import ru.dbotthepony.mc.otm.capability.matter.*;
import ru.dbotthepony.mc.otm.container.MatteryContainer;
import ru.dbotthepony.mc.otm.container.MatteryContainerHandler;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu;
@ -49,9 +49,7 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
// запросы от matter replicator interface
public final MatteryContainer reserved_slots = new MatteryContainer(this::setChanged, 3);
private final LazyOptional<IItemHandler> resolve_handler = LazyOptional.of(() -> regular_slots.handler(
(slot, stack) -> false
));
private final MatteryContainerHandler slots_handler = regular_slots.handler((slot, stack) -> false);
private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.matter_replicator");
@ -231,15 +229,19 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
slots_handler.invalidate();
resolver_self.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
slots_handler.revive();
resolver_self = LazyOptional.of(() -> this);
}
private final LazyOptional<BlockEntityMatterReplicator> resolver_self = LazyOptional.of(() -> this);
private LazyOptional<BlockEntityMatterReplicator> resolver_self = LazyOptional.of(() -> this);
@Nonnull
@Override
@ -249,7 +251,7 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implem
return resolver_self.cast();
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return resolve_handler.cast();
return slots_handler.get().cast();
}
return super.getCapability(cap, side);

View File

@ -21,6 +21,7 @@ import ru.dbotthepony.mc.otm.block.entity.worker.MachineJob;
import ru.dbotthepony.mc.otm.block.entity.worker.MachineJobStatus;
import ru.dbotthepony.mc.otm.capability.*;
import ru.dbotthepony.mc.otm.capability.matter.*;
import ru.dbotthepony.mc.otm.container.MatteryContainerHandler;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
import ru.dbotthepony.mc.otm.Registry;
@ -41,10 +42,10 @@ public class BlockEntityMatterScanner extends BlockEntityMatteryWorker implement
public final MatteryContainer input_slot = new MatteryContainer(this::setChanged, 1);
private final LazyOptional<IItemHandler> handler_resolver = LazyOptional.of(() -> input_slot.handler(
private final MatteryContainerHandler input_handler = input_slot.handler(
(slot, stack) -> MatterRegistry.canDecompose(stack),
(slot, amount, stack) -> is_idling
));
);
public BlockEntityMatterScanner(BlockPos p_155229_, BlockState p_155230_) {
super(Registry.BlockEntities.MATTER_SCANNER, p_155229_, p_155230_);
@ -53,14 +54,14 @@ public class BlockEntityMatterScanner extends BlockEntityMatteryWorker implement
private boolean valid = true;
private final LazyOptional<IMatterGridCell> resolver_grid = LazyOptional.of(() -> this);
private LazyOptional<IMatterGridCell> resolver_grid = LazyOptional.of(() -> this);
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (valid) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return handler_resolver.cast();
return input_handler.get().cast();
if (cap == MatteryCapability.MATTER_CELL)
return resolver_grid.cast();
@ -73,12 +74,16 @@ public class BlockEntityMatterScanner extends BlockEntityMatteryWorker implement
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
input_handler.invalidate();
resolver_grid.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
input_handler.revive();
resolver_grid = LazyOptional.of(() -> this);
}
@Override

View File

@ -1,12 +1,15 @@
package ru.dbotthepony.mc.otm.block.entity;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
@ -16,13 +19,20 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.lang.ref.WeakReference;
import java.util.UUID;
import java.util.function.Consumer;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@SuppressWarnings("unused")
public abstract class BlockEntityMattery extends BlockEntity implements MenuProvider {
protected Component display_name;
protected RedstoneSetting redstone_setting = RedstoneSetting.LOW;
@ -38,6 +48,58 @@ public abstract class BlockEntityMattery extends BlockEntity implements MenuProv
abstract protected Component getDefaultDisplayName();
protected void tickOnce(Runnable func) {
if (level != null)
OverdriveThatMatters.tickOnce(level, func);
}
protected void tickOnceServer(Runnable func) {
if (level instanceof ServerLevel level)
OverdriveThatMatters.tickOnce(level, func);
}
protected void tickOnceClient(Runnable func) {
if (level instanceof ClientLevel level)
OverdriveThatMatters.tickOnce(level, func);
}
protected void tickOnce(Consumer<Level> func) {
if (level != null)
OverdriveThatMatters.tickOnce(level, func);
}
protected void tickOnceServer(Consumer<Level> func) {
if (level instanceof ServerLevel level)
OverdriveThatMatters.tickOnce(level, func);
}
protected void tickOnceClient(Consumer<Level> func) {
if (level instanceof ClientLevel level)
OverdriveThatMatters.tickOnce(level, func);
}
protected <T> LazyOptional<T> getAndBind(LazyOptional<T> old, @Nullable ICapabilityProvider provider, Capability<T> cap, @Nullable Direction side, Runnable invalidate) {
final var get = provider != null ? provider.getCapability(cap, side) : LazyOptional.empty();
if (old != get) {
if (get.isPresent()) {
final var ref = new WeakReference<>(invalidate);
get.addListener((l) -> {
final var self = ref.get();
if (self != null) {
self.run();
}
});
}
return get.cast();
}
return get.cast();
}
@Override
public Component getDisplayName() {
return display_name != null ? display_name : getDefaultDisplayName();

View File

@ -26,7 +26,7 @@ import java.util.Optional;
@ParametersAreNonnullByDefault
abstract public class BlockEntityMatteryPowered extends BlockEntityMattery {
protected MatteryMachineEnergyStorage energy = null;
protected final LazyOptional<MatteryMachineEnergyStorage> energy_resolver = LazyOptional.of(() -> energy);;
private LazyOptional<MatteryMachineEnergyStorage> energy_resolver = LazyOptional.of(() -> energy);
private boolean valid = true;
public MatteryContainer battery_container = new MatteryContainer(this::setChanged, 1);
@ -38,40 +38,40 @@ abstract public class BlockEntityMatteryPowered extends BlockEntityMattery {
if (energy.getMissingPower().compareTo(BigDecimal.ZERO) <= 0)
return;
BigDecimal demand = energy.getMissingPower();
var demand = energy.getMissingPower();
if (demand.compareTo(BigDecimal.ZERO) == 0)
return;
demand = demand.min(energy.receiveEnergyOuter(demand, true));
for (int i = 0; i < battery_container.getContainerSize() && demand.compareTo(BigDecimal.ZERO) > 0; i++) {
ItemStack stack = battery_container.getItem(i);
final var stack = battery_container.getItem(i);
if (!stack.isEmpty()) {
Optional<IMatteryEnergyStorage> mattery_storage = stack.getCapability(MatteryCapability.ENERGY).resolve();
final var mattery_storage = stack.getCapability(MatteryCapability.ENERGY).resolve();
if (mattery_storage.isPresent()) {
IMatteryEnergyStorage storage = mattery_storage.get();
BigDecimal drain = storage.extractEnergyOuter(demand, true);
final var drain = mattery_storage.get().extractEnergyOuter(demand, true);
if (drain.compareTo(BigDecimal.ZERO) != 0) {
BigDecimal receive = energy.receiveEnergyOuter(drain, true);
final var receive = energy.receiveEnergyOuter(drain, true);
storage.extractEnergyOuter(receive, false);
mattery_storage.get().extractEnergyOuter(receive, false);
energy.receiveEnergyOuter(receive, false);
demand = demand.subtract(receive, MatteryCapability.ROUND_RULES);
}
} else if (demand.compareTo(BigDecimal.ONE) >= 0) {
Optional<IEnergyStorage> storage = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
} else {
final var storage = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (storage.isPresent()) {
IEnergyStorage energy_fe = storage.get();
BigDecimal drain = MatteryCapability.drainFE(energy_fe, demand, true);
final var drain = MatteryCapability.drainFE(storage.get(), demand, true);
if (drain.compareTo(BigDecimal.ZERO) != 0) {
BigDecimal receive = energy.receiveEnergyOuter(drain, true);
final var receive = energy.receiveEnergyOuter(drain, true);
MatteryCapability.drainFE(energy_fe, receive, false);
MatteryCapability.drainFE(storage.get(), receive, false);
energy.receiveEnergyOuter(receive, false);
demand = demand.subtract(receive, MatteryCapability.ROUND_RULES);
@ -90,12 +90,14 @@ abstract public class BlockEntityMatteryPowered extends BlockEntityMattery {
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
energy_resolver.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
energy_resolver = LazyOptional.of(() -> energy);
}
@Nonnull
@ -109,14 +111,16 @@ abstract public class BlockEntityMatteryPowered extends BlockEntityMattery {
@Override
public CompoundTag save(CompoundTag nbt) {
if (energy != null)
nbt.put("energy_cap", energy.serializeNBT());
nbt.put("battery_container", battery_container.serializeNBT());
return super.save(nbt);
}
public void load(CompoundTag nbt) {
if (nbt.contains("energy_cap") && nbt.get("energy_cap") instanceof CompoundTag tag)
if (energy != null && nbt.get("energy_cap") instanceof CompoundTag tag)
energy.deserializeNBT(tag);
if (nbt.contains("battery_container") && nbt.get("battery_container") instanceof CompoundTag tag)

View File

@ -21,6 +21,7 @@ import net.minecraftforge.items.IItemHandler;
import ru.dbotthepony.mc.otm.block.BlockPatternStorage;
import ru.dbotthepony.mc.otm.capability.*;
import ru.dbotthepony.mc.otm.capability.matter.*;
import ru.dbotthepony.mc.otm.container.MatteryContainerHandler;
import ru.dbotthepony.mc.otm.matter.MatterGrid;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.container.MatteryContainer;
@ -78,9 +79,9 @@ public class BlockEntityPatternStorage extends BlockEntityMattery implements IMa
}
}
private final LazyOptional<IItemHandler> resolver_item = LazyOptional.of(() -> patterns.handler(
private final MatteryContainerHandler resolver_item = patterns.handler(
((slot, stack) -> stack.getCapability(MatteryCapability.PATTERN).isPresent())
));
);
private MatterGrid grid;
@ -138,12 +139,14 @@ public class BlockEntityPatternStorage extends BlockEntityMattery implements IMa
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
resolver_item.invalidate();
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
resolver_item.revive();
}
private final LazyOptional<BlockEntityPatternStorage> resolver = LazyOptional.of(() -> this);
@ -156,7 +159,7 @@ public class BlockEntityPatternStorage extends BlockEntityMattery implements IMa
return resolver.cast();
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return resolver_item.cast();
return resolver_item.get().cast();
}
return super.getCapability(cap, side);

View File

@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.capability.matter;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.matter.MatterRegistry;
@ -45,6 +46,20 @@ public class MatterHandlerCapability implements IMatterHandler, INBTSerializable
this.max_extract = max_extract;
}
private LazyOptional<IMatterHandler> handler = LazyOptional.of(() -> this);
public void invalidate() {
handler.invalidate();
}
public void revive() {
handler = LazyOptional.of(() -> this);
}
public LazyOptional<IMatterHandler> get() {
return handler;
}
@Nonnull
@Override
public BigDecimal getStoredMatter() {

View File

@ -164,21 +164,21 @@ public class MatteryContainer implements Container, Iterable<ItemStack> {
protected MatteryContainerHandler handler;
public IItemHandler handler(MatteryContainerInsertValidator insert_validator, MatteryContainerExtractValidator extract_validator) {
public MatteryContainerHandler handler(MatteryContainerInsertValidator insert_validator, MatteryContainerExtractValidator extract_validator) {
if (handler != null)
return handler;
return handler = new MatteryContainerHandler(this, insert_validator, extract_validator);
}
public IItemHandler handler(MatteryContainerInsertValidator insert_validator) {
public MatteryContainerHandler handler(MatteryContainerInsertValidator insert_validator) {
if (handler != null)
return handler;
return handler = new MatteryContainerHandler(this, insert_validator);
}
public IItemHandler handler() {
public MatteryContainerHandler handler() {
if (handler != null)
return handler;

View File

@ -1,11 +1,12 @@
package ru.dbotthepony.mc.otm.container;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
class MatteryContainerHandler implements IItemHandler {
public class MatteryContainerHandler implements IItemHandler {
private final MatteryContainer container;
private final MatteryContainerInsertValidator insert_validator;
private final MatteryContainerExtractValidator extract_validator;
@ -24,6 +25,20 @@ class MatteryContainerHandler implements IItemHandler {
this(container, insert_validator, (slot, amount, stack) -> true);
}
private LazyOptional<IItemHandler> handler = LazyOptional.of(() -> this);
public LazyOptional<IItemHandler> get() {
return handler;
}
public void invalidate() {
handler.invalidate();
}
public void revive() {
handler = LazyOptional.of(() -> this);
}
@Override
public int getSlots() {
return container.getContainerSize();

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.menu;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.entity.BlockEntity;
import ru.dbotthepony.mc.otm.Registry;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityCargoCrate;
import ru.dbotthepony.mc.otm.menu.slot.MatterySlot;
@ -17,7 +16,7 @@ public class CargoCrateMenu extends MatteryMenu {
public CargoCrateMenu(int p_38852_, Inventory inventory, BlockEntityCargoCrate tile) {
super(Registry.Menus.CARGO_CRATE, p_38852_, inventory, tile);
var container = tile != null ? tile.slots : new SimpleContainer(9 * 6);
var container = tile != null ? tile.container : new SimpleContainer(9 * 6);
for (int i = 0; i < container.getContainerSize(); i++) {
crate_slots[i] = new MatterySlot(container, i);