mirror of
https://github.com/GTNewHorizons/Applied-Energistics-2-Unofficial.git
synced 2026-10-25 20:22:23 +00:00
implement storage interceptor & fix locking card (#993)
Co-authored-by: Martin Robertz <dream-master@gmx.net>
This commit is contained in:
1 parent
0c34b1dd47
commit
0b03886f6f
5 files changed
+149
-57
No files matched your search
@@ -0,0 +1,14 @@
|
||||
package appeng.api.networking.storage;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
|
||||
public interface IStorageInterceptor {
|
||||
|
||||
boolean canAccept(IAEStack<?> stack);
|
||||
|
||||
IAEStack<?> injectItems(IAEStack<?> input, final Actionable type, final BaseActionSource src);
|
||||
|
||||
boolean shouldRemoveInterceptor(IAEStack<?> stack);
|
||||
}
|
||||
@@ -73,6 +73,7 @@ import appeng.api.networking.events.MENetworkCraftingPushedPattern;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.api.networking.security.MachineSource;
|
||||
import appeng.api.networking.storage.IStorageInterceptor;
|
||||
import appeng.api.networking.ticking.IGridTickable;
|
||||
import appeng.api.networking.ticking.TickRateModulation;
|
||||
import appeng.api.networking.ticking.TickingRequest;
|
||||
@@ -121,7 +122,7 @@ import appeng.util.item.AEItemStack;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
|
||||
public class DualityInterface implements IGridTickable, IStorageMonitorable, IInventoryDestination, IAEAppEngInventory,
|
||||
IConfigManagerHost, ICraftingProvider, IUpgradeableHost, IPriorityHost, IGridProxyable {
|
||||
IConfigManagerHost, ICraftingProvider, IUpgradeableHost, IPriorityHost, IGridProxyable, IStorageInterceptor {
|
||||
|
||||
public static final int NUMBER_OF_STORAGE_SLOTS = 9;
|
||||
public static final int NUMBER_OF_CONFIG_SLOTS = 9;
|
||||
@@ -161,7 +162,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
||||
|
||||
private YesNo redstoneState = YesNo.UNDECIDED;
|
||||
private UnlockCraftingEvent unlockEvent;
|
||||
private List<IAEItemStack> unlockStacks;
|
||||
private List<IAEStack<?>> unlockStacks;
|
||||
private int lastInputHash = 0;
|
||||
private final boolean isFluidInterface;
|
||||
private ScheduledReason scheduledReason = ScheduledReason.UNDEFINED;
|
||||
@@ -261,9 +262,9 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
||||
if (unlockStacks != null && !unlockStacks.isEmpty()) {
|
||||
data.setByte("unlockEvent", (byte) 2);
|
||||
NBTTagList stackList = new NBTTagList();
|
||||
for (IAEItemStack stack : unlockStacks) {
|
||||
for (IAEStack<?> stack : unlockStacks) {
|
||||
NBTTagCompound stackTag = new NBTTagCompound();
|
||||
stack.writeToNBT(stackTag);
|
||||
Platform.writeStackNBT(stack, stackTag, true);
|
||||
stackList.appendTag(stackTag);
|
||||
}
|
||||
data.setTag("unlockStacks", stackList);
|
||||
@@ -312,7 +313,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
||||
NBTTagList stackList = data.getTagList("unlockStacks", 10);
|
||||
for (int index = 0; index < stackList.tagCount(); index++) {
|
||||
NBTTagCompound stackTag = stackList.getCompoundTagAt(index);
|
||||
IAEItemStack unlockStack = AEItemStack.loadItemStackFromNBT(stackTag);
|
||||
IAEStack<?> unlockStack = Platform.readStackNBT(stackTag, true);
|
||||
if (unlockStack == null) {
|
||||
AELog.error("Could not load unlock stack for interface from NBT: {}", data);
|
||||
continue;
|
||||
@@ -322,6 +323,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
||||
}
|
||||
this.unlockStacks.add(unlockStack);
|
||||
}
|
||||
addInterception();
|
||||
} else {
|
||||
this.unlockStacks = null;
|
||||
}
|
||||
@@ -823,7 +825,6 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
||||
} else if (removed.stackSize != diff) {
|
||||
throw new IllegalStateException("bad attempt at managing inventory. ( removeItems )");
|
||||
}
|
||||
onStackReturnedToNetwork(AEItemStack.create(removed));
|
||||
}
|
||||
} else if (this.craftingTracker.isBusy(x)) {
|
||||
changed = this.handleCrafting(x, adaptor, itemStack);
|
||||
@@ -1084,6 +1085,90 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
||||
this.lastInputHash = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept(IAEStack<?> stack) {
|
||||
if (unlockStacks != null && stack != null) {
|
||||
for (IAEStack<?> unlockStack : unlockStacks) {
|
||||
if (stack.equals(unlockStack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAEStack<?> injectItems(IAEStack<?> input, Actionable type, BaseActionSource src) {
|
||||
if (type == Actionable.SIMULATE) return input;
|
||||
if (unlockStacks != null && input != null) {
|
||||
boolean changed = false;
|
||||
|
||||
for (Iterator<IAEStack<?>> iterator = unlockStacks.iterator(); iterator.hasNext();) {
|
||||
IAEStack<?> unlockStack = iterator.next();
|
||||
if (unlockStack.equals(input)) {
|
||||
changed = true;
|
||||
unlockStack.decStackSize(input.getStackSize());
|
||||
if (unlockStack.getStackSize() <= 0) {
|
||||
iterator.remove();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
saveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
private void addInterception() {
|
||||
boolean hasItems = false;
|
||||
boolean hasFluids = false;
|
||||
|
||||
for (IAEStack<?> aes : unlockStacks) {
|
||||
if (aes.isItem()) {
|
||||
hasItems = true;
|
||||
} else if (aes.isFluid()) {
|
||||
hasFluids = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasItems) {
|
||||
try {
|
||||
if (this.gridProxy.getStorage().getItemInventory() instanceof NetworkMonitor<?>nm) {
|
||||
nm.addStorageInterceptor(this);
|
||||
}
|
||||
} catch (GridAccessException ignored) {}
|
||||
}
|
||||
|
||||
if (hasFluids) {
|
||||
try {
|
||||
if (this.gridProxy.getStorage().getFluidInventory() instanceof NetworkMonitor<?>nm) {
|
||||
nm.addStorageInterceptor(this);
|
||||
}
|
||||
} catch (GridAccessException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRemoveInterceptor(IAEStack<?> stack) {
|
||||
if (unlockStacks != null) {
|
||||
if (unlockStacks.isEmpty()) {
|
||||
unlockEvent = null;
|
||||
unlockStacks = null;
|
||||
} else {
|
||||
for (IAEStack<?> unlockStack : unlockStacks) {
|
||||
if (stack.isItem() && unlockStack.isItem()) return false;
|
||||
if (stack.isFluid() && unlockStack.isFluid()) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class VerifiedAcceptors {
|
||||
|
||||
public TileEntity te;
|
||||
@@ -1583,9 +1668,13 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
||||
if (unlockStacks == null) {
|
||||
unlockStacks = new ArrayList<>();
|
||||
}
|
||||
for (IAEItemStack output : pattern.getCondensedOutputs()) {
|
||||
|
||||
for (IAEStack<?> output : pattern.getCondensedAEOutputs()) {
|
||||
unlockStacks.add(output.copy());
|
||||
}
|
||||
|
||||
addInterception();
|
||||
|
||||
saveChanges();
|
||||
}
|
||||
}
|
||||
@@ -1620,46 +1709,10 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
||||
/**
|
||||
* @return Null if {@linkplain #getCraftingLockedReason()} is not {@link LockCraftingMode#LOCK_UNTIL_RESULT}.
|
||||
*/
|
||||
public List<IAEItemStack> getUnlockStacks() {
|
||||
public List<IAEStack<?>> getUnlockStacks() {
|
||||
return unlockStacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an ItemStack has been pushed into the network from the internal buffer. Public to enable other
|
||||
* interface types (mainly AE2FC) to work with locking return mode.
|
||||
*/
|
||||
public void onStackReturnedToNetwork(IAEItemStack returnedStack) {
|
||||
if (unlockEvent != UnlockCraftingEvent.RESULT) {
|
||||
return; // If we're not waiting for the result, we don't care
|
||||
}
|
||||
|
||||
if (unlockStacks == null) {
|
||||
// Actually an error state...
|
||||
AELog.error("interface was waiting for RESULT, but no result was set");
|
||||
unlockEvent = null;
|
||||
return;
|
||||
}
|
||||
boolean changed = false;
|
||||
for (Iterator<IAEItemStack> iterator = unlockStacks.iterator(); iterator.hasNext();) {
|
||||
IAEItemStack unlockStack = iterator.next();
|
||||
if (unlockStack.equals(returnedStack)) {
|
||||
changed = true;
|
||||
unlockStack.decStackSize(returnedStack.getStackSize());
|
||||
if (unlockStack.getStackSize() <= 0) {
|
||||
iterator.remove();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (unlockStacks.isEmpty()) {
|
||||
unlockEvent = null;
|
||||
unlockStacks = null;
|
||||
}
|
||||
if (changed) {
|
||||
saveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateRedstoneState() {
|
||||
// reset cache to undecided
|
||||
redstoneState = YesNo.UNDECIDED;
|
||||
|
||||
@@ -10,10 +10,10 @@ import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.config.LockCraftingMode;
|
||||
import appeng.api.parts.IPart;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.core.localization.WailaText;
|
||||
import appeng.helpers.IInterfaceHost;
|
||||
import appeng.util.item.AEItemStack;
|
||||
import appeng.util.Platform;
|
||||
import mcp.mobius.waila.api.IWailaConfigHandler;
|
||||
import mcp.mobius.waila.api.IWailaDataAccessor;
|
||||
|
||||
@@ -42,7 +42,7 @@ public final class PartInterfaceDataProvider extends BasePartWailaDataProvider {
|
||||
NBTTagList stackList = accessor.getNBTData().getTagList(NBT_LOCK_STACKS, 10);
|
||||
for (int index = 0; index < stackList.tagCount(); index++) {
|
||||
NBTTagCompound stackTag = stackList.getCompoundTagAt(index);
|
||||
AEItemStack stack = (AEItemStack) AEItemStack.loadItemStackFromNBT(stackTag);
|
||||
IAEStack<?> stack = Platform.readStackNBT(stackTag);
|
||||
|
||||
if (stack != null) {
|
||||
currentToolTip.add("> " + stack.getStackSize() + " " + stack.getDisplayName());
|
||||
@@ -70,12 +70,12 @@ public final class PartInterfaceDataProvider extends BasePartWailaDataProvider {
|
||||
tag.setString(NBT_LOCK_REASON, interfaceDuality.getCraftingLockedReason().name());
|
||||
LockCraftingMode lock = interfaceDuality.getCraftingLockedReason();
|
||||
if (lock == LockCraftingMode.LOCK_UNTIL_RESULT) {
|
||||
List<IAEItemStack> unlockStacks = interfaceDuality.getUnlockStacks();
|
||||
List<IAEStack<?>> unlockStacks = interfaceDuality.getUnlockStacks();
|
||||
if (unlockStacks != null && !unlockStacks.isEmpty()) {
|
||||
NBTTagList stackList = new NBTTagList();
|
||||
for (IAEItemStack stack : unlockStacks) {
|
||||
for (IAEStack<?> stack : unlockStacks) {
|
||||
NBTTagCompound stackTag = new NBTTagCompound();
|
||||
stack.writeToNBT(stackTag);
|
||||
Platform.writeStackNBT(stack, stackTag, true);
|
||||
stackList.appendTag(stackTag);
|
||||
}
|
||||
tag.setTag(NBT_LOCK_STACKS, stackList);
|
||||
|
||||
@@ -10,11 +10,11 @@ import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import appeng.api.config.LockCraftingMode;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IAEStack;
|
||||
import appeng.core.localization.WailaText;
|
||||
import appeng.helpers.IInterfaceHost;
|
||||
import appeng.integration.modules.waila.BaseWailaDataProvider;
|
||||
import appeng.util.item.AEItemStack;
|
||||
import appeng.util.Platform;
|
||||
import mcp.mobius.waila.api.IWailaConfigHandler;
|
||||
import mcp.mobius.waila.api.IWailaDataAccessor;
|
||||
|
||||
@@ -43,7 +43,7 @@ public final class InterfaceDataProvider extends BaseWailaDataProvider {
|
||||
NBTTagList stackList = accessor.getNBTData().getTagList(NBT_LOCK_STACKS, 10);
|
||||
for (int index = 0; index < stackList.tagCount(); index++) {
|
||||
NBTTagCompound stackTag = stackList.getCompoundTagAt(index);
|
||||
AEItemStack stack = (AEItemStack) AEItemStack.loadItemStackFromNBT(stackTag);
|
||||
IAEStack<?> stack = Platform.readStackNBT(stackTag);
|
||||
|
||||
if (stack != null) {
|
||||
currentToolTip.add("> " + stack.getStackSize() + " " + stack.getDisplayName());
|
||||
@@ -71,12 +71,12 @@ public final class InterfaceDataProvider extends BaseWailaDataProvider {
|
||||
tag.setString(NBT_LOCK_REASON, interfaceDuality.getCraftingLockedReason().name());
|
||||
LockCraftingMode lock = interfaceDuality.getCraftingLockedReason();
|
||||
if (lock == LockCraftingMode.LOCK_UNTIL_RESULT) {
|
||||
List<IAEItemStack> unlockStacks = interfaceDuality.getUnlockStacks();
|
||||
List<IAEStack<?>> unlockStacks = interfaceDuality.getUnlockStacks();
|
||||
if (unlockStacks != null && !unlockStacks.isEmpty()) {
|
||||
NBTTagList stackList = new NBTTagList();
|
||||
for (IAEItemStack stack : unlockStacks) {
|
||||
for (IAEStack<?> stack : unlockStacks) {
|
||||
NBTTagCompound stackTag = new NBTTagCompound();
|
||||
stack.writeToNBT(stackTag);
|
||||
Platform.writeStackNBT(stack, stackTag, true);
|
||||
stackList.appendTag(stackTag);
|
||||
}
|
||||
tag.setTag(NBT_LOCK_STACKS, stackList);
|
||||
|
||||
+26
-1
@@ -13,9 +13,11 @@ package appeng.me.cache;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnegative;
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -29,6 +31,7 @@ import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.events.MENetworkStorageEvent;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.networking.storage.IStorageInterceptor;
|
||||
import appeng.api.storage.IMEInventoryHandler;
|
||||
import appeng.api.storage.IMEMonitor;
|
||||
import appeng.api.storage.IMEMonitorHandlerReceiver;
|
||||
@@ -65,6 +68,8 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T> {
|
||||
@Nonnegative
|
||||
private int localDepthSemaphore = 0;
|
||||
|
||||
private final Set<IStorageInterceptor> storageInterceptors = new HashSet<>();
|
||||
|
||||
public NetworkMonitor(final GridStorageCache cache, final StorageChannel chan) {
|
||||
this.myGridCache = cache;
|
||||
this.myChannel = chan;
|
||||
@@ -148,7 +153,19 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T injectItems(final T input, final Actionable mode, final BaseActionSource src) {
|
||||
public T injectItems(T input, final Actionable mode, final BaseActionSource src) {
|
||||
|
||||
for (Iterator<IStorageInterceptor> iterator = storageInterceptors.iterator(); iterator.hasNext();) {
|
||||
final IStorageInterceptor isi = iterator.next();
|
||||
if (isi.canAccept(input)) {
|
||||
input = (T) isi.injectItems(input, mode, src);
|
||||
|
||||
if (isi.shouldRemoveInterceptor(input)) iterator.remove();
|
||||
|
||||
if (input == null) return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == Actionable.SIMULATE) {
|
||||
return this.getHandler().injectItems(input, mode, src);
|
||||
}
|
||||
@@ -326,4 +343,12 @@ public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T> {
|
||||
this.myGridCache.getGrid().postEvent(new MENetworkStorageEvent(this, this.myChannel));
|
||||
}
|
||||
}
|
||||
|
||||
public void addStorageInterceptor(IStorageInterceptor storageInterceptor) {
|
||||
this.storageInterceptors.add(storageInterceptor);
|
||||
}
|
||||
|
||||
public void removeStorageInterceptor(IStorageInterceptor storageInterceptor) {
|
||||
this.storageInterceptors.remove(storageInterceptor);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user