Lots more moved

This commit is contained in:
Sebastian Hartte
2020-07-04 21:03:30 +02:00
parent 5982f094ec
commit 1478e4c378
444 changed files with 4693 additions and 5235 deletions
@@ -21,6 +21,7 @@ package appeng.tile.storage;
import alexiil.mc.lib.attributes.AttributeList;
import alexiil.mc.lib.attributes.Simulation;
import alexiil.mc.lib.attributes.fluid.FluidInsertable;
import alexiil.mc.lib.attributes.fluid.FluidVolumeUtil;
import alexiil.mc.lib.attributes.fluid.amount.FluidAmount;
import alexiil.mc.lib.attributes.fluid.filter.ConstantFluidFilter;
import alexiil.mc.lib.attributes.fluid.filter.FluidFilter;
@@ -50,6 +51,7 @@ import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.util.AEColor;
import appeng.api.util.IConfigManager;
import appeng.container.implementations.MEMonitorableContainer;
import appeng.fluids.util.AEFluidStack;
import appeng.helpers.IPriorityHost;
import appeng.me.GridAccessException;
@@ -703,6 +705,9 @@ public class ChestBlockEntity extends AENetworkPowerBlockEntity
FluidAmount filledAmt = remaining != null ? remaining.getAmount() : toInsert.getAmount();
FluidAmount remainingAmt = fluidVolume.amount().roundedSub(filledAmt, RoundingMode.DOWN);
if (remainingAmt.isZero()) {
return FluidVolumeUtil.EMPTY;
}
return fluidVolume.withAmount(remainingAmt);
}
@@ -756,8 +761,7 @@ public class ChestBlockEntity extends AENetworkPowerBlockEntity
if (this.cellHandler != null) {
if (this.cellHandler.getChannel() == AEApi.instance().storage()
.getStorageChannel(IItemStorageChannel.class)) {
throw new IllegalStateException();
// FIXME FABRIC return MEMonitorableContainer.TYPE;
return MEMonitorableContainer.TYPE;
}
if (this.cellHandler.getChannel() == AEApi.instance().storage()
.getStorageChannel(IFluidStorageChannel.class)) {
@@ -0,0 +1,451 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.tile.storage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
import appeng.api.AEApi;
import appeng.api.implementations.tiles.IChestOrDrive;
import appeng.api.networking.GridFlags;
import appeng.api.networking.events.MENetworkCellArrayUpdate;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.networking.security.IActionSource;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.cells.CellState;
import appeng.api.storage.cells.ICellHandler;
import appeng.api.storage.cells.ICellInventory;
import appeng.api.storage.cells.ICellInventoryHandler;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.block.storage.DriveSlotsState;
import appeng.client.render.model.DriveModelData;
import appeng.container.implementations.DriveContainer;
import appeng.helpers.IPriorityHost;
import appeng.me.GridAccessException;
import appeng.me.helpers.MachineSource;
import appeng.me.storage.DriveWatcher;
import appeng.tile.grid.AENetworkInvBlockEntity;
import appeng.tile.inventory.AppEngCellInventory;
import appeng.util.Platform;
import appeng.util.inv.InvOperation;
import appeng.util.inv.filter.IAEItemFilter;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry;
public class DriveBlockEntity extends AENetworkInvBlockEntity implements IChestOrDrive, IPriorityHost {
private static final int BIT_POWER_MASK = Integer.MIN_VALUE;
private static final int BIT_STATE_MASK = 0b111111111111111111111111111111;
private static final int BIT_CELL_STATE_MASK = 0b111;
private static final int BIT_CELL_STATE_BITS = 3;
private final AppEngCellInventory inv = new AppEngCellInventory(this, 10);
private final ICellHandler[] handlersBySlot = new ICellHandler[10];
private final DriveWatcher<IAEItemStack>[] invBySlot = new DriveWatcher[10];
private final IActionSource mySrc;
private boolean isCached = false;
private Map<IStorageChannel<? extends IAEStack<?>>, List<IMEInventoryHandler>> inventoryHandlers;
private int priority = 0;
private boolean wasActive = false;
// This is only used on the client
private final Item[] cellItems = new Item[10];
/**
* The state of all cells inside a drive as bitset, using the following format.
*
* - Bit 31: power state. 0 = off, 1 = on.
*
* - Bit 30: reserved
*
* - Bit 29-0: 3 bits for the state of each cell
*
* Cell states:
*
* - Bit 2-0: {@link CellState} ordinal
*
*
*
*/
private int state = 0;
public DriveBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
this.mySrc = new MachineSource(this);
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
this.inventoryHandlers = new IdentityHashMap<>();
}
@Override
public void setOrientation(Direction inForward, Direction inUp) {
super.setOrientation(inForward, inUp);
this.getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(inForward)));
}
@Override
protected void writeToStream(final PacketByteBuf data) throws IOException {
super.writeToStream(data);
int newState = 0;
if (this.getProxy().isActive()) {
newState |= BIT_POWER_MASK;
}
for (int x = 0; x < this.getCellCount(); x++) {
final int o = this.getCellStatus(x).ordinal();
final int i = (o << (BIT_CELL_STATE_BITS * x));
newState |= i;
}
data.writeInt(newState);
writeCellItemIds(data);
}
private void writeCellItemIds(PacketByteBuf data) {
List<Integer> cellItemIds = new ArrayList<>(getCellCount());
byte[] bm = new byte[getCellCount()];
for (int x = 0; x < this.getCellCount(); x++) {
Item item = getCellItem(x);
if (item != null) {
int itemId = Item.getRawId(item);
int idx = cellItemIds.indexOf(itemId);
if (idx == -1) {
cellItemIds.add(itemId);
bm[x] = (byte) cellItemIds.size(); // We use 1-based in bm[]
} else {
bm[x] = (byte) (1 + idx); // 1-based indexing!!
}
}
}
// Write out the list of unique cell item ids
data.writeByte(cellItemIds.size());
for (int itemId : cellItemIds) {
data.writeVarInt(itemId);
}
// Then the lookup table for each slot
for (int i = 0; i < getCellCount(); i++) {
data.writeByte(bm[i]);
}
}
@Override
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
boolean c = super.readFromStream(data);
final int oldState = this.state;
this.state = data.readInt();
c |= this.readCellItemIDs(data);
return (this.state & BIT_STATE_MASK) != (oldState & BIT_STATE_MASK) || c;
}
private boolean readCellItemIDs(final PacketByteBuf data) {
int uniqueIdCount = data.readByte();
int[] uniqueIds = new int[uniqueIdCount];
for (int i = 0; i < uniqueIdCount; i++) {
uniqueIds[i] = data.readVarInt();
}
boolean changed = false;
for (int i = 0; i < getCellCount(); i++) {
byte idx = data.readByte();
// an index of 0 indicates the slot is empty
Item item = null;
if (idx > 0) {
--idx;
int itemId = uniqueIds[idx];
item = Item.byRawId(itemId);
}
if (cellItems[i] != item) {
changed = true;
cellItems[i] = item;
}
}
return changed;
}
@Override
public int getCellCount() {
return 10;
}
@Nullable
@Override
public Item getCellItem(int slot) {
// Client-side we'll need to actually use the synced state
if (world == null || world.isClient) {
return cellItems[slot];
}
ItemStack stackInSlot = inv.getInvStack(slot);
if (!stackInSlot.isEmpty()) {
return stackInSlot.getItem();
}
return null;
}
@Override
public CellState getCellStatus(final int slot) {
if (Platform.isClient()) {
final int cellState = ((this.state >> (slot * BIT_CELL_STATE_BITS)) & BIT_CELL_STATE_MASK);
return CellState.values()[cellState];
}
final DriveWatcher handler = this.invBySlot[slot];
if (handler == null) {
return CellState.ABSENT;
}
return handler.getStatus();
}
@Override
public boolean isPowered() {
if (isClient()) {
return (this.state & BIT_POWER_MASK) == BIT_POWER_MASK;
}
return this.getProxy().isActive();
}
@Override
public boolean isCellBlinking(final int slot) {
return false;
}
@Override
public void fromTag(BlockState state, final CompoundTag data) {
super.fromTag(state, data);
this.isCached = false;
this.priority = data.getInt("priority");
}
@Override
public CompoundTag toTag(final CompoundTag data) {
super.toTag(data);
data.putInt("priority", this.priority);
return data;
}
@MENetworkEventSubscribe
public void powerRender(final MENetworkPowerStatusChange c) {
this.recalculateDisplay();
}
private void recalculateDisplay() {
final boolean currentActive = this.getProxy().isActive();
int newState = 0;
if (currentActive) {
newState |= BIT_POWER_MASK;
}
if (this.wasActive != currentActive) {
this.wasActive = currentActive;
try {
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
} catch (final GridAccessException e) {
// :P
}
}
for (int x = 0; x < this.getCellCount(); x++) {
newState |= (this.getCellStatus(x).ordinal() << (BIT_CELL_STATE_BITS * x));
}
if (newState != this.state) {
this.state = newState;
this.markForUpdate();
}
}
@MENetworkEventSubscribe
public void channelRender(final MENetworkChannelsChanged c) {
this.recalculateDisplay();
}
@Override
public AECableType getCableConnectionType(final AEPartLocation dir) {
return AECableType.SMART;
}
@Override
public DimensionalCoord getLocation() {
return new DimensionalCoord(this);
}
@Override
public FixedItemInv getInternalInventory() {
return this.inv;
}
@Override
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
final ItemStack removed, final ItemStack added) {
if (this.isCached) {
this.isCached = false; // recalculate the storage cell.
this.updateState();
}
try {
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
final IStorageGrid gs = this.getProxy().getStorage();
Platform.postChanges(gs, removed, added, this.mySrc);
} catch (final GridAccessException ignored) {
}
this.markForUpdate();
}
private void updateState() {
if (!this.isCached) {
final Collection<IStorageChannel<? extends IAEStack<?>>> storageChannels = AEApi.instance().storage()
.storageChannels();
storageChannels.forEach(channel -> this.inventoryHandlers.put(channel, new ArrayList<>(10)));
double power = 2.0;
for (int x = 0; x < this.inv.getSlotCount(); x++) {
final ItemStack is = this.inv.getInvStack(x);
this.invBySlot[x] = null;
this.handlersBySlot[x] = null;
if (!is.isEmpty()) {
this.handlersBySlot[x] = AEApi.instance().registries().cell().getHandler(is);
if (this.handlersBySlot[x] != null) {
for (IStorageChannel<? extends IAEStack<?>> channel : storageChannels) {
ICellInventoryHandler cell = this.handlersBySlot[x].getCellInventory(is, this, channel);
if (cell != null) {
this.inv.setHandler(x, cell);
power += this.handlersBySlot[x].cellIdleDrain(is, cell);
final DriveWatcher<IAEItemStack> ih = new DriveWatcher(cell, is, this.handlersBySlot[x],
this);
ih.setPriority(this.priority);
this.invBySlot[x] = ih;
this.inventoryHandlers.get(channel).add(ih);
break;
}
}
}
}
}
this.getProxy().setIdlePowerUsage(power);
this.isCached = true;
}
}
@Override
public void onReady() {
super.onReady();
this.updateState();
}
@Override
public List<IMEInventoryHandler> getCellArray(final IStorageChannel channel) {
if (this.getProxy().isActive()) {
this.updateState();
return this.inventoryHandlers.get(channel);
}
return Collections.emptyList();
}
@Override
public int getPriority() {
return this.priority;
}
@Override
public void setPriority(final int newValue) {
this.priority = newValue;
this.saveChanges();
this.isCached = false; // recalculate the storage cell.
this.updateState();
try {
this.getProxy().getGrid().postEvent(new MENetworkCellArrayUpdate());
} catch (final GridAccessException e) {
// :P
}
}
@Override
public void blinkCell(final int slot) {
this.recalculateDisplay();
}
@Override
public void saveChanges(final ICellInventory<?> cellInventory) {
this.world.markDirty(this.pos, this);
}
@Override
public ItemStack getItemStackRepresentation() {
return AEApi.instance().definitions().blocks().drive().maybeStack(1).orElse(ItemStack.EMPTY);
}
@Override
public DriveModelData getRenderAttachmentData() {
return new DriveModelData(getUp(), getForward(), DriveSlotsState.fromChestOrDrive(this));
}
@Override
public ScreenHandlerType<?> getContainerType() {
return DriveContainer.TYPE;
}
}
@@ -0,0 +1,449 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.tile.storage;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import alexiil.mc.lib.attributes.Simulation;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FullnessMode;
import appeng.api.config.OperationMode;
import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings;
import appeng.api.config.Upgrades;
import appeng.api.config.YesNo;
import appeng.api.implementations.IUpgradeableHost;
import appeng.api.networking.GridFlags;
import appeng.api.networking.IGridNode;
import appeng.api.networking.energy.IEnergySource;
import appeng.api.networking.security.IActionSource;
import appeng.api.networking.ticking.IGridTickable;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.api.util.IConfigManager;
import appeng.core.settings.TickRates;
import appeng.me.GridAccessException;
import appeng.me.helpers.MachineSource;
import appeng.parts.automation.BlockUpgradeInventory;
import appeng.parts.automation.UpgradeInventory;
import appeng.tile.grid.AENetworkInvBlockEntity;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.AdaptorFixedInv;
import appeng.util.inv.InvOperation;
import appeng.util.inv.WrapperChainedItemHandler;
import appeng.util.inv.WrapperFilteredItemHandler;
import appeng.util.inv.filter.AEItemFilters;
public class IOPortBlockEntity extends AENetworkInvBlockEntity
implements IUpgradeableHost, IConfigManagerHost, IGridTickable {
private static final int NUMBER_OF_CELL_SLOTS = 6;
private static final int NUMBER_OF_UPGRADE_SLOTS = 3;
private final ConfigManager manager;
private final AppEngInternalInventory inputCells = new AppEngInternalInventory(this, NUMBER_OF_CELL_SLOTS);
private final AppEngInternalInventory outputCells = new AppEngInternalInventory(this, NUMBER_OF_CELL_SLOTS);
private final FixedItemInv combinedInventory = new WrapperChainedItemHandler(this.inputCells, this.outputCells);
private final FixedItemInv inputCellsExt = new WrapperFilteredItemHandler(this.inputCells,
AEItemFilters.INSERT_ONLY);
private final FixedItemInv outputCellsExt = new WrapperFilteredItemHandler(this.outputCells,
AEItemFilters.EXTRACT_ONLY);
private final UpgradeInventory upgrades;
private final IActionSource mySrc;
private YesNo lastRedstoneState;
private ItemStack currentCell;
private Map<IStorageChannel<?>, IMEInventory<?>> cachedInventories;
public IOPortBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
this.manager = new ConfigManager(this);
this.manager.registerSetting(Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE);
this.manager.registerSetting(Settings.FULLNESS_MODE, FullnessMode.EMPTY);
this.manager.registerSetting(Settings.OPERATION_MODE, OperationMode.EMPTY);
this.mySrc = new MachineSource(this);
this.lastRedstoneState = YesNo.UNDECIDED;
final Block ioPortBlock = AEApi.instance().definitions().blocks().iOPort().maybeBlock().get();
this.upgrades = new BlockUpgradeInventory(ioPortBlock, this, NUMBER_OF_UPGRADE_SLOTS);
}
@Override
public CompoundTag toTag(final CompoundTag data) {
super.toTag(data);
this.manager.writeToNBT(data);
this.upgrades.writeToNBT(data, "upgrades");
data.putInt("lastRedstoneState", this.lastRedstoneState.ordinal());
return data;
}
@Override
public void fromTag(BlockState state, final CompoundTag data) {
super.fromTag(state, data);
this.manager.readFromNBT(data);
this.upgrades.readFromNBT(data, "upgrades");
if (data.contains("lastRedstoneState")) {
this.lastRedstoneState = YesNo.values()[data.getInt("lastRedstoneState")];
}
}
@Override
public AECableType getCableConnectionType(final AEPartLocation dir) {
return AECableType.SMART;
}
@Override
public DimensionalCoord getLocation() {
return new DimensionalCoord(this);
}
private void updateTask() {
try {
if (this.hasWork()) {
this.getProxy().getTick().wakeDevice(this.getProxy().getNode());
} else {
this.getProxy().getTick().sleepDevice(this.getProxy().getNode());
}
} catch (final GridAccessException e) {
// :P
}
}
public void updateRedstoneState() {
final YesNo currentState = this.world.getReceivedRedstonePower(this.pos) != 0 ? YesNo.YES : YesNo.NO;
if (this.lastRedstoneState != currentState) {
this.lastRedstoneState = currentState;
this.updateTask();
}
}
private boolean getRedstoneState() {
if (this.lastRedstoneState == YesNo.UNDECIDED) {
this.updateRedstoneState();
}
return this.lastRedstoneState == YesNo.YES;
}
private boolean isEnabled() {
if (this.getInstalledUpgrades(Upgrades.REDSTONE) == 0) {
return true;
}
final RedstoneMode rs = (RedstoneMode) this.manager.getSetting(Settings.REDSTONE_CONTROLLED);
if (rs == RedstoneMode.HIGH_SIGNAL) {
return this.getRedstoneState();
}
return !this.getRedstoneState();
}
@Override
public IConfigManager getConfigManager() {
return this.manager;
}
@Override
public FixedItemInv getInventoryByName(final String name) {
if (name.equals("upgrades")) {
return this.upgrades;
}
if (name.equals("cells")) {
return this.combinedInventory;
}
return null;
}
@Override
public void updateSetting(final IConfigManager manager, final Settings settingName, final Enum<?> newValue) {
this.updateTask();
}
private boolean hasWork() {
if (this.isEnabled()) {
return !ItemHandlerUtil.isEmpty(this.inputCells);
}
return false;
}
@Override
public FixedItemInv getInternalInventory() {
return this.combinedInventory;
}
@Override
public void onChangeInventory(final FixedItemInv inv, final int slot, final InvOperation mc,
final ItemStack removed, final ItemStack added) {
if (this.inputCells == inv) {
this.updateTask();
}
}
@Override
protected FixedItemInv getItemHandlerForSide(final Direction facing) {
if (facing == this.getUp() || facing == this.getUp().getOpposite()) {
return this.inputCellsExt;
} else {
return this.outputCellsExt;
}
}
@Override
public TickingRequest getTickingRequest(final IGridNode node) {
return new TickingRequest(TickRates.IOPort.getMin(), TickRates.IOPort.getMax(), !this.hasWork(), false);
}
@Override
public TickRateModulation tickingRequest(final IGridNode node, final int ticksSinceLastCall) {
if (!this.getProxy().isActive()) {
return TickRateModulation.IDLE;
}
TickRateModulation ret = TickRateModulation.SLEEP;
long itemsToMove = 256;
switch (this.getInstalledUpgrades(Upgrades.SPEED)) {
case 1:
itemsToMove *= 2;
break;
case 2:
itemsToMove *= 4;
break;
case 3:
itemsToMove *= 8;
break;
}
try {
final IEnergySource energy = this.getProxy().getEnergy();
for (int x = 0; x < NUMBER_OF_CELL_SLOTS; x++) {
final ItemStack is = this.inputCells.getInvStack(x);
if (!is.isEmpty()) {
boolean shouldMove = true;
for (IStorageChannel<? extends IAEStack<?>> c : AEApi.instance().storage().storageChannels()) {
if (itemsToMove > 0) {
final IMEMonitor<? extends IAEStack<?>> network = this.getProxy().getStorage()
.getInventory(c);
final IMEInventory<?> inv = this.getInv(is, c);
if (inv == null) {
continue;
}
if (this.manager.getSetting(Settings.OPERATION_MODE) == OperationMode.EMPTY) {
itemsToMove = this.transferContents(energy, inv, network, itemsToMove, c);
} else {
itemsToMove = this.transferContents(energy, network, inv, itemsToMove, c);
}
shouldMove &= this.shouldMove(inv);
if (itemsToMove > 0) {
ret = TickRateModulation.IDLE;
} else {
ret = TickRateModulation.URGENT;
}
}
}
if (itemsToMove > 0 && shouldMove && this.moveSlot(x)) {
ret = TickRateModulation.URGENT;
} else {
ret = TickRateModulation.URGENT;
}
}
}
} catch (final GridAccessException e) {
ret = TickRateModulation.IDLE;
}
return ret;
}
@Override
public int getInstalledUpgrades(final Upgrades u) {
return this.upgrades.getInstalledUpgrades(u);
}
private IMEInventory<?> getInv(final ItemStack is, final IStorageChannel<?> chan) {
if (this.currentCell != is) {
this.currentCell = is;
this.cachedInventories = new IdentityHashMap<>();
for (IStorageChannel<? extends IAEStack<?>> c : AEApi.instance().storage().storageChannels()) {
this.cachedInventories.put(c, AEApi.instance().registries().cell().getCellInventory(is, null, c));
}
}
return this.cachedInventories.get(chan);
}
private long transferContents(final IEnergySource energy, final IMEInventory src, final IMEInventory destination,
long itemsToMove, final IStorageChannel chan) {
final IItemList<? extends IAEStack> myList;
if (src instanceof IMEMonitor) {
myList = ((IMEMonitor) src).getStorageList();
} else {
myList = src.getAvailableItems(src.getChannel().createList());
}
itemsToMove *= chan.transferFactor();
boolean didStuff;
do {
didStuff = false;
for (final IAEStack s : myList) {
final long totalStackSize = s.getStackSize();
if (totalStackSize > 0) {
final IAEStack stack = destination.injectItems(s, Actionable.SIMULATE, this.mySrc);
long possible = 0;
if (stack == null) {
possible = totalStackSize;
} else {
possible = totalStackSize - stack.getStackSize();
}
if (possible > 0) {
possible = Math.min(possible, itemsToMove);
s.setStackSize(possible);
final IAEStack extracted = src.extractItems(s, Actionable.MODULATE, this.mySrc);
if (extracted != null) {
possible = extracted.getStackSize();
final IAEStack failed = Platform.poweredInsert(energy, destination, extracted, this.mySrc);
if (failed != null) {
possible -= failed.getStackSize();
src.injectItems(failed, Actionable.MODULATE, this.mySrc);
}
if (possible > 0) {
itemsToMove -= possible;
didStuff = true;
}
break;
}
}
}
}
} while (itemsToMove > 0 && didStuff);
return itemsToMove / chan.transferFactor();
}
private boolean shouldMove(final IMEInventory<?> inv) {
final FullnessMode fm = (FullnessMode) this.manager.getSetting(Settings.FULLNESS_MODE);
if (inv != null) {
return this.matches(fm, inv);
}
return true;
}
private boolean moveSlot(final int x) {
final InventoryAdaptor ad = new AdaptorFixedInv(this.outputCells);
if (ad.addItems(this.inputCells.getInvStack(x)).isEmpty()) {
this.inputCells.setInvStack(x, ItemStack.EMPTY, Simulation.ACTION);
return true;
}
return false;
}
private boolean matches(final FullnessMode fm, final IMEInventory src) {
if (fm == FullnessMode.HALF) {
return true;
}
final IItemList<? extends IAEStack> myList;
if (src instanceof IMEMonitor) {
myList = ((IMEMonitor) src).getStorageList();
} else {
myList = src.getAvailableItems(src.getChannel().createList());
}
if (fm == FullnessMode.EMPTY) {
return myList.isEmpty();
}
final IAEStack test = myList.getFirstItem();
if (test != null) {
test.setStackSize(1);
return src.injectItems(test, Actionable.SIMULATE, this.mySrc) != null;
}
return false;
}
/**
* Adds the items in the upgrade slots to the drop list.
*
* @param w world
* @param pos pos of block entity
* @param drops drops of block entity
*/
@Override
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
super.getDrops(w, pos, drops);
for (int upgradeIndex = 0; upgradeIndex < this.upgrades.getSlotCount(); upgradeIndex++) {
final ItemStack stackInSlot = this.upgrades.getInvStack(upgradeIndex);
if (!stackInSlot.isEmpty()) {
drops.add(stackInSlot);
}
}
}
}