pick 97420a31d The big reformat of 2020
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
@@ -30,322 +29,273 @@ import appeng.api.storage.ISaveProvider;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
|
||||
|
||||
/**
|
||||
* @author DrummerMC
|
||||
* @version rv6 - 2018-01-17
|
||||
* @since rv6 2018-01-17
|
||||
*/
|
||||
public abstract class AbstractCellInventory<T extends IAEStack<T>> implements ICellInventory<T>
|
||||
{
|
||||
private static final int MAX_ITEM_TYPES = 63;
|
||||
private static final String ITEM_TYPE_TAG = "it";
|
||||
private static final String ITEM_COUNT_TAG = "ic";
|
||||
private static final String ITEM_SLOT = "#";
|
||||
private static final String ITEM_SLOT_COUNT = "@";
|
||||
protected static final String ITEM_PRE_FORMATTED_COUNT = "PF";
|
||||
protected static final String ITEM_PRE_FORMATTED_SLOT = "PF#";
|
||||
protected static final String ITEM_PRE_FORMATTED_NAME = "PN";
|
||||
protected static final String ITEM_PRE_FORMATTED_FUZZY = "FP";
|
||||
private static final String[] ITEM_SLOT_KEYS = new String[MAX_ITEM_TYPES];
|
||||
private static final String[] ITEM_SLOT_COUNT_KEYS = new String[MAX_ITEM_TYPES];
|
||||
private final CompoundNBT tagCompound;
|
||||
protected final ISaveProvider container;
|
||||
private int maxItemTypes = MAX_ITEM_TYPES;
|
||||
private short storedItems = 0;
|
||||
private int storedItemCount = 0;
|
||||
protected IItemList<T> cellItems;
|
||||
private final ItemStack i;
|
||||
protected final IStorageCell<T> cellType;
|
||||
protected final int itemsPerByte;
|
||||
private boolean isPersisted = true;
|
||||
public abstract class AbstractCellInventory<T extends IAEStack<T>> implements ICellInventory<T> {
|
||||
private static final int MAX_ITEM_TYPES = 63;
|
||||
private static final String ITEM_TYPE_TAG = "it";
|
||||
private static final String ITEM_COUNT_TAG = "ic";
|
||||
private static final String ITEM_SLOT = "#";
|
||||
private static final String ITEM_SLOT_COUNT = "@";
|
||||
protected static final String ITEM_PRE_FORMATTED_COUNT = "PF";
|
||||
protected static final String ITEM_PRE_FORMATTED_SLOT = "PF#";
|
||||
protected static final String ITEM_PRE_FORMATTED_NAME = "PN";
|
||||
protected static final String ITEM_PRE_FORMATTED_FUZZY = "FP";
|
||||
private static final String[] ITEM_SLOT_KEYS = new String[MAX_ITEM_TYPES];
|
||||
private static final String[] ITEM_SLOT_COUNT_KEYS = new String[MAX_ITEM_TYPES];
|
||||
private final CompoundNBT tagCompound;
|
||||
protected final ISaveProvider container;
|
||||
private int maxItemTypes = MAX_ITEM_TYPES;
|
||||
private short storedItems = 0;
|
||||
private int storedItemCount = 0;
|
||||
protected IItemList<T> cellItems;
|
||||
private final ItemStack i;
|
||||
protected final IStorageCell<T> cellType;
|
||||
protected final int itemsPerByte;
|
||||
private boolean isPersisted = true;
|
||||
|
||||
static
|
||||
{
|
||||
for( int x = 0; x < MAX_ITEM_TYPES; x++ )
|
||||
{
|
||||
ITEM_SLOT_KEYS[x] = ITEM_SLOT + x;
|
||||
ITEM_SLOT_COUNT_KEYS[x] = ITEM_SLOT_COUNT + x;
|
||||
}
|
||||
}
|
||||
static {
|
||||
for (int x = 0; x < MAX_ITEM_TYPES; x++) {
|
||||
ITEM_SLOT_KEYS[x] = ITEM_SLOT + x;
|
||||
ITEM_SLOT_COUNT_KEYS[x] = ITEM_SLOT_COUNT + x;
|
||||
}
|
||||
}
|
||||
|
||||
protected AbstractCellInventory( final IStorageCell<T> cellType, final ItemStack o, final ISaveProvider container )
|
||||
{
|
||||
this.i = o;
|
||||
this.cellType = cellType;
|
||||
this.itemsPerByte = this.cellType.getChannel().getUnitsPerByte();
|
||||
this.maxItemTypes = this.cellType.getTotalTypes( this.i );
|
||||
protected AbstractCellInventory(final IStorageCell<T> cellType, final ItemStack o, final ISaveProvider container) {
|
||||
this.i = o;
|
||||
this.cellType = cellType;
|
||||
this.itemsPerByte = this.cellType.getChannel().getUnitsPerByte();
|
||||
this.maxItemTypes = this.cellType.getTotalTypes(this.i);
|
||||
|
||||
if( this.maxItemTypes > MAX_ITEM_TYPES )
|
||||
{
|
||||
this.maxItemTypes = MAX_ITEM_TYPES;
|
||||
}
|
||||
if( this.maxItemTypes < 1 )
|
||||
{
|
||||
this.maxItemTypes = 1;
|
||||
}
|
||||
if (this.maxItemTypes > MAX_ITEM_TYPES) {
|
||||
this.maxItemTypes = MAX_ITEM_TYPES;
|
||||
}
|
||||
if (this.maxItemTypes < 1) {
|
||||
this.maxItemTypes = 1;
|
||||
}
|
||||
|
||||
this.container = container;
|
||||
this.tagCompound = o.getOrCreateTag();
|
||||
this.storedItems = this.tagCompound.getShort( ITEM_TYPE_TAG );
|
||||
this.storedItemCount = this.tagCompound.getInt( ITEM_COUNT_TAG );
|
||||
this.cellItems = null;
|
||||
}
|
||||
this.container = container;
|
||||
this.tagCompound = o.getOrCreateTag();
|
||||
this.storedItems = this.tagCompound.getShort(ITEM_TYPE_TAG);
|
||||
this.storedItemCount = this.tagCompound.getInt(ITEM_COUNT_TAG);
|
||||
this.cellItems = null;
|
||||
}
|
||||
|
||||
protected IItemList<T> getCellItems()
|
||||
{
|
||||
if( this.cellItems == null )
|
||||
{
|
||||
this.cellItems = this.getChannel().createList();
|
||||
this.loadCellItems();
|
||||
}
|
||||
protected IItemList<T> getCellItems() {
|
||||
if (this.cellItems == null) {
|
||||
this.cellItems = this.getChannel().createList();
|
||||
this.loadCellItems();
|
||||
}
|
||||
|
||||
return this.cellItems;
|
||||
}
|
||||
return this.cellItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void persist()
|
||||
{
|
||||
if( this.isPersisted )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void persist() {
|
||||
if (this.isPersisted) {
|
||||
return;
|
||||
}
|
||||
|
||||
int itemCount = 0;
|
||||
int itemCount = 0;
|
||||
|
||||
// add new pretty stuff...
|
||||
int x = 0;
|
||||
for( final T v : this.cellItems )
|
||||
{
|
||||
itemCount += v.getStackSize();
|
||||
// add new pretty stuff...
|
||||
int x = 0;
|
||||
for (final T v : this.cellItems) {
|
||||
itemCount += v.getStackSize();
|
||||
|
||||
final CompoundNBT g = new CompoundNBT();
|
||||
v.writeToNBT( g );
|
||||
this.tagCompound.put( ITEM_SLOT_KEYS[x], g );
|
||||
this.tagCompound.putInt( ITEM_SLOT_COUNT_KEYS[x], (int) v.getStackSize() );
|
||||
final CompoundNBT g = new CompoundNBT();
|
||||
v.writeToNBT(g);
|
||||
this.tagCompound.put(ITEM_SLOT_KEYS[x], g);
|
||||
this.tagCompound.putInt(ITEM_SLOT_COUNT_KEYS[x], (int) v.getStackSize());
|
||||
|
||||
x++;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
final short oldStoredItems = this.storedItems;
|
||||
final short oldStoredItems = this.storedItems;
|
||||
|
||||
this.storedItems = (short) this.cellItems.size();
|
||||
if( this.cellItems.isEmpty() )
|
||||
{
|
||||
this.tagCompound.remove( ITEM_TYPE_TAG );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tagCompound.putShort( ITEM_TYPE_TAG, this.storedItems );
|
||||
}
|
||||
this.storedItems = (short) this.cellItems.size();
|
||||
if (this.cellItems.isEmpty()) {
|
||||
this.tagCompound.remove(ITEM_TYPE_TAG);
|
||||
} else {
|
||||
this.tagCompound.putShort(ITEM_TYPE_TAG, this.storedItems);
|
||||
}
|
||||
|
||||
this.storedItemCount = itemCount;
|
||||
if( itemCount == 0 )
|
||||
{
|
||||
this.tagCompound.remove( ITEM_COUNT_TAG );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tagCompound.putInt( ITEM_COUNT_TAG, itemCount );
|
||||
}
|
||||
this.storedItemCount = itemCount;
|
||||
if (itemCount == 0) {
|
||||
this.tagCompound.remove(ITEM_COUNT_TAG);
|
||||
} else {
|
||||
this.tagCompound.putInt(ITEM_COUNT_TAG, itemCount);
|
||||
}
|
||||
|
||||
// clean any old crusty stuff...
|
||||
for( ; x < oldStoredItems && x < this.maxItemTypes; x++ )
|
||||
{
|
||||
this.tagCompound.remove( ITEM_SLOT_KEYS[x] );
|
||||
this.tagCompound.remove( ITEM_SLOT_COUNT_KEYS[x] );
|
||||
}
|
||||
// clean any old crusty stuff...
|
||||
for (; x < oldStoredItems && x < this.maxItemTypes; x++) {
|
||||
this.tagCompound.remove(ITEM_SLOT_KEYS[x]);
|
||||
this.tagCompound.remove(ITEM_SLOT_COUNT_KEYS[x]);
|
||||
}
|
||||
|
||||
this.isPersisted = true;
|
||||
}
|
||||
this.isPersisted = true;
|
||||
}
|
||||
|
||||
protected void saveChanges()
|
||||
{
|
||||
// recalculate values
|
||||
this.storedItems = (short) this.cellItems.size();
|
||||
this.storedItemCount = 0;
|
||||
for( final T v : this.cellItems )
|
||||
{
|
||||
this.storedItemCount += v.getStackSize();
|
||||
}
|
||||
protected void saveChanges() {
|
||||
// recalculate values
|
||||
this.storedItems = (short) this.cellItems.size();
|
||||
this.storedItemCount = 0;
|
||||
for (final T v : this.cellItems) {
|
||||
this.storedItemCount += v.getStackSize();
|
||||
}
|
||||
|
||||
this.isPersisted = false;
|
||||
if( this.container != null )
|
||||
{
|
||||
this.container.saveChanges( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there is no ISaveProvider, store to NBT immediately
|
||||
this.persist();
|
||||
}
|
||||
}
|
||||
this.isPersisted = false;
|
||||
if (this.container != null) {
|
||||
this.container.saveChanges(this);
|
||||
} else {
|
||||
// if there is no ISaveProvider, store to NBT immediately
|
||||
this.persist();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadCellItems()
|
||||
{
|
||||
if( this.cellItems == null )
|
||||
{
|
||||
this.cellItems = this.getChannel().createList();
|
||||
}
|
||||
private void loadCellItems() {
|
||||
if (this.cellItems == null) {
|
||||
this.cellItems = this.getChannel().createList();
|
||||
}
|
||||
|
||||
this.cellItems.resetStatus(); // clears totals and stuff.
|
||||
this.cellItems.resetStatus(); // clears totals and stuff.
|
||||
|
||||
final int types = (int) this.getStoredItemTypes();
|
||||
boolean needsUpdate = false;
|
||||
final int types = (int) this.getStoredItemTypes();
|
||||
boolean needsUpdate = false;
|
||||
|
||||
for( int slot = 0; slot < types; slot++ )
|
||||
{
|
||||
CompoundNBT compoundTag = this.tagCompound.getCompound( ITEM_SLOT_KEYS[slot] );
|
||||
int stackSize = this.tagCompound.getInt( ITEM_SLOT_COUNT_KEYS[slot] );
|
||||
needsUpdate |= !this.loadCellItem( compoundTag, stackSize );
|
||||
}
|
||||
for (int slot = 0; slot < types; slot++) {
|
||||
CompoundNBT compoundTag = this.tagCompound.getCompound(ITEM_SLOT_KEYS[slot]);
|
||||
int stackSize = this.tagCompound.getInt(ITEM_SLOT_COUNT_KEYS[slot]);
|
||||
needsUpdate |= !this.loadCellItem(compoundTag, stackSize);
|
||||
}
|
||||
|
||||
if( needsUpdate )
|
||||
{
|
||||
this.saveChanges();
|
||||
}
|
||||
}
|
||||
if (needsUpdate) {
|
||||
this.saveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a single item.
|
||||
*
|
||||
* @param compoundTag
|
||||
* @param stackSize
|
||||
* @return true when successfully loaded
|
||||
*/
|
||||
protected abstract boolean loadCellItem( CompoundNBT compoundTag, int stackSize );
|
||||
/**
|
||||
* Load a single item.
|
||||
*
|
||||
* @param compoundTag
|
||||
* @param stackSize
|
||||
* @return true when successfully loaded
|
||||
*/
|
||||
protected abstract boolean loadCellItem(CompoundNBT compoundTag, int stackSize);
|
||||
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems( final IItemList<T> out )
|
||||
{
|
||||
for( final T item : this.getCellItems() )
|
||||
{
|
||||
out.add( item );
|
||||
}
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems(final IItemList<T> out) {
|
||||
for (final T item : this.getCellItems()) {
|
||||
out.add(item);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack()
|
||||
{
|
||||
return this.i;
|
||||
}
|
||||
@Override
|
||||
public ItemStack getItemStack() {
|
||||
return this.i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getIdleDrain()
|
||||
{
|
||||
return this.cellType.getIdleDrain();
|
||||
}
|
||||
@Override
|
||||
public double getIdleDrain() {
|
||||
return this.cellType.getIdleDrain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FuzzyMode getFuzzyMode()
|
||||
{
|
||||
return this.cellType.getFuzzyMode( this.i );
|
||||
}
|
||||
@Override
|
||||
public FuzzyMode getFuzzyMode() {
|
||||
return this.cellType.getFuzzyMode(this.i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemHandler getConfigInventory()
|
||||
{
|
||||
return this.cellType.getConfigInventory( this.i );
|
||||
}
|
||||
@Override
|
||||
public IItemHandler getConfigInventory() {
|
||||
return this.cellType.getConfigInventory(this.i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemHandler getUpgradesInventory()
|
||||
{
|
||||
return this.cellType.getUpgradesInventory( this.i );
|
||||
}
|
||||
@Override
|
||||
public IItemHandler getUpgradesInventory() {
|
||||
return this.cellType.getUpgradesInventory(this.i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytesPerType()
|
||||
{
|
||||
return this.cellType.getBytesPerType( this.i );
|
||||
}
|
||||
@Override
|
||||
public int getBytesPerType() {
|
||||
return this.cellType.getBytesPerType(this.i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHoldNewItem()
|
||||
{
|
||||
final long bytesFree = this.getFreeBytes();
|
||||
return ( bytesFree > this.getBytesPerType() || ( bytesFree == this.getBytesPerType() && this.getUnusedItemCount() > 0 ) ) && this
|
||||
.getRemainingItemTypes() > 0;
|
||||
}
|
||||
@Override
|
||||
public boolean canHoldNewItem() {
|
||||
final long bytesFree = this.getFreeBytes();
|
||||
return (bytesFree > this.getBytesPerType()
|
||||
|| (bytesFree == this.getBytesPerType() && this.getUnusedItemCount() > 0))
|
||||
&& this.getRemainingItemTypes() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalBytes()
|
||||
{
|
||||
return this.cellType.getBytes( this.i );
|
||||
}
|
||||
@Override
|
||||
public long getTotalBytes() {
|
||||
return this.cellType.getBytes(this.i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFreeBytes()
|
||||
{
|
||||
return this.getTotalBytes() - this.getUsedBytes();
|
||||
}
|
||||
@Override
|
||||
public long getFreeBytes() {
|
||||
return this.getTotalBytes() - this.getUsedBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalItemTypes()
|
||||
{
|
||||
return this.maxItemTypes;
|
||||
}
|
||||
@Override
|
||||
public long getTotalItemTypes() {
|
||||
return this.maxItemTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStoredItemCount()
|
||||
{
|
||||
return this.storedItemCount;
|
||||
}
|
||||
@Override
|
||||
public long getStoredItemCount() {
|
||||
return this.storedItemCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStoredItemTypes()
|
||||
{
|
||||
return this.storedItems;
|
||||
}
|
||||
@Override
|
||||
public long getStoredItemTypes() {
|
||||
return this.storedItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingItemTypes()
|
||||
{
|
||||
final long basedOnStorage = this.getFreeBytes() / this.getBytesPerType();
|
||||
final long baseOnTotal = this.getTotalItemTypes() - this.getStoredItemTypes();
|
||||
return basedOnStorage > baseOnTotal ? baseOnTotal : basedOnStorage;
|
||||
}
|
||||
@Override
|
||||
public long getRemainingItemTypes() {
|
||||
final long basedOnStorage = this.getFreeBytes() / this.getBytesPerType();
|
||||
final long baseOnTotal = this.getTotalItemTypes() - this.getStoredItemTypes();
|
||||
return basedOnStorage > baseOnTotal ? baseOnTotal : basedOnStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUsedBytes()
|
||||
{
|
||||
final long bytesForItemCount = ( this.getStoredItemCount() + this.getUnusedItemCount() ) / this.itemsPerByte;
|
||||
return this.getStoredItemTypes() * this.getBytesPerType() + bytesForItemCount;
|
||||
}
|
||||
@Override
|
||||
public long getUsedBytes() {
|
||||
final long bytesForItemCount = (this.getStoredItemCount() + this.getUnusedItemCount()) / this.itemsPerByte;
|
||||
return this.getStoredItemTypes() * this.getBytesPerType() + bytesForItemCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingItemCount()
|
||||
{
|
||||
final long remaining = this.getFreeBytes() * this.itemsPerByte + this.getUnusedItemCount();
|
||||
return remaining > 0 ? remaining : 0;
|
||||
}
|
||||
@Override
|
||||
public long getRemainingItemCount() {
|
||||
final long remaining = this.getFreeBytes() * this.itemsPerByte + this.getUnusedItemCount();
|
||||
return remaining > 0 ? remaining : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnusedItemCount()
|
||||
{
|
||||
final int div = (int) ( this.getStoredItemCount() % 8 );
|
||||
@Override
|
||||
public int getUnusedItemCount() {
|
||||
final int div = (int) (this.getStoredItemCount() % 8);
|
||||
|
||||
if( div == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (div == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.itemsPerByte - div;
|
||||
}
|
||||
return this.itemsPerByte - div;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatusForCell()
|
||||
{
|
||||
if( this.canHoldNewItem() )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if( this.getRemainingItemCount() > 0 )
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
@Override
|
||||
public int getStatusForCell() {
|
||||
if (this.canHoldNewItem()) {
|
||||
return 1;
|
||||
}
|
||||
if (this.getRemainingItemCount() > 0) {
|
||||
return 2;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
@@ -19,270 +18,221 @@ import appeng.core.AEConfig;
|
||||
import appeng.core.AELog;
|
||||
import appeng.util.item.AEStack;
|
||||
|
||||
public class BasicCellInventory<T extends IAEStack<T>> extends AbstractCellInventory<T> {
|
||||
private final IStorageChannel<T> channel;
|
||||
|
||||
public class BasicCellInventory<T extends IAEStack<T>> extends AbstractCellInventory<T>
|
||||
{
|
||||
private final IStorageChannel<T> channel;
|
||||
private BasicCellInventory(final IStorageCell<T> cellType, final ItemStack o, final ISaveProvider container) {
|
||||
super(cellType, o, container);
|
||||
this.channel = cellType.getChannel();
|
||||
}
|
||||
|
||||
private BasicCellInventory( final IStorageCell<T> cellType, final ItemStack o, final ISaveProvider container )
|
||||
{
|
||||
super( cellType, o, container );
|
||||
this.channel = cellType.getChannel();
|
||||
}
|
||||
public static <T extends IAEStack<T>> ICellInventory<T> createInventory(final ItemStack o,
|
||||
final ISaveProvider container) {
|
||||
try {
|
||||
if (o == null) {
|
||||
throw new AppEngException("ItemStack was used as a cell, but was not a cell!");
|
||||
}
|
||||
|
||||
public static <T extends IAEStack<T>> ICellInventory<T> createInventory( final ItemStack o, final ISaveProvider container )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( o == null )
|
||||
{
|
||||
throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" );
|
||||
}
|
||||
final Item type = o.getItem();
|
||||
final IStorageCell<T> cellType;
|
||||
if (type instanceof IStorageCell) {
|
||||
cellType = (IStorageCell<T>) type;
|
||||
} else {
|
||||
throw new AppEngException("ItemStack was used as a cell, but was not a cell!");
|
||||
}
|
||||
|
||||
final Item type = o.getItem();
|
||||
final IStorageCell<T> cellType;
|
||||
if( type instanceof IStorageCell )
|
||||
{
|
||||
cellType = (IStorageCell<T>) type;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" );
|
||||
}
|
||||
if (!cellType.isStorageCell(o)) {
|
||||
throw new AppEngException("ItemStack was used as a cell, but was not a cell!");
|
||||
}
|
||||
|
||||
if( !cellType.isStorageCell( o ) )
|
||||
{
|
||||
throw new AppEngException( "ItemStack was used as a cell, but was not a cell!" );
|
||||
}
|
||||
return new BasicCellInventory<T>(cellType, o, container);
|
||||
} catch (final AppEngException e) {
|
||||
AELog.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return new BasicCellInventory<T>( cellType, o, container );
|
||||
}
|
||||
catch( final AppEngException e )
|
||||
{
|
||||
AELog.error( e );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static <T extends AEStack<T>> boolean isCellOfType(final ItemStack input, IStorageChannel<?> channel) {
|
||||
final IStorageCell<?> type = getStorageCell(input);
|
||||
|
||||
public static <T extends AEStack<T>> boolean isCellOfType( final ItemStack input, IStorageChannel<?> channel )
|
||||
{
|
||||
final IStorageCell<?> type = getStorageCell( input );
|
||||
return type != null && type.getChannel() == channel;
|
||||
}
|
||||
|
||||
return type != null && type.getChannel() == channel;
|
||||
}
|
||||
public static boolean isCell(final ItemStack input) {
|
||||
return getStorageCell(input) != null;
|
||||
}
|
||||
|
||||
public static boolean isCell( final ItemStack input )
|
||||
{
|
||||
return getStorageCell( input ) != null;
|
||||
}
|
||||
private boolean isStorageCell(final T input) {
|
||||
if (input instanceof IAEItemStack) {
|
||||
final IAEItemStack stack = (IAEItemStack) input;
|
||||
final IStorageCell<?> type = getStorageCell(stack.getDefinition());
|
||||
|
||||
private boolean isStorageCell( final T input )
|
||||
{
|
||||
if( input instanceof IAEItemStack )
|
||||
{
|
||||
final IAEItemStack stack = (IAEItemStack) input;
|
||||
final IStorageCell<?> type = getStorageCell( stack.getDefinition() );
|
||||
return type != null && !type.storableInStorageCell();
|
||||
}
|
||||
|
||||
return type != null && !type.storableInStorageCell();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
private static IStorageCell<?> getStorageCell(final ItemStack input) {
|
||||
if (input != null) {
|
||||
final Item type = input.getItem();
|
||||
|
||||
private static IStorageCell<?> getStorageCell( final ItemStack input )
|
||||
{
|
||||
if( input != null )
|
||||
{
|
||||
final Item type = input.getItem();
|
||||
if (type instanceof IStorageCell) {
|
||||
return (IStorageCell<?>) type;
|
||||
}
|
||||
}
|
||||
|
||||
if( type instanceof IStorageCell )
|
||||
{
|
||||
return (IStorageCell<?>) type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private static boolean isCellEmpty(ICellInventory inv) {
|
||||
if (inv != null) {
|
||||
return inv.getAvailableItems(inv.getChannel().createList()).isEmpty();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings( { "rawtypes", "unchecked" } )
|
||||
private static boolean isCellEmpty( ICellInventory inv )
|
||||
{
|
||||
if( inv != null )
|
||||
{
|
||||
return inv.getAvailableItems( inv.getChannel().createList() ).isEmpty();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public T injectItems(T input, Actionable mode, IActionSource src) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
if (input.getStackSize() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems( T input, Actionable mode, IActionSource src )
|
||||
{
|
||||
if( input == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if( input.getStackSize() == 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (this.cellType.isBlackListed(this.getItemStack(), input)) {
|
||||
return input;
|
||||
}
|
||||
// This is slightly hacky as it expects a read-only access, but fine for now.
|
||||
// TODO: Guarantee a read-only access. E.g. provide an isEmpty() method and
|
||||
// ensure CellInventory does not write
|
||||
// any NBT data for empty cells instead of relying on an empty IItemContainer
|
||||
if (this.isStorageCell(input)) {
|
||||
final ICellInventory<?> meInventory = createInventory(((IAEItemStack) input).createItemStack(), null);
|
||||
if (!isCellEmpty(meInventory)) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
if( this.cellType.isBlackListed( this.getItemStack(), input ) )
|
||||
{
|
||||
return input;
|
||||
}
|
||||
// This is slightly hacky as it expects a read-only access, but fine for now.
|
||||
// TODO: Guarantee a read-only access. E.g. provide an isEmpty() method and ensure CellInventory does not write
|
||||
// any NBT data for empty cells instead of relying on an empty IItemContainer
|
||||
if( this.isStorageCell( input ) )
|
||||
{
|
||||
final ICellInventory<?> meInventory = createInventory( ( (IAEItemStack) input ).createItemStack(), null );
|
||||
if( !isCellEmpty( meInventory ) )
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
final T l = this.getCellItems().findPrecise(input);
|
||||
if (l != null) {
|
||||
final long remainingItemCount = this.getRemainingItemCount();
|
||||
if (remainingItemCount <= 0) {
|
||||
return input;
|
||||
}
|
||||
|
||||
final T l = this.getCellItems().findPrecise( input );
|
||||
if( l != null )
|
||||
{
|
||||
final long remainingItemCount = this.getRemainingItemCount();
|
||||
if( remainingItemCount <= 0 )
|
||||
{
|
||||
return input;
|
||||
}
|
||||
if (input.getStackSize() > remainingItemCount) {
|
||||
final T r = input.copy();
|
||||
r.setStackSize(r.getStackSize() - remainingItemCount);
|
||||
if (mode == Actionable.MODULATE) {
|
||||
l.setStackSize(l.getStackSize() + remainingItemCount);
|
||||
this.saveChanges();
|
||||
}
|
||||
return r;
|
||||
} else {
|
||||
if (mode == Actionable.MODULATE) {
|
||||
l.setStackSize(l.getStackSize() + input.getStackSize());
|
||||
this.saveChanges();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if( input.getStackSize() > remainingItemCount )
|
||||
{
|
||||
final T r = input.copy();
|
||||
r.setStackSize( r.getStackSize() - remainingItemCount );
|
||||
if( mode == Actionable.MODULATE )
|
||||
{
|
||||
l.setStackSize( l.getStackSize() + remainingItemCount );
|
||||
this.saveChanges();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mode == Actionable.MODULATE )
|
||||
{
|
||||
l.setStackSize( l.getStackSize() + input.getStackSize() );
|
||||
this.saveChanges();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (this.canHoldNewItem()) // room for new type, and for at least one item!
|
||||
{
|
||||
final int remainingItemCount = (int) this.getRemainingItemCount()
|
||||
- this.getBytesPerType() * this.itemsPerByte;
|
||||
if (remainingItemCount > 0) {
|
||||
if (input.getStackSize() > remainingItemCount) {
|
||||
final T toReturn = input.copy();
|
||||
toReturn.setStackSize(input.getStackSize() - remainingItemCount);
|
||||
if (mode == Actionable.MODULATE) {
|
||||
final T toWrite = input.copy();
|
||||
toWrite.setStackSize(remainingItemCount);
|
||||
|
||||
if( this.canHoldNewItem() ) // room for new type, and for at least one item!
|
||||
{
|
||||
final int remainingItemCount = (int) this.getRemainingItemCount() - this.getBytesPerType() * this.itemsPerByte;
|
||||
if( remainingItemCount > 0 )
|
||||
{
|
||||
if( input.getStackSize() > remainingItemCount )
|
||||
{
|
||||
final T toReturn = input.copy();
|
||||
toReturn.setStackSize( input.getStackSize() - remainingItemCount );
|
||||
if( mode == Actionable.MODULATE )
|
||||
{
|
||||
final T toWrite = input.copy();
|
||||
toWrite.setStackSize( remainingItemCount );
|
||||
this.cellItems.add(toWrite);
|
||||
this.saveChanges();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
this.cellItems.add( toWrite );
|
||||
this.saveChanges();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
if (mode == Actionable.MODULATE) {
|
||||
this.cellItems.add(input);
|
||||
this.saveChanges();
|
||||
}
|
||||
|
||||
if( mode == Actionable.MODULATE )
|
||||
{
|
||||
this.cellItems.add( input );
|
||||
this.saveChanges();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
@Override
|
||||
public T extractItems(T request, Actionable mode, IActionSource src) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extractItems( T request, Actionable mode, IActionSource src )
|
||||
{
|
||||
if( request == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final long size = Math.min(Integer.MAX_VALUE, request.getStackSize());
|
||||
|
||||
final long size = Math.min( Integer.MAX_VALUE, request.getStackSize() );
|
||||
T Results = null;
|
||||
|
||||
T Results = null;
|
||||
final T l = this.getCellItems().findPrecise(request);
|
||||
if (l != null) {
|
||||
Results = l.copy();
|
||||
|
||||
final T l = this.getCellItems().findPrecise( request );
|
||||
if( l != null )
|
||||
{
|
||||
Results = l.copy();
|
||||
if (l.getStackSize() <= size) {
|
||||
Results.setStackSize(l.getStackSize());
|
||||
if (mode == Actionable.MODULATE) {
|
||||
l.setStackSize(0);
|
||||
this.saveChanges();
|
||||
}
|
||||
} else {
|
||||
Results.setStackSize(size);
|
||||
if (mode == Actionable.MODULATE) {
|
||||
l.setStackSize(l.getStackSize() - size);
|
||||
this.saveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( l.getStackSize() <= size )
|
||||
{
|
||||
Results.setStackSize( l.getStackSize() );
|
||||
if( mode == Actionable.MODULATE )
|
||||
{
|
||||
l.setStackSize( 0 );
|
||||
this.saveChanges();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Results.setStackSize( size );
|
||||
if( mode == Actionable.MODULATE )
|
||||
{
|
||||
l.setStackSize( l.getStackSize() - size );
|
||||
this.saveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Results;
|
||||
}
|
||||
|
||||
return Results;
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel<T> getChannel() {
|
||||
return this.channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel<T> getChannel()
|
||||
{
|
||||
return this.channel;
|
||||
}
|
||||
@Override
|
||||
protected boolean loadCellItem(CompoundNBT compoundTag, int stackSize) {
|
||||
// Now load the item stack
|
||||
final T t;
|
||||
try {
|
||||
t = this.getChannel().createFromNBT(compoundTag);
|
||||
if (t == null) {
|
||||
AELog.warn("Removing item " + compoundTag
|
||||
+ " from storage cell because the associated item type couldn't be found.");
|
||||
return false;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
if (AEConfig.instance().isRemoveCrashingItemsOnLoad()) {
|
||||
AELog.warn(ex,
|
||||
"Removing item " + compoundTag + " from storage cell because loading the ItemStack crashed.");
|
||||
return false;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean loadCellItem( CompoundNBT compoundTag, int stackSize )
|
||||
{
|
||||
// Now load the item stack
|
||||
final T t;
|
||||
try
|
||||
{
|
||||
t = this.getChannel().createFromNBT( compoundTag );
|
||||
if( t == null )
|
||||
{
|
||||
AELog.warn( "Removing item " + compoundTag + " from storage cell because the associated item type couldn't be found." );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch( Throwable ex )
|
||||
{
|
||||
if( AEConfig.instance().isRemoveCrashingItemsOnLoad() )
|
||||
{
|
||||
AELog.warn( ex, "Removing item " + compoundTag + " from storage cell because loading the ItemStack crashed." );
|
||||
return false;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
t.setStackSize(stackSize);
|
||||
|
||||
t.setStackSize( stackSize );
|
||||
if (stackSize > 0) {
|
||||
this.cellItems.add(t);
|
||||
}
|
||||
|
||||
if( stackSize > 0 )
|
||||
{
|
||||
this.cellItems.add( t );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
@@ -36,114 +35,94 @@ import appeng.api.storage.data.IItemList;
|
||||
import appeng.util.prioritylist.FuzzyPriorityList;
|
||||
import appeng.util.prioritylist.PrecisePriorityList;
|
||||
|
||||
|
||||
/**
|
||||
* @author DrummerMC
|
||||
* @version rv6 - 2018-01-23
|
||||
* @since rv6 2018-01-23
|
||||
*/
|
||||
public class BasicCellInventoryHandler<T extends IAEStack<T>> extends MEInventoryHandler<T> implements ICellInventoryHandler<T>
|
||||
{
|
||||
public BasicCellInventoryHandler( final IMEInventory c, final IStorageChannel<T> channel )
|
||||
{
|
||||
super( c, channel );
|
||||
public class BasicCellInventoryHandler<T extends IAEStack<T>> extends MEInventoryHandler<T>
|
||||
implements ICellInventoryHandler<T> {
|
||||
public BasicCellInventoryHandler(final IMEInventory c, final IStorageChannel<T> channel) {
|
||||
super(c, channel);
|
||||
|
||||
final ICellInventory ci = this.getCellInv();
|
||||
if( ci != null )
|
||||
{
|
||||
final IItemList<T> priorityList = channel.createList();
|
||||
final ICellInventory ci = this.getCellInv();
|
||||
if (ci != null) {
|
||||
final IItemList<T> priorityList = channel.createList();
|
||||
|
||||
final IItemHandler upgrades = ci.getUpgradesInventory();
|
||||
final IItemHandler config = ci.getConfigInventory();
|
||||
final FuzzyMode fzMode = ci.getFuzzyMode();
|
||||
final IItemHandler upgrades = ci.getUpgradesInventory();
|
||||
final IItemHandler config = ci.getConfigInventory();
|
||||
final FuzzyMode fzMode = ci.getFuzzyMode();
|
||||
|
||||
boolean hasInverter = false;
|
||||
boolean hasFuzzy = false;
|
||||
boolean hasInverter = false;
|
||||
boolean hasFuzzy = false;
|
||||
|
||||
for( int x = 0; x < upgrades.getSlots(); x++ )
|
||||
{
|
||||
final ItemStack is = upgrades.getStackInSlot( x );
|
||||
if( !is.isEmpty() && is.getItem() instanceof IUpgradeModule )
|
||||
{
|
||||
final Upgrades u = ( (IUpgradeModule) is.getItem() ).getType( is );
|
||||
if( u != null )
|
||||
{
|
||||
switch( u )
|
||||
{
|
||||
case FUZZY:
|
||||
hasFuzzy = true;
|
||||
break;
|
||||
case INVERTER:
|
||||
hasInverter = true;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < upgrades.getSlots(); x++) {
|
||||
final ItemStack is = upgrades.getStackInSlot(x);
|
||||
if (!is.isEmpty() && is.getItem() instanceof IUpgradeModule) {
|
||||
final Upgrades u = ((IUpgradeModule) is.getItem()).getType(is);
|
||||
if (u != null) {
|
||||
switch (u) {
|
||||
case FUZZY:
|
||||
hasFuzzy = true;
|
||||
break;
|
||||
case INVERTER:
|
||||
hasInverter = true;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( int x = 0; x < config.getSlots(); x++ )
|
||||
{
|
||||
final ItemStack is = config.getStackInSlot( x );
|
||||
if( !is.isEmpty() )
|
||||
{
|
||||
final T configItem = channel.createStack( is );
|
||||
if( configItem != null )
|
||||
{
|
||||
priorityList.add( configItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < config.getSlots(); x++) {
|
||||
final ItemStack is = config.getStackInSlot(x);
|
||||
if (!is.isEmpty()) {
|
||||
final T configItem = channel.createStack(is);
|
||||
if (configItem != null) {
|
||||
priorityList.add(configItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setWhitelist( hasInverter ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST );
|
||||
this.setWhitelist(hasInverter ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST);
|
||||
|
||||
if( !priorityList.isEmpty() )
|
||||
{
|
||||
if( hasFuzzy )
|
||||
{
|
||||
this.setPartitionList( new FuzzyPriorityList<>( priorityList, fzMode ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setPartitionList( new PrecisePriorityList<>( priorityList ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!priorityList.isEmpty()) {
|
||||
if (hasFuzzy) {
|
||||
this.setPartitionList(new FuzzyPriorityList<>(priorityList, fzMode));
|
||||
} else {
|
||||
this.setPartitionList(new PrecisePriorityList<>(priorityList));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICellInventory getCellInv()
|
||||
{
|
||||
Object o = this.getInternal();
|
||||
@Override
|
||||
public ICellInventory getCellInv() {
|
||||
Object o = this.getInternal();
|
||||
|
||||
if( o instanceof MEPassThrough )
|
||||
{
|
||||
o = ( (MEPassThrough) o ).getInternal();
|
||||
}
|
||||
if (o instanceof MEPassThrough) {
|
||||
o = ((MEPassThrough) o).getInternal();
|
||||
}
|
||||
|
||||
return (ICellInventory) ( o instanceof ICellInventory ? o : null );
|
||||
}
|
||||
return (ICellInventory) (o instanceof ICellInventory ? o : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreformatted()
|
||||
{
|
||||
return !this.getPartitionList().isEmpty();
|
||||
}
|
||||
@Override
|
||||
public boolean isPreformatted() {
|
||||
return !this.getPartitionList().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFuzzy()
|
||||
{
|
||||
return this.getPartitionList() instanceof FuzzyPriorityList;
|
||||
}
|
||||
@Override
|
||||
public boolean isFuzzy() {
|
||||
return this.getPartitionList() instanceof FuzzyPriorityList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IncludeExclude getIncludeExcludeMode()
|
||||
{
|
||||
return this.getWhitelist();
|
||||
}
|
||||
@Override
|
||||
public IncludeExclude getIncludeExcludeMode() {
|
||||
return this.getWhitelist();
|
||||
}
|
||||
|
||||
CompoundNBT openNbtData()
|
||||
{
|
||||
CompoundNBT openNbtData() {
|
||||
return this.getCellInv().getItemStack().getOrCreateTag();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
@@ -34,104 +33,87 @@ import appeng.api.storage.data.IItemList;
|
||||
import appeng.items.contents.CellConfig;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class CreativeCellInventory implements IMEInventoryHandler<IAEItemStack> {
|
||||
|
||||
public class CreativeCellInventory implements IMEInventoryHandler<IAEItemStack>
|
||||
{
|
||||
private final IItemList<IAEItemStack> itemListCache = AEApi.instance().storage()
|
||||
.getStorageChannel(IItemStorageChannel.class).createList();
|
||||
|
||||
private final IItemList<IAEItemStack> itemListCache = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
|
||||
protected CreativeCellInventory(final ItemStack o) {
|
||||
final CellConfig cc = new CellConfig(o);
|
||||
for (final ItemStack is : cc) {
|
||||
if (!is.isEmpty()) {
|
||||
final IAEItemStack i = AEItemStack.fromItemStack(is);
|
||||
i.setStackSize(Integer.MAX_VALUE);
|
||||
this.itemListCache.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected CreativeCellInventory( final ItemStack o )
|
||||
{
|
||||
final CellConfig cc = new CellConfig( o );
|
||||
for( final ItemStack is : cc )
|
||||
{
|
||||
if( !is.isEmpty() )
|
||||
{
|
||||
final IAEItemStack i = AEItemStack.fromItemStack( is );
|
||||
i.setStackSize( Integer.MAX_VALUE );
|
||||
this.itemListCache.add( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
public static ICellInventoryHandler getCell(final ItemStack o) {
|
||||
return new BasicCellInventoryHandler(new CreativeCellInventory(o),
|
||||
AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class));
|
||||
}
|
||||
|
||||
public static ICellInventoryHandler getCell( final ItemStack o )
|
||||
{
|
||||
return new BasicCellInventoryHandler( new CreativeCellInventory( o ), AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
|
||||
}
|
||||
@Override
|
||||
public IAEItemStack injectItems(final IAEItemStack input, final Actionable mode, final IActionSource src) {
|
||||
final IAEItemStack local = this.itemListCache.findPrecise(input);
|
||||
if (local == null) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack injectItems( final IAEItemStack input, final Actionable mode, final IActionSource src )
|
||||
{
|
||||
final IAEItemStack local = this.itemListCache.findPrecise( input );
|
||||
if( local == null )
|
||||
{
|
||||
return input;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public IAEItemStack extractItems(final IAEItemStack request, final Actionable mode, final IActionSource src) {
|
||||
final IAEItemStack local = this.itemListCache.findPrecise(request);
|
||||
if (local == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack extractItems( final IAEItemStack request, final Actionable mode, final IActionSource src )
|
||||
{
|
||||
final IAEItemStack local = this.itemListCache.findPrecise( request );
|
||||
if( local == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return request.copy();
|
||||
}
|
||||
|
||||
return request.copy();
|
||||
}
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getAvailableItems(final IItemList out) {
|
||||
for (final IAEItemStack ais : this.itemListCache) {
|
||||
out.add(ais);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getAvailableItems( final IItemList out )
|
||||
{
|
||||
for( final IAEItemStack ais : this.itemListCache )
|
||||
{
|
||||
out.add( ais );
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel getChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel getChannel()
|
||||
{
|
||||
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
|
||||
}
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrioritized(final IAEItemStack input) {
|
||||
return this.itemListCache.findPrecise(input) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final IAEItemStack input )
|
||||
{
|
||||
return this.itemListCache.findPrecise( input ) != null;
|
||||
}
|
||||
@Override
|
||||
public boolean canAccept(final IAEItemStack input) {
|
||||
return this.itemListCache.findPrecise(input) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final IAEItemStack input )
|
||||
{
|
||||
return this.itemListCache.findPrecise( input ) != null;
|
||||
}
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
@@ -28,65 +27,56 @@ import appeng.api.storage.ICellHandler;
|
||||
import appeng.api.storage.ICellInventoryHandler;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
|
||||
public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T> {
|
||||
|
||||
public class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T>
|
||||
{
|
||||
private int oldStatus = 0;
|
||||
private final ItemStack is;
|
||||
private final ICellHandler handler;
|
||||
private final IChestOrDrive cord;
|
||||
|
||||
private int oldStatus = 0;
|
||||
private final ItemStack is;
|
||||
private final ICellHandler handler;
|
||||
private final IChestOrDrive cord;
|
||||
public DriveWatcher(final ICellInventoryHandler<T> i, final ItemStack is, final ICellHandler han,
|
||||
final IChestOrDrive cod) {
|
||||
super(i, i.getChannel());
|
||||
this.is = is;
|
||||
this.handler = han;
|
||||
this.cord = cod;
|
||||
}
|
||||
|
||||
public DriveWatcher( final ICellInventoryHandler<T> i, final ItemStack is, final ICellHandler han, final IChestOrDrive cod )
|
||||
{
|
||||
super( i, i.getChannel() );
|
||||
this.is = is;
|
||||
this.handler = han;
|
||||
this.cord = cod;
|
||||
}
|
||||
public int getStatus() {
|
||||
return this.handler.getStatusForCell(this.is, (ICellInventoryHandler) this.getInternal());
|
||||
}
|
||||
|
||||
public int getStatus()
|
||||
{
|
||||
return this.handler.getStatusForCell( this.is, (ICellInventoryHandler) this.getInternal() );
|
||||
}
|
||||
@Override
|
||||
public T injectItems(final T input, final Actionable type, final IActionSource src) {
|
||||
final long size = input.getStackSize();
|
||||
|
||||
@Override
|
||||
public T injectItems( final T input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
final long size = input.getStackSize();
|
||||
final T a = super.injectItems(input, type, src);
|
||||
|
||||
final T a = super.injectItems( input, type, src );
|
||||
if (type == Actionable.MODULATE && (a == null || a.getStackSize() != size)) {
|
||||
final int newStatus = this.getStatus();
|
||||
|
||||
if( type == Actionable.MODULATE && ( a == null || a.getStackSize() != size ) )
|
||||
{
|
||||
final int newStatus = this.getStatus();
|
||||
if (newStatus != this.oldStatus) {
|
||||
this.cord.blinkCell(this.getSlot());
|
||||
this.oldStatus = newStatus;
|
||||
}
|
||||
}
|
||||
|
||||
if( newStatus != this.oldStatus )
|
||||
{
|
||||
this.cord.blinkCell( this.getSlot() );
|
||||
this.oldStatus = newStatus;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
@Override
|
||||
public T extractItems(final T request, final Actionable type, final IActionSource src) {
|
||||
final T a = super.extractItems(request, type, src);
|
||||
|
||||
@Override
|
||||
public T extractItems( final T request, final Actionable type, final IActionSource src )
|
||||
{
|
||||
final T a = super.extractItems( request, type, src );
|
||||
if (type == Actionable.MODULATE && a != null) {
|
||||
final int newStatus = this.getStatus();
|
||||
|
||||
if( type == Actionable.MODULATE && a != null )
|
||||
{
|
||||
final int newStatus = this.getStatus();
|
||||
if (newStatus != this.oldStatus) {
|
||||
this.cord.blinkCell(this.getSlot());
|
||||
this.oldStatus = newStatus;
|
||||
}
|
||||
}
|
||||
|
||||
if( newStatus != this.oldStatus )
|
||||
{
|
||||
this.cord.blinkCell( this.getSlot() );
|
||||
this.oldStatus = newStatus;
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,13 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
|
||||
public interface ITickingMonitor {
|
||||
|
||||
public interface ITickingMonitor
|
||||
{
|
||||
TickRateModulation onTick();
|
||||
|
||||
TickRateModulation onTick();
|
||||
|
||||
void setActionSource( IActionSource actionSource );
|
||||
void setActionSource(IActionSource actionSource);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
@@ -28,54 +27,46 @@ import appeng.api.networking.storage.IStackWatcherHost;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.me.cache.GridStorageCache;
|
||||
|
||||
|
||||
/**
|
||||
* Maintain my interests, and a global watch list, they should always be fully synchronized.
|
||||
* Maintain my interests, and a global watch list, they should always be fully
|
||||
* synchronized.
|
||||
*/
|
||||
public class ItemWatcher implements IStackWatcher
|
||||
{
|
||||
public class ItemWatcher implements IStackWatcher {
|
||||
|
||||
private final GridStorageCache gsc;
|
||||
private final IStackWatcherHost myObject;
|
||||
private final Set<IAEStack> myInterests = new HashSet<>();
|
||||
private final GridStorageCache gsc;
|
||||
private final IStackWatcherHost myObject;
|
||||
private final Set<IAEStack> myInterests = new HashSet<>();
|
||||
|
||||
public ItemWatcher( final GridStorageCache cache, final IStackWatcherHost host )
|
||||
{
|
||||
this.gsc = cache;
|
||||
this.myObject = host;
|
||||
}
|
||||
public ItemWatcher(final GridStorageCache cache, final IStackWatcherHost host) {
|
||||
this.gsc = cache;
|
||||
this.myObject = host;
|
||||
}
|
||||
|
||||
public IStackWatcherHost getHost()
|
||||
{
|
||||
return this.myObject;
|
||||
}
|
||||
public IStackWatcherHost getHost() {
|
||||
return this.myObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add( final IAEStack e )
|
||||
{
|
||||
if( this.myInterests.contains( e ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean add(final IAEStack e) {
|
||||
if (this.myInterests.contains(e)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.myInterests.add( e.copy() ) && this.gsc.getInterestManager().put( e, this );
|
||||
}
|
||||
return this.myInterests.add(e.copy()) && this.gsc.getInterestManager().put(e, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove( final IAEStack o )
|
||||
{
|
||||
return this.myInterests.remove( o ) && this.gsc.getInterestManager().remove( o, this );
|
||||
}
|
||||
@Override
|
||||
public boolean remove(final IAEStack o) {
|
||||
return this.myInterests.remove(o) && this.gsc.getInterestManager().remove(o, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
final Iterator<IAEStack> i = this.myInterests.iterator();
|
||||
@Override
|
||||
public void reset() {
|
||||
final Iterator<IAEStack> i = this.myInterests.iterator();
|
||||
|
||||
while( i.hasNext() )
|
||||
{
|
||||
this.gsc.getInterestManager().remove( i.next(), this );
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
while (i.hasNext()) {
|
||||
this.gsc.getInterestManager().remove(i.next(), this);
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.config.IncludeExclude;
|
||||
@@ -31,169 +30,138 @@ import appeng.api.storage.data.IItemList;
|
||||
import appeng.util.prioritylist.DefaultPriorityList;
|
||||
import appeng.util.prioritylist.IPartitionList;
|
||||
|
||||
public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHandler<T> {
|
||||
|
||||
public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHandler<T>
|
||||
{
|
||||
private final IMEInventoryHandler<T> internal;
|
||||
private int myPriority;
|
||||
private IncludeExclude myWhitelist;
|
||||
private AccessRestriction myAccess;
|
||||
private IPartitionList<T> myPartitionList;
|
||||
|
||||
private final IMEInventoryHandler<T> internal;
|
||||
private int myPriority;
|
||||
private IncludeExclude myWhitelist;
|
||||
private AccessRestriction myAccess;
|
||||
private IPartitionList<T> myPartitionList;
|
||||
private AccessRestriction cachedAccessRestriction;
|
||||
private boolean hasReadAccess;
|
||||
private boolean hasWriteAccess;
|
||||
|
||||
private AccessRestriction cachedAccessRestriction;
|
||||
private boolean hasReadAccess;
|
||||
private boolean hasWriteAccess;
|
||||
public MEInventoryHandler(final IMEInventory<T> i, final IStorageChannel<T> channel) {
|
||||
if (i instanceof IMEInventoryHandler) {
|
||||
this.internal = (IMEInventoryHandler<T>) i;
|
||||
} else {
|
||||
this.internal = new MEPassThrough<>(i, channel);
|
||||
}
|
||||
|
||||
public MEInventoryHandler( final IMEInventory<T> i, final IStorageChannel<T> channel )
|
||||
{
|
||||
if( i instanceof IMEInventoryHandler )
|
||||
{
|
||||
this.internal = (IMEInventoryHandler<T>) i;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.internal = new MEPassThrough<>( i, channel );
|
||||
}
|
||||
this.myPriority = 0;
|
||||
this.myWhitelist = IncludeExclude.WHITELIST;
|
||||
this.setBaseAccess(AccessRestriction.READ_WRITE);
|
||||
this.myPartitionList = new DefaultPriorityList<>();
|
||||
}
|
||||
|
||||
this.myPriority = 0;
|
||||
this.myWhitelist = IncludeExclude.WHITELIST;
|
||||
this.setBaseAccess( AccessRestriction.READ_WRITE );
|
||||
this.myPartitionList = new DefaultPriorityList<>();
|
||||
}
|
||||
IncludeExclude getWhitelist() {
|
||||
return this.myWhitelist;
|
||||
}
|
||||
|
||||
IncludeExclude getWhitelist()
|
||||
{
|
||||
return this.myWhitelist;
|
||||
}
|
||||
public void setWhitelist(final IncludeExclude myWhitelist) {
|
||||
this.myWhitelist = myWhitelist;
|
||||
}
|
||||
|
||||
public void setWhitelist( final IncludeExclude myWhitelist )
|
||||
{
|
||||
this.myWhitelist = myWhitelist;
|
||||
}
|
||||
public AccessRestriction getBaseAccess() {
|
||||
return this.myAccess;
|
||||
}
|
||||
|
||||
public AccessRestriction getBaseAccess()
|
||||
{
|
||||
return this.myAccess;
|
||||
}
|
||||
public void setBaseAccess(final AccessRestriction myAccess) {
|
||||
this.myAccess = myAccess;
|
||||
this.cachedAccessRestriction = this.myAccess.restrictPermissions(this.internal.getAccess());
|
||||
this.hasReadAccess = this.cachedAccessRestriction.hasPermission(AccessRestriction.READ);
|
||||
this.hasWriteAccess = this.cachedAccessRestriction.hasPermission(AccessRestriction.WRITE);
|
||||
}
|
||||
|
||||
public void setBaseAccess( final AccessRestriction myAccess )
|
||||
{
|
||||
this.myAccess = myAccess;
|
||||
this.cachedAccessRestriction = this.myAccess.restrictPermissions( this.internal.getAccess() );
|
||||
this.hasReadAccess = this.cachedAccessRestriction.hasPermission( AccessRestriction.READ );
|
||||
this.hasWriteAccess = this.cachedAccessRestriction.hasPermission( AccessRestriction.WRITE );
|
||||
}
|
||||
IPartitionList<T> getPartitionList() {
|
||||
return this.myPartitionList;
|
||||
}
|
||||
|
||||
IPartitionList<T> getPartitionList()
|
||||
{
|
||||
return this.myPartitionList;
|
||||
}
|
||||
public void setPartitionList(final IPartitionList<T> myPartitionList) {
|
||||
this.myPartitionList = myPartitionList;
|
||||
}
|
||||
|
||||
public void setPartitionList( final IPartitionList<T> myPartitionList )
|
||||
{
|
||||
this.myPartitionList = myPartitionList;
|
||||
}
|
||||
@Override
|
||||
public T injectItems(final T input, final Actionable type, final IActionSource src) {
|
||||
if (!this.canAccept(input)) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems( final T input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
if( !this.canAccept( input ) )
|
||||
{
|
||||
return input;
|
||||
}
|
||||
return this.internal.injectItems(input, type, src);
|
||||
}
|
||||
|
||||
return this.internal.injectItems( input, type, src );
|
||||
}
|
||||
@Override
|
||||
public T extractItems(final T request, final Actionable type, final IActionSource src) {
|
||||
if (!this.hasReadAccess) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extractItems( final T request, final Actionable type, final IActionSource src )
|
||||
{
|
||||
if( !this.hasReadAccess )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return this.internal.extractItems(request, type, src);
|
||||
}
|
||||
|
||||
return this.internal.extractItems( request, type, src );
|
||||
}
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems(final IItemList<T> out) {
|
||||
if (!this.hasReadAccess) {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems( final IItemList<T> out )
|
||||
{
|
||||
if( !this.hasReadAccess )
|
||||
{
|
||||
return out;
|
||||
}
|
||||
return this.internal.getAvailableItems(out);
|
||||
}
|
||||
|
||||
return this.internal.getAvailableItems( out );
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel<T> getChannel() {
|
||||
return this.internal.getChannel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel<T> getChannel()
|
||||
{
|
||||
return this.internal.getChannel();
|
||||
}
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return this.cachedAccessRestriction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return this.cachedAccessRestriction;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrioritized(final T input) {
|
||||
if (this.myWhitelist == IncludeExclude.WHITELIST) {
|
||||
return this.myPartitionList.isListed(input) || this.internal.isPrioritized(input);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final T input )
|
||||
{
|
||||
if( this.myWhitelist == IncludeExclude.WHITELIST )
|
||||
{
|
||||
return this.myPartitionList.isListed( input ) || this.internal.isPrioritized( input );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canAccept(final T input) {
|
||||
if (!this.hasWriteAccess) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final T input )
|
||||
{
|
||||
if( !this.hasWriteAccess )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.myWhitelist == IncludeExclude.BLACKLIST && this.myPartitionList.isListed(input)) {
|
||||
return false;
|
||||
}
|
||||
if (this.myPartitionList.isEmpty() || this.myWhitelist == IncludeExclude.BLACKLIST) {
|
||||
return this.internal.canAccept(input);
|
||||
}
|
||||
return this.myPartitionList.isListed(input) && this.internal.canAccept(input);
|
||||
}
|
||||
|
||||
if( this.myWhitelist == IncludeExclude.BLACKLIST && this.myPartitionList.isListed( input ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( this.myPartitionList.isEmpty() || this.myWhitelist == IncludeExclude.BLACKLIST )
|
||||
{
|
||||
return this.internal.canAccept( input );
|
||||
}
|
||||
return this.myPartitionList.isListed( input ) && this.internal.canAccept( input );
|
||||
}
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return this.myPriority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return this.myPriority;
|
||||
}
|
||||
public void setPriority(final int myPriority) {
|
||||
this.myPriority = myPriority;
|
||||
}
|
||||
|
||||
public void setPriority( final int myPriority )
|
||||
{
|
||||
this.myPriority = myPriority;
|
||||
}
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return this.internal.getSlot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return this.internal.getSlot();
|
||||
}
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public IMEInventory<T> getInternal()
|
||||
{
|
||||
return this.internal;
|
||||
}
|
||||
public IMEInventory<T> getInternal() {
|
||||
return this.internal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@@ -44,315 +43,262 @@ import appeng.api.storage.channels.IFluidStorageChannel;
|
||||
import appeng.api.storage.data.IAEFluidStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
|
||||
public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITickingMonitor {
|
||||
private final IFluidHandler handler;
|
||||
private final IItemList<IAEFluidStack> list = AEApi.instance().storage()
|
||||
.getStorageChannel(IFluidStorageChannel.class).createList();
|
||||
private final HashMap<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> listeners = new HashMap<>();
|
||||
private final NavigableMap<Integer, CachedFluidStack> memory;
|
||||
private IActionSource mySource;
|
||||
private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY;
|
||||
|
||||
public class MEMonitorIFluidHandler implements IMEMonitor<IAEFluidStack>, ITickingMonitor
|
||||
{
|
||||
private final IFluidHandler handler;
|
||||
private final IItemList<IAEFluidStack> list = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createList();
|
||||
private final HashMap<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> listeners = new HashMap<>();
|
||||
private final NavigableMap<Integer, CachedFluidStack> memory;
|
||||
private IActionSource mySource;
|
||||
private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY;
|
||||
public MEMonitorIFluidHandler(final IFluidHandler handler) {
|
||||
this.handler = handler;
|
||||
this.memory = new ConcurrentSkipListMap<>();
|
||||
}
|
||||
|
||||
public MEMonitorIFluidHandler( final IFluidHandler handler )
|
||||
{
|
||||
this.handler = handler;
|
||||
this.memory = new ConcurrentSkipListMap<>();
|
||||
}
|
||||
@Override
|
||||
public void addListener(final IMEMonitorHandlerReceiver<IAEFluidStack> l, final Object verificationToken) {
|
||||
this.listeners.put(l, verificationToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener( final IMEMonitorHandlerReceiver<IAEFluidStack> l, final Object verificationToken )
|
||||
{
|
||||
this.listeners.put( l, verificationToken );
|
||||
}
|
||||
@Override
|
||||
public void removeListener(final IMEMonitorHandlerReceiver<IAEFluidStack> l) {
|
||||
this.listeners.remove(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener( final IMEMonitorHandlerReceiver<IAEFluidStack> l )
|
||||
{
|
||||
this.listeners.remove( l );
|
||||
}
|
||||
@Override
|
||||
public IAEFluidStack injectItems(final IAEFluidStack input, final Actionable type, final IActionSource src) {
|
||||
final int filled = this.handler.fill(input.getFluidStack(), type.getFluidAction());
|
||||
|
||||
@Override
|
||||
public IAEFluidStack injectItems( final IAEFluidStack input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
final int filled = this.handler.fill( input.getFluidStack(), type.getFluidAction() );
|
||||
if (filled == 0) {
|
||||
return input.copy();
|
||||
}
|
||||
|
||||
if( filled == 0 )
|
||||
{
|
||||
return input.copy();
|
||||
}
|
||||
if (type == Actionable.MODULATE) {
|
||||
this.onTick();
|
||||
}
|
||||
|
||||
if( type == Actionable.MODULATE )
|
||||
{
|
||||
this.onTick();
|
||||
}
|
||||
if (filled == input.getStackSize()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if( filled == input.getStackSize() )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final IAEFluidStack o = input.copy();
|
||||
o.setStackSize(input.getStackSize() - filled);
|
||||
return o;
|
||||
}
|
||||
|
||||
final IAEFluidStack o = input.copy();
|
||||
o.setStackSize( input.getStackSize() - filled );
|
||||
return o;
|
||||
}
|
||||
@Override
|
||||
public IAEFluidStack extractItems(final IAEFluidStack request, final Actionable type, final IActionSource src) {
|
||||
final FluidStack removed = this.handler.drain(request.getFluidStack(), type.getFluidAction());
|
||||
|
||||
@Override
|
||||
public IAEFluidStack extractItems( final IAEFluidStack request, final Actionable type, final IActionSource src )
|
||||
{
|
||||
final FluidStack removed = this.handler.drain( request.getFluidStack(), type.getFluidAction() );
|
||||
if (removed == null || removed.getAmount() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if( removed == null || removed.getAmount() == 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (type == Actionable.MODULATE) {
|
||||
this.onTick();
|
||||
}
|
||||
|
||||
if( type == Actionable.MODULATE )
|
||||
{
|
||||
this.onTick();
|
||||
}
|
||||
final IAEFluidStack o = request.copy();
|
||||
o.setStackSize(removed.getAmount());
|
||||
return o;
|
||||
}
|
||||
|
||||
final IAEFluidStack o = request.copy();
|
||||
o.setStackSize( removed.getAmount() );
|
||||
return o;
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel getChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel getChannel()
|
||||
{
|
||||
return AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class );
|
||||
}
|
||||
@Override
|
||||
public TickRateModulation onTick() {
|
||||
final List<IAEFluidStack> changes = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public TickRateModulation onTick()
|
||||
{
|
||||
final List<IAEFluidStack> changes = new ArrayList<>();
|
||||
this.list.resetStatus();
|
||||
int high = 0;
|
||||
boolean changed = false;
|
||||
|
||||
this.list.resetStatus();
|
||||
int high = 0;
|
||||
boolean changed = false;
|
||||
int tankCount = this.handler.getTanks();
|
||||
for (int tank = 0; tank < tankCount; ++tank) {
|
||||
final CachedFluidStack old = this.memory.get(tank);
|
||||
high = Math.max(high, tank);
|
||||
|
||||
int tankCount = this.handler.getTanks();
|
||||
for( int tank = 0; tank < tankCount; ++tank )
|
||||
{
|
||||
final CachedFluidStack old = this.memory.get( tank );
|
||||
high = Math.max( high, tank );
|
||||
FluidStack newIS = this.handler.getFluidInTank(tank);
|
||||
if (!newIS.isEmpty() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY) {
|
||||
// We have to actually check if we could extract _anything_
|
||||
if (this.handler.drain(1, IFluidHandler.FluidAction.SIMULATE).isEmpty()) {
|
||||
// Just to safeguard against tanks that prevent non-bucket-size extractions
|
||||
if (this.handler.drain(FluidAttributes.BUCKET_VOLUME, IFluidHandler.FluidAction.SIMULATE)
|
||||
.isEmpty()) {
|
||||
newIS = FluidStack.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
final FluidStack oldIS = old == null ? FluidStack.EMPTY : old.fluidStack;
|
||||
|
||||
FluidStack newIS = this.handler.getFluidInTank(tank);
|
||||
if (!newIS.isEmpty() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY) {
|
||||
// We have to actually check if we could extract _anything_
|
||||
if (this.handler.drain(1, IFluidHandler.FluidAction.SIMULATE).isEmpty()) {
|
||||
// Just to safeguard against tanks that prevent non-bucket-size extractions
|
||||
if (this.handler.drain(FluidAttributes.BUCKET_VOLUME, IFluidHandler.FluidAction.SIMULATE).isEmpty()) {
|
||||
newIS = FluidStack.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
final FluidStack oldIS = old == null ? FluidStack.EMPTY : old.fluidStack;
|
||||
if (isDifferent(newIS, oldIS)) {
|
||||
final CachedFluidStack cis = new CachedFluidStack(newIS);
|
||||
this.memory.put(tank, cis);
|
||||
|
||||
if( isDifferent( newIS, oldIS ) )
|
||||
{
|
||||
final CachedFluidStack cis = new CachedFluidStack( newIS );
|
||||
this.memory.put( tank, cis );
|
||||
if (old != null && old.aeStack != null) {
|
||||
old.aeStack.setStackSize(-old.aeStack.getStackSize());
|
||||
changes.add(old.aeStack);
|
||||
}
|
||||
|
||||
if( old != null && old.aeStack != null )
|
||||
{
|
||||
old.aeStack.setStackSize( -old.aeStack.getStackSize() );
|
||||
changes.add( old.aeStack );
|
||||
}
|
||||
if (cis.aeStack != null) {
|
||||
changes.add(cis.aeStack);
|
||||
this.list.add(cis.aeStack);
|
||||
}
|
||||
|
||||
if( cis.aeStack != null )
|
||||
{
|
||||
changes.add( cis.aeStack );
|
||||
this.list.add( cis.aeStack );
|
||||
}
|
||||
changed = true;
|
||||
} else {
|
||||
final int newSize = newIS.isEmpty() ? 0 : newIS.getAmount();
|
||||
final int diff = newSize - (oldIS.isEmpty() ? 0 : oldIS.getAmount());
|
||||
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
final int newSize = newIS.isEmpty() ? 0 : newIS.getAmount();
|
||||
final int diff = newSize - ( oldIS.isEmpty() ? 0 : oldIS.getAmount() );
|
||||
IAEFluidStack stack = null;
|
||||
|
||||
IAEFluidStack stack = null;
|
||||
if (!newIS.isEmpty()) {
|
||||
stack = (old == null || old.aeStack == null ? AEApi.instance().storage()
|
||||
.getStorageChannel(IFluidStorageChannel.class).createStack(newIS) : old.aeStack.copy());
|
||||
}
|
||||
if (stack != null) {
|
||||
stack.setStackSize(newSize);
|
||||
this.list.add(stack);
|
||||
}
|
||||
|
||||
if( !newIS.isEmpty() )
|
||||
{
|
||||
stack = ( old == null || old.aeStack == null ? AEApi.instance()
|
||||
.storage()
|
||||
.getStorageChannel( IFluidStorageChannel.class )
|
||||
.createStack( newIS ) : old.aeStack.copy() );
|
||||
}
|
||||
if( stack != null )
|
||||
{
|
||||
stack.setStackSize( newSize );
|
||||
this.list.add( stack );
|
||||
}
|
||||
if (diff != 0 && stack != null) {
|
||||
final CachedFluidStack cis = new CachedFluidStack(newIS);
|
||||
this.memory.put(tank, cis);
|
||||
|
||||
if( diff != 0 && stack != null )
|
||||
{
|
||||
final CachedFluidStack cis = new CachedFluidStack( newIS );
|
||||
this.memory.put( tank, cis );
|
||||
final IAEFluidStack a = stack.copy();
|
||||
a.setStackSize(diff);
|
||||
changes.add(a);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final IAEFluidStack a = stack.copy();
|
||||
a.setStackSize( diff );
|
||||
changes.add( a );
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// detect dropped items; should fix non IISided Inventory Changes.
|
||||
final NavigableMap<Integer, CachedFluidStack> end = this.memory.tailMap(high, false);
|
||||
if (!end.isEmpty()) {
|
||||
for (final CachedFluidStack cis : end.values()) {
|
||||
if (cis != null && cis.aeStack != null) {
|
||||
final IAEFluidStack a = cis.aeStack.copy();
|
||||
a.setStackSize(-a.getStackSize());
|
||||
changes.add(a);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
end.clear();
|
||||
}
|
||||
|
||||
// detect dropped items; should fix non IISided Inventory Changes.
|
||||
final NavigableMap<Integer, CachedFluidStack> end = this.memory.tailMap( high, false );
|
||||
if( !end.isEmpty() )
|
||||
{
|
||||
for( final CachedFluidStack cis : end.values() )
|
||||
{
|
||||
if( cis != null && cis.aeStack != null )
|
||||
{
|
||||
final IAEFluidStack a = cis.aeStack.copy();
|
||||
a.setStackSize( -a.getStackSize() );
|
||||
changes.add( a );
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
end.clear();
|
||||
}
|
||||
if (!changes.isEmpty()) {
|
||||
this.postDifference(changes);
|
||||
}
|
||||
|
||||
if( !changes.isEmpty() )
|
||||
{
|
||||
this.postDifference( changes );
|
||||
}
|
||||
return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
|
||||
}
|
||||
|
||||
return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
|
||||
}
|
||||
private static boolean isDifferent(FluidStack a, FluidStack b) {
|
||||
if (a == b) {
|
||||
return false;
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return true;
|
||||
}
|
||||
return !a.getFluid().equals(b.getFluid());
|
||||
}
|
||||
|
||||
private static boolean isDifferent( FluidStack a, FluidStack b )
|
||||
{
|
||||
if( a == b )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( a == null || b == null )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return !a.getFluid().equals( b.getFluid() );
|
||||
}
|
||||
private void postDifference(final Iterable<IAEFluidStack> a) {
|
||||
if (a != null) {
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object>> i = this.listeners.entrySet()
|
||||
.iterator();
|
||||
while (i.hasNext()) {
|
||||
final Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> l = i.next();
|
||||
final IMEMonitorHandlerReceiver<IAEFluidStack> key = l.getKey();
|
||||
if (key.isValid(l.getValue())) {
|
||||
key.postChange(this, a, this.getActionSource());
|
||||
} else {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void postDifference( final Iterable<IAEFluidStack> a )
|
||||
{
|
||||
if( a != null )
|
||||
{
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object>> i = this.listeners.entrySet().iterator();
|
||||
while( i.hasNext() )
|
||||
{
|
||||
final Entry<IMEMonitorHandlerReceiver<IAEFluidStack>, Object> l = i.next();
|
||||
final IMEMonitorHandlerReceiver<IAEFluidStack> key = l.getKey();
|
||||
if( key.isValid( l.getValue() ) )
|
||||
{
|
||||
key.postChange( this, a, this.getActionSource() );
|
||||
}
|
||||
else
|
||||
{
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrioritized(final IAEFluidStack input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final IAEFluidStack input )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canAccept(final IAEFluidStack input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final IAEFluidStack input )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public IItemList<IAEFluidStack> getAvailableItems(final IItemList out) {
|
||||
for (final CachedFluidStack is : this.memory.values()) {
|
||||
out.addStorage(is.aeStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEFluidStack> getAvailableItems( final IItemList out )
|
||||
{
|
||||
for( final CachedFluidStack is : this.memory.values() )
|
||||
{
|
||||
out.addStorage( is.aeStack );
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
@Override
|
||||
public IItemList<IAEFluidStack> getStorageList() {
|
||||
return this.list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEFluidStack> getStorageList()
|
||||
{
|
||||
return this.list;
|
||||
}
|
||||
private StorageFilter getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
private StorageFilter getMode()
|
||||
{
|
||||
return this.mode;
|
||||
}
|
||||
public void setMode(final StorageFilter mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public void setMode( final StorageFilter mode )
|
||||
{
|
||||
this.mode = mode;
|
||||
}
|
||||
private IActionSource getActionSource() {
|
||||
return this.mySource;
|
||||
}
|
||||
|
||||
private IActionSource getActionSource()
|
||||
{
|
||||
return this.mySource;
|
||||
}
|
||||
@Override
|
||||
public void setActionSource(final IActionSource mySource) {
|
||||
this.mySource = mySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionSource( final IActionSource mySource )
|
||||
{
|
||||
this.mySource = mySource;
|
||||
}
|
||||
private static class CachedFluidStack {
|
||||
|
||||
private static class CachedFluidStack
|
||||
{
|
||||
private final FluidStack fluidStack;
|
||||
private final IAEFluidStack aeStack;
|
||||
|
||||
private final FluidStack fluidStack;
|
||||
private final IAEFluidStack aeStack;
|
||||
|
||||
CachedFluidStack( final FluidStack is )
|
||||
{
|
||||
if( is == null )
|
||||
{
|
||||
this.fluidStack = null;
|
||||
this.aeStack = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fluidStack = is.copy();
|
||||
this.aeStack = AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ).createStack( is );
|
||||
}
|
||||
}
|
||||
}
|
||||
CachedFluidStack(final FluidStack is) {
|
||||
if (is == null) {
|
||||
this.fluidStack = null;
|
||||
this.aeStack = null;
|
||||
} else {
|
||||
this.fluidStack = is.copy();
|
||||
this.aeStack = AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class).createStack(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@@ -45,320 +44,266 @@ import appeng.util.InventoryAdaptor;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.ItemSlot;
|
||||
|
||||
public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMonitor {
|
||||
|
||||
public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMonitor
|
||||
{
|
||||
private final InventoryAdaptor adaptor;
|
||||
private final IItemList<IAEItemStack> list = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)
|
||||
.createList();
|
||||
private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
|
||||
private final NavigableMap<Integer, CachedItemStack> memory;
|
||||
private IActionSource mySource;
|
||||
private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY;
|
||||
|
||||
private final InventoryAdaptor adaptor;
|
||||
private final IItemList<IAEItemStack> list = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
|
||||
private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
|
||||
private final NavigableMap<Integer, CachedItemStack> memory;
|
||||
private IActionSource mySource;
|
||||
private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY;
|
||||
public MEMonitorIInventory(final InventoryAdaptor adaptor) {
|
||||
this.adaptor = adaptor;
|
||||
this.memory = new ConcurrentSkipListMap<>();
|
||||
}
|
||||
|
||||
public MEMonitorIInventory( final InventoryAdaptor adaptor )
|
||||
{
|
||||
this.adaptor = adaptor;
|
||||
this.memory = new ConcurrentSkipListMap<>();
|
||||
}
|
||||
@Override
|
||||
public void addListener(final IMEMonitorHandlerReceiver<IAEItemStack> l, final Object verificationToken) {
|
||||
this.listeners.put(l, verificationToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener( final IMEMonitorHandlerReceiver<IAEItemStack> l, final Object verificationToken )
|
||||
{
|
||||
this.listeners.put( l, verificationToken );
|
||||
}
|
||||
@Override
|
||||
public void removeListener(final IMEMonitorHandlerReceiver<IAEItemStack> l) {
|
||||
this.listeners.remove(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener( final IMEMonitorHandlerReceiver<IAEItemStack> l )
|
||||
{
|
||||
this.listeners.remove( l );
|
||||
}
|
||||
@Override
|
||||
public IAEItemStack injectItems(final IAEItemStack input, final Actionable type, final IActionSource src) {
|
||||
ItemStack out = ItemStack.EMPTY;
|
||||
|
||||
@Override
|
||||
public IAEItemStack injectItems( final IAEItemStack input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
ItemStack out = ItemStack.EMPTY;
|
||||
if (type == Actionable.SIMULATE) {
|
||||
out = this.adaptor.simulateAdd(input.createItemStack());
|
||||
} else {
|
||||
out = this.adaptor.addItems(input.createItemStack());
|
||||
}
|
||||
|
||||
if( type == Actionable.SIMULATE )
|
||||
{
|
||||
out = this.adaptor.simulateAdd( input.createItemStack() );
|
||||
}
|
||||
else
|
||||
{
|
||||
out = this.adaptor.addItems( input.createItemStack() );
|
||||
}
|
||||
if (type == Actionable.MODULATE) {
|
||||
this.onTick();
|
||||
}
|
||||
|
||||
if( type == Actionable.MODULATE )
|
||||
{
|
||||
this.onTick();
|
||||
}
|
||||
if (out.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if( out.isEmpty() )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// better then doing construction from scratch :3
|
||||
final IAEItemStack o = input.copy();
|
||||
o.setStackSize(out.getCount());
|
||||
return o;
|
||||
}
|
||||
|
||||
// better then doing construction from scratch :3
|
||||
final IAEItemStack o = input.copy();
|
||||
o.setStackSize( out.getCount() );
|
||||
return o;
|
||||
}
|
||||
@Override
|
||||
public IAEItemStack extractItems(final IAEItemStack request, final Actionable type, final IActionSource src) {
|
||||
ItemStack out = ItemStack.EMPTY;
|
||||
|
||||
@Override
|
||||
public IAEItemStack extractItems( final IAEItemStack request, final Actionable type, final IActionSource src )
|
||||
{
|
||||
ItemStack out = ItemStack.EMPTY;
|
||||
if (type == Actionable.SIMULATE) {
|
||||
out = this.adaptor.simulateRemove((int) request.getStackSize(), request.getDefinition(), null);
|
||||
} else {
|
||||
out = this.adaptor.removeItems((int) request.getStackSize(), request.getDefinition(), null);
|
||||
}
|
||||
|
||||
if( type == Actionable.SIMULATE )
|
||||
{
|
||||
out = this.adaptor.simulateRemove( (int) request.getStackSize(), request.getDefinition(), null );
|
||||
}
|
||||
else
|
||||
{
|
||||
out = this.adaptor.removeItems( (int) request.getStackSize(), request.getDefinition(), null );
|
||||
}
|
||||
if (out.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if( out.isEmpty() )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// better then doing construction from scratch :3
|
||||
final IAEItemStack o = request.copy();
|
||||
o.setStackSize(out.getCount());
|
||||
|
||||
// better then doing construction from scratch :3
|
||||
final IAEItemStack o = request.copy();
|
||||
o.setStackSize( out.getCount() );
|
||||
if (type == Actionable.MODULATE) {
|
||||
this.onTick();
|
||||
}
|
||||
|
||||
if( type == Actionable.MODULATE )
|
||||
{
|
||||
this.onTick();
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel getChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel getChannel()
|
||||
{
|
||||
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
|
||||
}
|
||||
@Override
|
||||
public TickRateModulation onTick() {
|
||||
|
||||
@Override
|
||||
public TickRateModulation onTick()
|
||||
{
|
||||
final List<IAEItemStack> changes = new ArrayList<>();
|
||||
|
||||
final List<IAEItemStack> changes = new ArrayList<>();
|
||||
this.list.resetStatus();
|
||||
int high = 0;
|
||||
boolean changed = false;
|
||||
for (final ItemSlot is : this.adaptor) {
|
||||
final CachedItemStack old = this.memory.get(is.getSlot());
|
||||
high = Math.max(high, is.getSlot());
|
||||
|
||||
this.list.resetStatus();
|
||||
int high = 0;
|
||||
boolean changed = false;
|
||||
for( final ItemSlot is : this.adaptor )
|
||||
{
|
||||
final CachedItemStack old = this.memory.get( is.getSlot() );
|
||||
high = Math.max( high, is.getSlot() );
|
||||
final ItemStack newIS = !is.isExtractable() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY
|
||||
? ItemStack.EMPTY
|
||||
: is.getItemStack();
|
||||
final ItemStack oldIS = old == null ? ItemStack.EMPTY : old.itemStack;
|
||||
|
||||
final ItemStack newIS = !is.isExtractable() && this.getMode() == StorageFilter.EXTRACTABLE_ONLY ? ItemStack.EMPTY : is.getItemStack();
|
||||
final ItemStack oldIS = old == null ? ItemStack.EMPTY : old.itemStack;
|
||||
if (this.isDifferent(newIS, oldIS)) {
|
||||
final CachedItemStack cis = new CachedItemStack(is.getItemStack());
|
||||
this.memory.put(is.getSlot(), cis);
|
||||
|
||||
if( this.isDifferent( newIS, oldIS ) )
|
||||
{
|
||||
final CachedItemStack cis = new CachedItemStack( is.getItemStack() );
|
||||
this.memory.put( is.getSlot(), cis );
|
||||
if (old != null && old.aeStack != null) {
|
||||
old.aeStack.setStackSize(-old.aeStack.getStackSize());
|
||||
changes.add(old.aeStack);
|
||||
}
|
||||
|
||||
if( old != null && old.aeStack != null )
|
||||
{
|
||||
old.aeStack.setStackSize( -old.aeStack.getStackSize() );
|
||||
changes.add( old.aeStack );
|
||||
}
|
||||
if (cis.aeStack != null) {
|
||||
changes.add(cis.aeStack);
|
||||
this.list.add(cis.aeStack);
|
||||
}
|
||||
|
||||
if( cis.aeStack != null )
|
||||
{
|
||||
changes.add( cis.aeStack );
|
||||
this.list.add( cis.aeStack );
|
||||
}
|
||||
changed = true;
|
||||
} else {
|
||||
final int newSize = (newIS.isEmpty() ? 0 : newIS.getCount());
|
||||
final int diff = newSize - (oldIS.isEmpty() ? 0 : oldIS.getCount());
|
||||
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
final int newSize = ( newIS.isEmpty() ? 0 : newIS.getCount() );
|
||||
final int diff = newSize - ( oldIS.isEmpty() ? 0 : oldIS.getCount() );
|
||||
final IAEItemStack stack = (old == null || old.aeStack == null
|
||||
? AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(newIS)
|
||||
: old.aeStack.copy());
|
||||
if (stack != null) {
|
||||
stack.setStackSize(newSize);
|
||||
this.list.add(stack);
|
||||
}
|
||||
|
||||
final IAEItemStack stack = ( old == null || old.aeStack == null ? AEApi.instance()
|
||||
.storage()
|
||||
.getStorageChannel( IItemStorageChannel.class )
|
||||
.createStack( newIS ) : old.aeStack.copy() );
|
||||
if( stack != null )
|
||||
{
|
||||
stack.setStackSize( newSize );
|
||||
this.list.add( stack );
|
||||
}
|
||||
if (diff != 0 && stack != null) {
|
||||
final CachedItemStack cis = new CachedItemStack(is.getItemStack());
|
||||
this.memory.put(is.getSlot(), cis);
|
||||
|
||||
if( diff != 0 && stack != null )
|
||||
{
|
||||
final CachedItemStack cis = new CachedItemStack( is.getItemStack() );
|
||||
this.memory.put( is.getSlot(), cis );
|
||||
final IAEItemStack a = stack.copy();
|
||||
a.setStackSize(diff);
|
||||
changes.add(a);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final IAEItemStack a = stack.copy();
|
||||
a.setStackSize( diff );
|
||||
changes.add( a );
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// detect dropped items; should fix non IISided Inventory Changes.
|
||||
final NavigableMap<Integer, CachedItemStack> end = this.memory.tailMap(high, false);
|
||||
if (!end.isEmpty()) {
|
||||
for (final CachedItemStack cis : end.values()) {
|
||||
if (cis != null && cis.aeStack != null) {
|
||||
final IAEItemStack a = cis.aeStack.copy();
|
||||
a.setStackSize(-a.getStackSize());
|
||||
changes.add(a);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
end.clear();
|
||||
}
|
||||
|
||||
// detect dropped items; should fix non IISided Inventory Changes.
|
||||
final NavigableMap<Integer, CachedItemStack> end = this.memory.tailMap( high, false );
|
||||
if( !end.isEmpty() )
|
||||
{
|
||||
for( final CachedItemStack cis : end.values() )
|
||||
{
|
||||
if( cis != null && cis.aeStack != null )
|
||||
{
|
||||
final IAEItemStack a = cis.aeStack.copy();
|
||||
a.setStackSize( -a.getStackSize() );
|
||||
changes.add( a );
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
end.clear();
|
||||
}
|
||||
if (!changes.isEmpty()) {
|
||||
this.postDifference(changes);
|
||||
}
|
||||
|
||||
if( !changes.isEmpty() )
|
||||
{
|
||||
this.postDifference( changes );
|
||||
}
|
||||
return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
|
||||
}
|
||||
|
||||
return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
|
||||
}
|
||||
private boolean isDifferent(final ItemStack a, final ItemStack b) {
|
||||
if (a == b && b.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isDifferent( final ItemStack a, final ItemStack b )
|
||||
{
|
||||
if( a == b && b.isEmpty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((a.isEmpty() && !b.isEmpty()) || (!a.isEmpty() && b.isEmpty())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if( ( a.isEmpty() && !b.isEmpty() ) || ( !a.isEmpty() && b.isEmpty() ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return !Platform.itemComparisons().isSameItem(a, b);
|
||||
}
|
||||
|
||||
return !Platform.itemComparisons().isSameItem( a, b );
|
||||
}
|
||||
private void postDifference(final Iterable<IAEItemStack> a) {
|
||||
// AELog.info( a.getItemStack().getTranslationKey() + " @ " + a.getStackSize()
|
||||
// );
|
||||
if (a != null) {
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet()
|
||||
.iterator();
|
||||
while (i.hasNext()) {
|
||||
final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
|
||||
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
|
||||
if (key.isValid(l.getValue())) {
|
||||
key.postChange(this, a, this.getActionSource());
|
||||
} else {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void postDifference( final Iterable<IAEItemStack> a )
|
||||
{
|
||||
// AELog.info( a.getItemStack().getTranslationKey() + " @ " + a.getStackSize() );
|
||||
if( a != null )
|
||||
{
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
|
||||
while( i.hasNext() )
|
||||
{
|
||||
final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
|
||||
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
|
||||
if( key.isValid( l.getValue() ) )
|
||||
{
|
||||
key.postChange( this, a, this.getActionSource() );
|
||||
}
|
||||
else
|
||||
{
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrioritized(final IAEItemStack input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final IAEItemStack input )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canAccept(final IAEItemStack input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final IAEItemStack input )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getAvailableItems(final IItemList out) {
|
||||
for (final CachedItemStack is : this.memory.values()) {
|
||||
out.addStorage(is.aeStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getAvailableItems( final IItemList out )
|
||||
{
|
||||
for( final CachedItemStack is : this.memory.values() )
|
||||
{
|
||||
out.addStorage( is.aeStack );
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getStorageList() {
|
||||
return this.list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getStorageList()
|
||||
{
|
||||
return this.list;
|
||||
}
|
||||
private StorageFilter getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
private StorageFilter getMode()
|
||||
{
|
||||
return this.mode;
|
||||
}
|
||||
public void setMode(final StorageFilter mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public void setMode( final StorageFilter mode )
|
||||
{
|
||||
this.mode = mode;
|
||||
}
|
||||
private IActionSource getActionSource() {
|
||||
return this.mySource;
|
||||
}
|
||||
|
||||
private IActionSource getActionSource()
|
||||
{
|
||||
return this.mySource;
|
||||
}
|
||||
@Override
|
||||
public void setActionSource(final IActionSource mySource) {
|
||||
this.mySource = mySource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionSource( final IActionSource mySource )
|
||||
{
|
||||
this.mySource = mySource;
|
||||
}
|
||||
private static class CachedItemStack {
|
||||
|
||||
private static class CachedItemStack
|
||||
{
|
||||
private final ItemStack itemStack;
|
||||
private final IAEItemStack aeStack;
|
||||
|
||||
private final ItemStack itemStack;
|
||||
private final IAEItemStack aeStack;
|
||||
|
||||
public CachedItemStack( final ItemStack is )
|
||||
{
|
||||
if( is.isEmpty() )
|
||||
{
|
||||
this.itemStack = ItemStack.EMPTY;
|
||||
this.aeStack = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.itemStack = is.copy();
|
||||
this.aeStack = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( is );
|
||||
}
|
||||
}
|
||||
}
|
||||
public CachedItemStack(final ItemStack is) {
|
||||
if (is.isEmpty()) {
|
||||
this.itemStack = ItemStack.EMPTY;
|
||||
this.aeStack = null;
|
||||
} else {
|
||||
this.itemStack = is.copy();
|
||||
this.aeStack = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
@@ -34,134 +33,111 @@ import appeng.api.storage.data.IItemList;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.inv.ItemListIgnoreCrafting;
|
||||
|
||||
public class MEMonitorPassThrough<T extends IAEStack<T>> extends MEPassThrough<T>
|
||||
implements IMEMonitor<T>, IMEMonitorHandlerReceiver<T> {
|
||||
|
||||
public class MEMonitorPassThrough<T extends IAEStack<T>> extends MEPassThrough<T> implements IMEMonitor<T>, IMEMonitorHandlerReceiver<T>
|
||||
{
|
||||
private final HashMap<IMEMonitorHandlerReceiver<T>, Object> listeners = new HashMap<>();
|
||||
private IActionSource changeSource;
|
||||
private IMEMonitor<T> monitor;
|
||||
|
||||
private final HashMap<IMEMonitorHandlerReceiver<T>, Object> listeners = new HashMap<>();
|
||||
private IActionSource changeSource;
|
||||
private IMEMonitor<T> monitor;
|
||||
public MEMonitorPassThrough(final IMEInventory<T> i, final IStorageChannel channel) {
|
||||
super(i, channel);
|
||||
if (i instanceof IMEMonitor) {
|
||||
this.monitor = (IMEMonitor<T>) i;
|
||||
}
|
||||
}
|
||||
|
||||
public MEMonitorPassThrough( final IMEInventory<T> i, final IStorageChannel channel )
|
||||
{
|
||||
super( i, channel );
|
||||
if( i instanceof IMEMonitor )
|
||||
{
|
||||
this.monitor = (IMEMonitor<T>) i;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void setInternal(final IMEInventory<T> i) {
|
||||
if (this.monitor != null) {
|
||||
this.monitor.removeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInternal( final IMEInventory<T> i )
|
||||
{
|
||||
if( this.monitor != null )
|
||||
{
|
||||
this.monitor.removeListener( this );
|
||||
}
|
||||
this.monitor = null;
|
||||
final IItemList<T> before = this.getInternal() == null ? this.getWrappedChannel().createList()
|
||||
: this.getInternal()
|
||||
.getAvailableItems(new ItemListIgnoreCrafting(this.getWrappedChannel().createList()));
|
||||
|
||||
this.monitor = null;
|
||||
final IItemList<T> before = this.getInternal() == null ? this.getWrappedChannel().createList() : this.getInternal()
|
||||
.getAvailableItems( new ItemListIgnoreCrafting( this.getWrappedChannel().createList() ) );
|
||||
super.setInternal(i);
|
||||
if (i instanceof IMEMonitor) {
|
||||
this.monitor = (IMEMonitor<T>) i;
|
||||
}
|
||||
|
||||
super.setInternal( i );
|
||||
if( i instanceof IMEMonitor )
|
||||
{
|
||||
this.monitor = (IMEMonitor<T>) i;
|
||||
}
|
||||
final IItemList<T> after = this.getInternal() == null ? this.getWrappedChannel().createList()
|
||||
: this.getInternal()
|
||||
.getAvailableItems(new ItemListIgnoreCrafting(this.getWrappedChannel().createList()));
|
||||
|
||||
final IItemList<T> after = this.getInternal() == null ? this.getWrappedChannel().createList() : this.getInternal()
|
||||
.getAvailableItems( new ItemListIgnoreCrafting( this.getWrappedChannel().createList() ) );
|
||||
if (this.monitor != null) {
|
||||
this.monitor.addListener(this, this.monitor);
|
||||
}
|
||||
|
||||
if( this.monitor != null )
|
||||
{
|
||||
this.monitor.addListener( this, this.monitor );
|
||||
}
|
||||
Platform.postListChanges(before, after, this, this.getChangeSource());
|
||||
}
|
||||
|
||||
Platform.postListChanges( before, after, this, this.getChangeSource() );
|
||||
}
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems(final IItemList out) {
|
||||
super.getAvailableItems(new ItemListIgnoreCrafting(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems( final IItemList out )
|
||||
{
|
||||
super.getAvailableItems( new ItemListIgnoreCrafting( out ) );
|
||||
return out;
|
||||
}
|
||||
@Override
|
||||
public void addListener(final IMEMonitorHandlerReceiver<T> l, final Object verificationToken) {
|
||||
this.listeners.put(l, verificationToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener( final IMEMonitorHandlerReceiver<T> l, final Object verificationToken )
|
||||
{
|
||||
this.listeners.put( l, verificationToken );
|
||||
}
|
||||
@Override
|
||||
public void removeListener(final IMEMonitorHandlerReceiver<T> l) {
|
||||
this.listeners.remove(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener( final IMEMonitorHandlerReceiver<T> l )
|
||||
{
|
||||
this.listeners.remove( l );
|
||||
}
|
||||
@Override
|
||||
public IItemList<T> getStorageList() {
|
||||
if (this.monitor == null) {
|
||||
final IItemList<T> out = this.getWrappedChannel().createList();
|
||||
this.getInternal().getAvailableItems(new ItemListIgnoreCrafting(out));
|
||||
return out;
|
||||
}
|
||||
return this.monitor.getStorageList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<T> getStorageList()
|
||||
{
|
||||
if( this.monitor == null )
|
||||
{
|
||||
final IItemList<T> out = this.getWrappedChannel().createList();
|
||||
this.getInternal().getAvailableItems( new ItemListIgnoreCrafting( out ) );
|
||||
return out;
|
||||
}
|
||||
return this.monitor.getStorageList();
|
||||
}
|
||||
@Override
|
||||
public boolean isValid(final Object verificationToken) {
|
||||
return verificationToken == this.monitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid( final Object verificationToken )
|
||||
{
|
||||
return verificationToken == this.monitor;
|
||||
}
|
||||
@Override
|
||||
public void postChange(final IBaseMonitor<T> monitor, final Iterable<T> change, final IActionSource source) {
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.listeners.entrySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
final Entry<IMEMonitorHandlerReceiver<T>, Object> e = i.next();
|
||||
final IMEMonitorHandlerReceiver<T> receiver = e.getKey();
|
||||
if (receiver.isValid(e.getValue())) {
|
||||
receiver.postChange(this, change, source);
|
||||
} else {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postChange( final IBaseMonitor<T> monitor, final Iterable<T> change, final IActionSource source )
|
||||
{
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.listeners.entrySet().iterator();
|
||||
while( i.hasNext() )
|
||||
{
|
||||
final Entry<IMEMonitorHandlerReceiver<T>, Object> e = i.next();
|
||||
final IMEMonitorHandlerReceiver<T> receiver = e.getKey();
|
||||
if( receiver.isValid( e.getValue() ) )
|
||||
{
|
||||
receiver.postChange( this, change, source );
|
||||
}
|
||||
else
|
||||
{
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onListUpdate() {
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.listeners.entrySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
final Entry<IMEMonitorHandlerReceiver<T>, Object> e = i.next();
|
||||
final IMEMonitorHandlerReceiver<T> receiver = e.getKey();
|
||||
if (receiver.isValid(e.getValue())) {
|
||||
receiver.onListUpdate();
|
||||
} else {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListUpdate()
|
||||
{
|
||||
final Iterator<Entry<IMEMonitorHandlerReceiver<T>, Object>> i = this.listeners.entrySet().iterator();
|
||||
while( i.hasNext() )
|
||||
{
|
||||
final Entry<IMEMonitorHandlerReceiver<T>, Object> e = i.next();
|
||||
final IMEMonitorHandlerReceiver<T> receiver = e.getKey();
|
||||
if( receiver.isValid( e.getValue() ) )
|
||||
{
|
||||
receiver.onListUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
private IActionSource getChangeSource() {
|
||||
return this.changeSource;
|
||||
}
|
||||
|
||||
private IActionSource getChangeSource()
|
||||
{
|
||||
return this.changeSource;
|
||||
}
|
||||
|
||||
public void setChangeSource( final IActionSource changeSource )
|
||||
{
|
||||
this.changeSource = changeSource;
|
||||
}
|
||||
public void setChangeSource(final IActionSource changeSource) {
|
||||
this.changeSource = changeSource;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
@@ -28,91 +27,75 @@ import appeng.api.storage.IStorageChannel;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
|
||||
public class MEPassThrough<T extends IAEStack<T>> implements IMEInventoryHandler<T> {
|
||||
|
||||
public class MEPassThrough<T extends IAEStack<T>> implements IMEInventoryHandler<T>
|
||||
{
|
||||
private final IStorageChannel wrappedChannel;
|
||||
private IMEInventory<T> internal;
|
||||
|
||||
private final IStorageChannel wrappedChannel;
|
||||
private IMEInventory<T> internal;
|
||||
public MEPassThrough(final IMEInventory<T> i, final IStorageChannel channel) {
|
||||
this.wrappedChannel = channel;
|
||||
this.setInternal(i);
|
||||
}
|
||||
|
||||
public MEPassThrough( final IMEInventory<T> i, final IStorageChannel channel )
|
||||
{
|
||||
this.wrappedChannel = channel;
|
||||
this.setInternal( i );
|
||||
}
|
||||
protected IMEInventory<T> getInternal() {
|
||||
return this.internal;
|
||||
}
|
||||
|
||||
protected IMEInventory<T> getInternal()
|
||||
{
|
||||
return this.internal;
|
||||
}
|
||||
public void setInternal(final IMEInventory<T> i) {
|
||||
this.internal = i;
|
||||
}
|
||||
|
||||
public void setInternal( final IMEInventory<T> i )
|
||||
{
|
||||
this.internal = i;
|
||||
}
|
||||
@Override
|
||||
public T injectItems(final T input, final Actionable type, final IActionSource src) {
|
||||
return this.internal.injectItems(input, type, src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems( final T input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
return this.internal.injectItems( input, type, src );
|
||||
}
|
||||
@Override
|
||||
public T extractItems(final T request, final Actionable type, final IActionSource src) {
|
||||
return this.internal.extractItems(request, type, src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extractItems( final T request, final Actionable type, final IActionSource src )
|
||||
{
|
||||
return this.internal.extractItems( request, type, src );
|
||||
}
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems(final IItemList out) {
|
||||
return this.internal.getAvailableItems(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems( final IItemList out )
|
||||
{
|
||||
return this.internal.getAvailableItems( out );
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel getChannel() {
|
||||
return this.internal.getChannel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel getChannel()
|
||||
{
|
||||
return this.internal.getChannel();
|
||||
}
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrioritized(final T input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final T input )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canAccept(final T input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final T input )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IStorageChannel getWrappedChannel()
|
||||
{
|
||||
return this.wrappedChannel;
|
||||
}
|
||||
IStorageChannel getWrappedChannel() {
|
||||
return this.wrappedChannel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@@ -41,289 +40,239 @@ import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
import appeng.me.cache.SecurityCache;
|
||||
|
||||
public class NetworkInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHandler<T> {
|
||||
|
||||
public class NetworkInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHandler<T>
|
||||
{
|
||||
private static final ThreadLocal<Deque> DEPTH_MOD = new ThreadLocal<>();
|
||||
private static final ThreadLocal<Deque> DEPTH_SIM = new ThreadLocal<>();
|
||||
private static final Comparator<Integer> PRIORITY_SORTER = (o1, o2) -> Integer.compare(o2, o1);
|
||||
|
||||
private static final ThreadLocal<Deque> DEPTH_MOD = new ThreadLocal<>();
|
||||
private static final ThreadLocal<Deque> DEPTH_SIM = new ThreadLocal<>();
|
||||
private static final Comparator<Integer> PRIORITY_SORTER = ( o1, o2 ) -> Integer.compare( o2, o1 );
|
||||
private static int currentPass = 0;
|
||||
private final IStorageChannel<T> myChannel;
|
||||
private final SecurityCache security;
|
||||
private final NavigableMap<Integer, List<IMEInventoryHandler<T>>> priorityInventory;
|
||||
private int myPass = 0;
|
||||
|
||||
private static int currentPass = 0;
|
||||
private final IStorageChannel<T> myChannel;
|
||||
private final SecurityCache security;
|
||||
private final NavigableMap<Integer, List<IMEInventoryHandler<T>>> priorityInventory;
|
||||
private int myPass = 0;
|
||||
public NetworkInventoryHandler(final IStorageChannel<T> chan, final SecurityCache security) {
|
||||
this.myChannel = chan;
|
||||
this.security = security;
|
||||
this.priorityInventory = new TreeMap<>(PRIORITY_SORTER);
|
||||
}
|
||||
|
||||
public NetworkInventoryHandler( final IStorageChannel<T> chan, final SecurityCache security )
|
||||
{
|
||||
this.myChannel = chan;
|
||||
this.security = security;
|
||||
this.priorityInventory = new TreeMap<>( PRIORITY_SORTER );
|
||||
}
|
||||
public void addNewStorage(final IMEInventoryHandler<T> h) {
|
||||
final int priority = h.getPriority();
|
||||
List<IMEInventoryHandler<T>> list = this.priorityInventory.get(priority);
|
||||
if (list == null) {
|
||||
this.priorityInventory.put(priority, list = new ArrayList<>());
|
||||
}
|
||||
|
||||
public void addNewStorage( final IMEInventoryHandler<T> h )
|
||||
{
|
||||
final int priority = h.getPriority();
|
||||
List<IMEInventoryHandler<T>> list = this.priorityInventory.get( priority );
|
||||
if( list == null )
|
||||
{
|
||||
this.priorityInventory.put( priority, list = new ArrayList<>() );
|
||||
}
|
||||
list.add(h);
|
||||
}
|
||||
|
||||
list.add( h );
|
||||
}
|
||||
@Override
|
||||
public T injectItems(T input, final Actionable type, final IActionSource src) {
|
||||
if (this.diveList(this, type)) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems( T input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
if( this.diveList( this, type ) )
|
||||
{
|
||||
return input;
|
||||
}
|
||||
if (this.testPermission(src, SecurityPermissions.INJECT)) {
|
||||
this.surface(this, type);
|
||||
return input;
|
||||
}
|
||||
|
||||
if( this.testPermission( src, SecurityPermissions.INJECT ) )
|
||||
{
|
||||
this.surface( this, type );
|
||||
return input;
|
||||
}
|
||||
for (final List<IMEInventoryHandler<T>> invList : this.priorityInventory.values()) {
|
||||
Iterator<IMEInventoryHandler<T>> ii = invList.iterator();
|
||||
while (ii.hasNext() && input != null) {
|
||||
final IMEInventoryHandler<T> inv = ii.next();
|
||||
|
||||
for( final List<IMEInventoryHandler<T>> invList : this.priorityInventory.values() )
|
||||
{
|
||||
Iterator<IMEInventoryHandler<T>> ii = invList.iterator();
|
||||
while( ii.hasNext() && input != null )
|
||||
{
|
||||
final IMEInventoryHandler<T> inv = ii.next();
|
||||
if (inv.validForPass(1) && inv.canAccept(input)
|
||||
&& (inv.isPrioritized(input) || inv.extractItems(input, Actionable.SIMULATE, src) != null)) {
|
||||
input = inv.injectItems(input, type, src);
|
||||
}
|
||||
}
|
||||
|
||||
if( inv.validForPass( 1 ) && inv
|
||||
.canAccept( input ) && ( inv.isPrioritized( input ) || inv.extractItems( input, Actionable.SIMULATE, src ) != null ) )
|
||||
{
|
||||
input = inv.injectItems( input, type, src );
|
||||
}
|
||||
}
|
||||
// We need to ignore prioritized inventories in the second pass. If they were
|
||||
// not able to store everything
|
||||
// during the first pass, they will do so in the second, but as this is
|
||||
// stateless we will just report twice
|
||||
// the amount of storable items.
|
||||
// ignores craftingcache on the second pass.
|
||||
ii = invList.iterator();
|
||||
while (ii.hasNext() && input != null) {
|
||||
final IMEInventoryHandler<T> inv = ii.next();
|
||||
|
||||
// We need to ignore prioritized inventories in the second pass. If they were not able to store everything
|
||||
// during the first pass, they will do so in the second, but as this is stateless we will just report twice
|
||||
// the amount of storable items.
|
||||
// ignores craftingcache on the second pass.
|
||||
ii = invList.iterator();
|
||||
while( ii.hasNext() && input != null )
|
||||
{
|
||||
final IMEInventoryHandler<T> inv = ii.next();
|
||||
if (inv.validForPass(2) && inv.canAccept(input) && !inv.isPrioritized(input)) {
|
||||
input = inv.injectItems(input, type, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( inv.validForPass( 2 ) && inv.canAccept( input ) && !inv.isPrioritized( input ) )
|
||||
{
|
||||
input = inv.injectItems( input, type, src );
|
||||
}
|
||||
}
|
||||
}
|
||||
this.surface(this, type);
|
||||
|
||||
this.surface( this, type );
|
||||
return input;
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
private boolean diveList(final NetworkInventoryHandler<T> networkInventoryHandler, final Actionable type) {
|
||||
final Deque cDepth = this.getDepth(type);
|
||||
if (cDepth.contains(networkInventoryHandler)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean diveList( final NetworkInventoryHandler<T> networkInventoryHandler, final Actionable type )
|
||||
{
|
||||
final Deque cDepth = this.getDepth( type );
|
||||
if( cDepth.contains( networkInventoryHandler ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
cDepth.push(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
cDepth.push( this );
|
||||
return false;
|
||||
}
|
||||
private boolean testPermission(final IActionSource src, final SecurityPermissions permission) {
|
||||
if (src.player().isPresent()) {
|
||||
if (!this.security.hasPermission(src.player().get(), permission)) {
|
||||
return true;
|
||||
}
|
||||
} else if (src.machine().isPresent()) {
|
||||
if (this.security.isAvailable()) {
|
||||
final IGridNode n = src.machine().get().getActionableNode();
|
||||
if (n == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean testPermission( final IActionSource src, final SecurityPermissions permission )
|
||||
{
|
||||
if( src.player().isPresent() )
|
||||
{
|
||||
if( !this.security.hasPermission( src.player().get(), permission ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( src.machine().isPresent() )
|
||||
{
|
||||
if( this.security.isAvailable() )
|
||||
{
|
||||
final IGridNode n = src.machine().get().getActionableNode();
|
||||
if( n == null )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
final IGrid gn = n.getGrid();
|
||||
if (gn != this.security.getGrid()) {
|
||||
|
||||
final IGrid gn = n.getGrid();
|
||||
if( gn != this.security.getGrid() )
|
||||
{
|
||||
final ISecurityGrid sg = gn.getCache(ISecurityGrid.class);
|
||||
final int playerID = sg.getOwner();
|
||||
|
||||
final ISecurityGrid sg = gn.getCache( ISecurityGrid.class );
|
||||
final int playerID = sg.getOwner();
|
||||
if (!this.security.hasPermission(playerID, permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !this.security.hasPermission( playerID, permission ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
private void surface(final NetworkInventoryHandler<T> networkInventoryHandler, final Actionable type) {
|
||||
if (this.getDepth(type).pop() != this) {
|
||||
throw new IllegalStateException("Invalid Access to Networked Storage API detected.");
|
||||
}
|
||||
}
|
||||
|
||||
private void surface( final NetworkInventoryHandler<T> networkInventoryHandler, final Actionable type )
|
||||
{
|
||||
if( this.getDepth( type ).pop() != this )
|
||||
{
|
||||
throw new IllegalStateException( "Invalid Access to Networked Storage API detected." );
|
||||
}
|
||||
}
|
||||
private Deque getDepth(final Actionable type) {
|
||||
final ThreadLocal<Deque> depth = type == Actionable.MODULATE ? DEPTH_MOD : DEPTH_SIM;
|
||||
|
||||
private Deque getDepth( final Actionable type )
|
||||
{
|
||||
final ThreadLocal<Deque> depth = type == Actionable.MODULATE ? DEPTH_MOD : DEPTH_SIM;
|
||||
Deque s = depth.get();
|
||||
|
||||
Deque s = depth.get();
|
||||
if (s == null) {
|
||||
depth.set(s = new ArrayDeque<>());
|
||||
}
|
||||
|
||||
if( s == null )
|
||||
{
|
||||
depth.set( s = new ArrayDeque<>() );
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
@Override
|
||||
public T extractItems(T request, final Actionable mode, final IActionSource src) {
|
||||
if (this.diveList(this, mode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extractItems( T request, final Actionable mode, final IActionSource src )
|
||||
{
|
||||
if( this.diveList( this, mode ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (this.testPermission(src, SecurityPermissions.EXTRACT)) {
|
||||
this.surface(this, mode);
|
||||
return null;
|
||||
}
|
||||
|
||||
if( this.testPermission( src, SecurityPermissions.EXTRACT ) )
|
||||
{
|
||||
this.surface( this, mode );
|
||||
return null;
|
||||
}
|
||||
final Iterator<List<IMEInventoryHandler<T>>> i = this.priorityInventory.descendingMap().values().iterator();// priorityInventory.asMap().descendingMap().entrySet().iterator();
|
||||
|
||||
final Iterator<List<IMEInventoryHandler<T>>> i = this.priorityInventory.descendingMap().values().iterator();// priorityInventory.asMap().descendingMap().entrySet().iterator();
|
||||
final T output = request.copy();
|
||||
request = request.copy();
|
||||
output.setStackSize(0);
|
||||
final long req = request.getStackSize();
|
||||
|
||||
final T output = request.copy();
|
||||
request = request.copy();
|
||||
output.setStackSize( 0 );
|
||||
final long req = request.getStackSize();
|
||||
while (i.hasNext()) {
|
||||
final List<IMEInventoryHandler<T>> invList = i.next();
|
||||
|
||||
while( i.hasNext() )
|
||||
{
|
||||
final List<IMEInventoryHandler<T>> invList = i.next();
|
||||
final Iterator<IMEInventoryHandler<T>> ii = invList.iterator();
|
||||
while (ii.hasNext() && output.getStackSize() < req) {
|
||||
final IMEInventoryHandler<T> inv = ii.next();
|
||||
|
||||
final Iterator<IMEInventoryHandler<T>> ii = invList.iterator();
|
||||
while( ii.hasNext() && output.getStackSize() < req )
|
||||
{
|
||||
final IMEInventoryHandler<T> inv = ii.next();
|
||||
request.setStackSize(req - output.getStackSize());
|
||||
output.add(inv.extractItems(request, mode, src));
|
||||
}
|
||||
}
|
||||
|
||||
request.setStackSize( req - output.getStackSize() );
|
||||
output.add( inv.extractItems( request, mode, src ) );
|
||||
}
|
||||
}
|
||||
this.surface(this, mode);
|
||||
|
||||
this.surface( this, mode );
|
||||
if (output.getStackSize() <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if( output.getStackSize() <= 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems(IItemList<T> out) {
|
||||
if (this.diveIteration(this, Actionable.SIMULATE)) {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems( IItemList<T> out )
|
||||
{
|
||||
if( this.diveIteration( this, Actionable.SIMULATE ) )
|
||||
{
|
||||
return out;
|
||||
}
|
||||
// for (Entry<Integer, IMEInventoryHandler<T>> h : priorityInventory.entries())
|
||||
for (final List<IMEInventoryHandler<T>> i : this.priorityInventory.values()) {
|
||||
for (final IMEInventoryHandler<T> j : i) {
|
||||
out = j.getAvailableItems(out);
|
||||
}
|
||||
}
|
||||
|
||||
// for (Entry<Integer, IMEInventoryHandler<T>> h : priorityInventory.entries())
|
||||
for( final List<IMEInventoryHandler<T>> i : this.priorityInventory.values() )
|
||||
{
|
||||
for( final IMEInventoryHandler<T> j : i )
|
||||
{
|
||||
out = j.getAvailableItems( out );
|
||||
}
|
||||
}
|
||||
this.surface(this, Actionable.SIMULATE);
|
||||
|
||||
this.surface( this, Actionable.SIMULATE );
|
||||
return out;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
private boolean diveIteration(final NetworkInventoryHandler<T> networkInventoryHandler, final Actionable type) {
|
||||
final Deque cDepth = this.getDepth(type);
|
||||
if (cDepth.isEmpty()) {
|
||||
currentPass++;
|
||||
this.myPass = currentPass;
|
||||
} else {
|
||||
if (currentPass == this.myPass) {
|
||||
return true;
|
||||
} else {
|
||||
this.myPass = currentPass;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean diveIteration( final NetworkInventoryHandler<T> networkInventoryHandler, final Actionable type )
|
||||
{
|
||||
final Deque cDepth = this.getDepth( type );
|
||||
if( cDepth.isEmpty() )
|
||||
{
|
||||
currentPass++;
|
||||
this.myPass = currentPass;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( currentPass == this.myPass )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.myPass = currentPass;
|
||||
}
|
||||
}
|
||||
cDepth.push(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
cDepth.push( this );
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel<T> getChannel() {
|
||||
return this.myChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel<T> getChannel()
|
||||
{
|
||||
return this.myChannel;
|
||||
}
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrioritized(final T input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final T input )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canAccept(final T input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final T input )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.AccessRestriction;
|
||||
import appeng.api.config.Actionable;
|
||||
@@ -29,67 +28,55 @@ import appeng.api.storage.channels.IItemStorageChannel;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
|
||||
public class NullInventory<T extends IAEStack<T>> implements IMEInventoryHandler<T> {
|
||||
|
||||
public class NullInventory<T extends IAEStack<T>> implements IMEInventoryHandler<T>
|
||||
{
|
||||
@Override
|
||||
public T injectItems(final T input, final Actionable mode, final IActionSource src) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems( final T input, final Actionable mode, final IActionSource src )
|
||||
{
|
||||
return input;
|
||||
}
|
||||
@Override
|
||||
public T extractItems(final T request, final Actionable mode, final IActionSource src) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extractItems( final T request, final Actionable mode, final IActionSource src )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems(final IItemList out) {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<T> getAvailableItems( final IItemList out )
|
||||
{
|
||||
return out;
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel getChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel getChannel()
|
||||
{
|
||||
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
|
||||
}
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.READ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return AccessRestriction.READ;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrioritized(final T input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final T input )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canAccept(final T input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final T input )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return i == 2;
|
||||
}
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return i == 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.me.storage;
|
||||
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
@@ -35,165 +34,134 @@ import appeng.api.storage.data.IItemList;
|
||||
import appeng.me.GridAccessException;
|
||||
import appeng.tile.misc.TileSecurityStation;
|
||||
|
||||
public class SecurityStationInventory implements IMEInventoryHandler<IAEItemStack> {
|
||||
|
||||
public class SecurityStationInventory implements IMEInventoryHandler<IAEItemStack>
|
||||
{
|
||||
private final IItemList<IAEItemStack> storedItems = AEApi.instance().storage()
|
||||
.getStorageChannel(IItemStorageChannel.class).createList();
|
||||
private final TileSecurityStation securityTile;
|
||||
|
||||
private final IItemList<IAEItemStack> storedItems = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
|
||||
private final TileSecurityStation securityTile;
|
||||
public SecurityStationInventory(final TileSecurityStation ts) {
|
||||
this.securityTile = ts;
|
||||
}
|
||||
|
||||
public SecurityStationInventory( final TileSecurityStation ts )
|
||||
{
|
||||
this.securityTile = ts;
|
||||
}
|
||||
@Override
|
||||
public IAEItemStack injectItems(final IAEItemStack input, final Actionable type, final IActionSource src) {
|
||||
if (this.hasPermission(src)) {
|
||||
if (AEApi.instance().definitions().items().biometricCard().isSameAs(input.createItemStack())) {
|
||||
if (this.canAccept(input)) {
|
||||
if (type == Actionable.SIMULATE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEItemStack injectItems( final IAEItemStack input, final Actionable type, final IActionSource src )
|
||||
{
|
||||
if( this.hasPermission( src ) )
|
||||
{
|
||||
if( AEApi.instance().definitions().items().biometricCard().isSameAs( input.createItemStack() ) )
|
||||
{
|
||||
if( this.canAccept( input ) )
|
||||
{
|
||||
if( type == Actionable.SIMULATE )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
this.getStoredItems().add(input);
|
||||
this.securityTile.inventoryChanged();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
this.getStoredItems().add( input );
|
||||
this.securityTile.inventoryChanged();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
private boolean hasPermission(final IActionSource src) {
|
||||
if (src.player().isPresent()) {
|
||||
try {
|
||||
return this.securityTile.getProxy().getSecurity().hasPermission(src.player().get(),
|
||||
SecurityPermissions.SECURITY);
|
||||
} catch (final GridAccessException e) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasPermission( final IActionSource src )
|
||||
{
|
||||
if( src.player().isPresent() )
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.securityTile.getProxy().getSecurity().hasPermission( src.player().get(), SecurityPermissions.SECURITY );
|
||||
}
|
||||
catch( final GridAccessException e )
|
||||
{
|
||||
// :P
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public IAEItemStack extractItems(final IAEItemStack request, final Actionable mode, final IActionSource src) {
|
||||
if (this.hasPermission(src)) {
|
||||
final IAEItemStack target = this.getStoredItems().findPrecise(request);
|
||||
if (target != null) {
|
||||
final IAEItemStack output = target.copy();
|
||||
|
||||
@Override
|
||||
public IAEItemStack extractItems( final IAEItemStack request, final Actionable mode, final IActionSource src )
|
||||
{
|
||||
if( this.hasPermission( src ) )
|
||||
{
|
||||
final IAEItemStack target = this.getStoredItems().findPrecise( request );
|
||||
if( target != null )
|
||||
{
|
||||
final IAEItemStack output = target.copy();
|
||||
if (mode == Actionable.SIMULATE) {
|
||||
return output;
|
||||
}
|
||||
|
||||
if( mode == Actionable.SIMULATE )
|
||||
{
|
||||
return output;
|
||||
}
|
||||
target.setStackSize(0);
|
||||
this.securityTile.inventoryChanged();
|
||||
return output;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
target.setStackSize( 0 );
|
||||
this.securityTile.inventoryChanged();
|
||||
return output;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getAvailableItems(final IItemList out) {
|
||||
for (final IAEItemStack ais : this.getStoredItems()) {
|
||||
out.add(ais);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemList<IAEItemStack> getAvailableItems( final IItemList out )
|
||||
{
|
||||
for( final IAEItemStack ais : this.getStoredItems() )
|
||||
{
|
||||
out.add( ais );
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
@Override
|
||||
public IStorageChannel getChannel() {
|
||||
return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStorageChannel getChannel()
|
||||
{
|
||||
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
|
||||
}
|
||||
@Override
|
||||
public AccessRestriction getAccess() {
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessRestriction getAccess()
|
||||
{
|
||||
return AccessRestriction.READ_WRITE;
|
||||
}
|
||||
@Override
|
||||
public boolean isPrioritized(final IAEItemStack input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrioritized( final IAEItemStack input )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean canAccept(final IAEItemStack input) {
|
||||
if (input.getItem() instanceof IBiometricCard) {
|
||||
final IBiometricCard tbc = (IBiometricCard) input.getItem();
|
||||
final GameProfile newUser = tbc.getProfile(input.createItemStack());
|
||||
|
||||
@Override
|
||||
public boolean canAccept( final IAEItemStack input )
|
||||
{
|
||||
if( input.getItem() instanceof IBiometricCard )
|
||||
{
|
||||
final IBiometricCard tbc = (IBiometricCard) input.getItem();
|
||||
final GameProfile newUser = tbc.getProfile( input.createItemStack() );
|
||||
final int PlayerID = AEApi.instance().registries().players().getID(newUser);
|
||||
if (this.securityTile.getOwner() == PlayerID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int PlayerID = AEApi.instance().registries().players().getID( newUser );
|
||||
if( this.securityTile.getOwner() == PlayerID )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (final IAEItemStack ais : this.getStoredItems()) {
|
||||
if (ais.isMeaningful()) {
|
||||
final GameProfile thisUser = tbc.getProfile(ais.createItemStack());
|
||||
if (thisUser == newUser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for( final IAEItemStack ais : this.getStoredItems() )
|
||||
{
|
||||
if( ais.isMeaningful() )
|
||||
{
|
||||
final GameProfile thisUser = tbc.getProfile( ais.createItemStack() );
|
||||
if( thisUser == newUser )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (thisUser != null && thisUser.equals(newUser)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( thisUser != null && thisUser.equals( newUser ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public boolean validForPass(final int i) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validForPass( final int i )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public IItemList<IAEItemStack> getStoredItems()
|
||||
{
|
||||
return this.storedItems;
|
||||
}
|
||||
public IItemList<IAEItemStack> getStoredItems() {
|
||||
return this.storedItems;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user