Add reshuffler access configuration (#1613)

This commit is contained in:
Worive authored and GitHub committed 2026-09-24 04:43:19 +00:00
1 parent 3455778252
commit 22023fe5ad
18 files changed
+403 -15

No files matched your search

@@ -62,6 +62,7 @@ public enum Settings {
INTERFACE_TERMINAL(EnumSet.of(YesNo.YES, YesNo.NO)),
CRAFT_VIA_REDSTONE(EnumSet.of(YesNo.YES, YesNo.NO)),
PATTERN_OPTIMIZATION(EnumSet.of(YesNo.YES, YesNo.NO)),
RESHUFFLE_ACCESS(EnumSet.allOf(AccessRestriction.class)),
STORAGE_FILTER(EnumSet.allOf(StorageFilter.class)),
PLACE_BLOCK(EnumSet.of(YesNo.YES, YesNo.NO)),
@@ -13,6 +13,7 @@
package appeng.api.storage;
import appeng.api.config.AccessRestriction;
import appeng.api.networking.security.IActionHost;
/**
@@ -20,6 +21,11 @@ import appeng.api.networking.security.IActionHost;
*/
public interface ICellContainer extends IActionHost, ICellProvider, ISaveProvider {
/** READ permits reshuffler extraction; WRITE permits reshuffler insertion. */
default AccessRestriction getReshuffleAccess() {
return AccessRestriction.READ_WRITE;
}
@Deprecated
default void blinkCell(int slot) {}
}
@@ -95,6 +95,11 @@ public interface IMEInventoryHandler<StackType extends IAEStack> extends IMEInve
return false;
}
/** READ permits reshuffler extraction; WRITE permits reshuffler insertion. */
default AccessRestriction getReshuffleAccess() {
return AccessRestriction.READ_WRITE;
}
/** returns internal IMEInventory if it has one */
default IMEInventory<StackType> getInternal() {
return null;
@@ -194,6 +194,11 @@ public class MEMonitorHandler<StackType extends IAEStack<?>> implements IMEMonit
return this.internalHandler.getSticky();
}
@Override
public AccessRestriction getReshuffleAccess() {
return this.internalHandler.getReshuffleAccess();
}
@Override
public @NotNull IAEStackType<?> getStackType() {
return this.getHandler().getStackType();
@@ -13,19 +13,26 @@ package appeng.client.gui.implementations;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.entity.player.InventoryPlayer;
import org.lwjgl.input.Mouse;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Settings;
import appeng.client.gui.AEBaseGui;
import appeng.client.gui.widgets.GuiImgButton;
import appeng.client.gui.widgets.GuiTabButton;
import appeng.container.implementations.ContainerChest;
import appeng.core.localization.ColorUtils;
import appeng.core.localization.GuiText;
import appeng.core.sync.GuiBridge;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketConfigButton;
import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.tile.storage.TileChest;
public class GuiChest extends AEBaseGui {
private GuiTabButton priority;
private GuiImgButton reshuffleAccess;
public GuiChest(final InventoryPlayer inventoryPlayer, final TileChest te) {
super(new ContainerChest(inventoryPlayer, te));
@@ -36,9 +43,14 @@ public class GuiChest extends AEBaseGui {
protected void actionPerformed(final GuiButton par1GuiButton) {
super.actionPerformed(par1GuiButton);
final boolean backwards = Mouse.isButtonDown(1);
if (par1GuiButton == this.priority) {
NetworkHandler.instance.sendToServer(new PacketSwitchGuis(GuiBridge.GUI_PRIORITY));
}
if (par1GuiButton == this.reshuffleAccess) {
NetworkHandler.instance.sendToServer(new PacketConfigButton(Settings.RESHUFFLE_ACCESS, backwards));
}
}
@Override
@@ -52,10 +64,17 @@ public class GuiChest extends AEBaseGui {
2 + 4 * 16,
GuiText.Priority.getLocal(),
itemRender));
this.buttonList.add(
this.reshuffleAccess = new GuiImgButton(
this.guiLeft - 18,
this.guiTop + 8,
Settings.RESHUFFLE_ACCESS,
AccessRestriction.READ_WRITE));
}
@Override
public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.reshuffleAccess.set(((ContainerChest) this.inventorySlots).getReshuffleAccess());
this.fontRendererObj.drawString(
this.getGuiDisplayName(GuiText.Chest.getLocal()),
8,
@@ -13,19 +13,26 @@ package appeng.client.gui.implementations;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.entity.player.InventoryPlayer;
import org.lwjgl.input.Mouse;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Settings;
import appeng.client.gui.AEBaseGui;
import appeng.client.gui.widgets.GuiImgButton;
import appeng.client.gui.widgets.GuiTabButton;
import appeng.container.implementations.ContainerDrive;
import appeng.core.localization.ColorUtils;
import appeng.core.localization.GuiText;
import appeng.core.sync.GuiBridge;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketConfigButton;
import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.tile.storage.TileDrive;
public class GuiDrive extends AEBaseGui {
private GuiTabButton priority;
private GuiImgButton reshuffleAccess;
public GuiDrive(final InventoryPlayer inventoryPlayer, final TileDrive te) {
super(new ContainerDrive(inventoryPlayer, te));
@@ -36,9 +43,14 @@ public class GuiDrive extends AEBaseGui {
protected void actionPerformed(final GuiButton par1GuiButton) {
super.actionPerformed(par1GuiButton);
final boolean backwards = Mouse.isButtonDown(1);
if (par1GuiButton == this.priority) {
NetworkHandler.instance.sendToServer(new PacketSwitchGuis(GuiBridge.GUI_PRIORITY));
}
if (par1GuiButton == this.reshuffleAccess) {
NetworkHandler.instance.sendToServer(new PacketConfigButton(Settings.RESHUFFLE_ACCESS, backwards));
}
}
@Override
@@ -52,10 +64,17 @@ public class GuiDrive extends AEBaseGui {
2 + 4 * 16,
GuiText.Priority.getLocal(),
itemRender));
this.buttonList.add(
this.reshuffleAccess = new GuiImgButton(
this.guiLeft - 18,
this.guiTop + 8,
Settings.RESHUFFLE_ACCESS,
AccessRestriction.READ_WRITE));
}
@Override
public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.reshuffleAccess.set(((ContainerDrive) this.inventorySlots).getReshuffleAccess());
this.fontRendererObj.drawString(
this.getGuiDisplayName(GuiText.Drive.getLocal()),
8,
@@ -1054,6 +1054,30 @@ public class GuiImgButton extends GuiButton implements ITooltip {
YesNo.NO,
ButtonToolTips.ReshuffleIncludeSubnets,
ButtonToolTips.ReshuffleIncludeSubnetsOff);
this.registerApp(
8 * 16 + 8,
Settings.RESHUFFLE_ACCESS,
AccessRestriction.READ_WRITE,
ButtonToolTips.ReshuffleAccess,
ButtonToolTips.ReshuffleReadWrite);
this.registerApp(
16 * 9 + 13,
Settings.RESHUFFLE_ACCESS,
AccessRestriction.WRITE,
ButtonToolTips.ReshuffleAccess,
ButtonToolTips.ReshuffleWrite);
this.registerApp(
8 * 16 + 9,
Settings.RESHUFFLE_ACCESS,
AccessRestriction.NO_ACCESS,
ButtonToolTips.ReshuffleAccess,
ButtonToolTips.ReshuffleNone);
this.registerApp(
16 * 9 + 12,
Settings.RESHUFFLE_ACCESS,
AccessRestriction.READ,
ButtonToolTips.ReshuffleAccess,
ButtonToolTips.ReshuffleRead);
this.registerApp(
4 * 16 + 10,
Settings.CELL_HEALTH_SORT,
@@ -12,17 +12,27 @@ package appeng.container.implementations;
import net.minecraft.entity.player.InventoryPlayer;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Settings;
import appeng.container.AEBaseContainer;
import appeng.container.slot.SlotRestrictedInput;
import appeng.container.sync.handlers.ConfigEnumSyncHandler;
import appeng.tile.storage.TileChest;
import appeng.util.Platform;
public class ContainerChest extends AEBaseContainer {
private final TileChest chest;
private final ConfigEnumSyncHandler<AccessRestriction> reshuffleAccessSync;
public ContainerChest(final InventoryPlayer ip, final TileChest chest) {
super(ip, chest);
this.chest = chest;
this.reshuffleAccessSync = this.syncRegistrar().configEnum(
"reshuffleAccess",
Settings.RESHUFFLE_ACCESS,
AccessRestriction.class,
chest.getConfigManager());
this.addSlotToContainer(
new SlotRestrictedInput(
@@ -35,4 +45,16 @@ public class ContainerChest extends AEBaseContainer {
this.bindPlayerInventory(ip, 0, 166 - /* height of player inventory */ 82);
}
@Override
public void detectAndSendChanges() {
if (Platform.isServer()) {
this.reshuffleAccessSync.syncFromConfig();
}
super.detectAndSendChanges();
}
public AccessRestriction getReshuffleAccess() {
return this.reshuffleAccessSync.get();
}
}
@@ -12,14 +12,27 @@ package appeng.container.implementations;
import net.minecraft.entity.player.InventoryPlayer;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Settings;
import appeng.container.AEBaseContainer;
import appeng.container.slot.SlotRestrictedInput;
import appeng.container.sync.handlers.ConfigEnumSyncHandler;
import appeng.tile.storage.TileDrive;
import appeng.util.Platform;
public class ContainerDrive extends AEBaseContainer {
private final TileDrive drive;
private final ConfigEnumSyncHandler<AccessRestriction> reshuffleAccessSync;
public ContainerDrive(final InventoryPlayer ip, final TileDrive drive) {
super(ip, drive);
this.drive = drive;
this.reshuffleAccessSync = this.syncRegistrar().configEnum(
"reshuffleAccess",
Settings.RESHUFFLE_ACCESS,
AccessRestriction.class,
drive.getConfigManager());
for (int y = 0; y < 5; y++) {
for (int x = 0; x < 2; x++) {
@@ -36,4 +49,16 @@ public class ContainerDrive extends AEBaseContainer {
this.bindPlayerInventory(ip, 0, 199 - /* height of player inventory */ 82);
}
@Override
public void detectAndSendChanges() {
if (Platform.isServer()) {
this.reshuffleAccessSync.syncFromConfig();
}
super.detectAndSendChanges();
}
public AccessRestriction getReshuffleAccess() {
return this.reshuffleAccessSync.get();
}
}
@@ -247,7 +247,7 @@ public class ContainerMEMonitorable extends AEBaseContainer
this.updateFlowTrackingState();
for (final Settings set : this.serverCM.getSettings()) {
for (final Settings set : this.clientCM.getSettings()) {
final Enum<?> sideLocal = this.serverCM.getSetting(set);
final Enum<?> sideRemote = this.clientCM.getSetting(set);
@@ -281,6 +281,11 @@ public enum ButtonToolTips implements Localization {
ReshuffleInsertOrder,
ReshuffleInsertOrderOn,
ReshuffleInsertOrderOff,
ReshuffleAccess,
ReshuffleReadWrite,
ReshuffleWrite,
ReshuffleNone,
ReshuffleRead,
OpenReshuffle,
OpenReshuffleDesc,
OpenReshuffleOffDesc,
@@ -6,6 +6,7 @@ import static appeng.gametests.AEGameTestHelpers.assertStoredAmount;
import static appeng.gametests.AEGameTestHelpers.cell1k;
import static appeng.gametests.AEGameTestHelpers.insertItems;
import static appeng.gametests.AEGameTestHelpers.itemStack;
import static appeng.util.item.AEItemStackType.ITEM_STACK_TYPE;
import java.util.Arrays;
import java.util.List;
@@ -25,13 +26,17 @@ import com.gtnewhorizons.horizonqa.api.annotation.GameTestHolder;
import com.gtnewhorizons.horizonqa.api.annotation.MethodSource;
import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.config.ReshufflePhase;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.security.MachineSource;
import appeng.api.networking.security.ReshuffleActionSource;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.networking.storage.IStorageInterceptor;
import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
@@ -60,6 +65,130 @@ public final class StorageReshuffleTests {
private StorageReshuffleTests() {}
@GameTest(template = TEMPLATE, timeoutTicks = 100)
public static void driveAndChestSupportAllAccessModes(GameTestHelper helper) {
Fixture fixture = placeFixture(helper);
ItemStack driveCell = cell1k();
ItemStack chestCell = cell1k();
insertItems(helper, driveCell, Blocks.cobblestone, 64);
insertItems(helper, chestCell, Blocks.dirt, 64);
helper.startSequence()
.thenWaitUntil(
"wait for access mode network activation",
40,
() -> { assertFixtureActive(helper, fixture); })
.thenExecute("install access mode cells", () -> {
helper.setSlot(SOURCE_DRIVE, 0, driveCell);
helper.setSlot(ME_CHEST, 1, chestCell);
}).thenWaitUntil("wait for access mode cells", 20, () -> {
helper.assertFalse(
fixture.sourceDrive.getCellArray(ITEM_STACK_TYPE).isEmpty(),
"Drive cell should be available");
helper.assertFalse(
fixture.meChest.getCellArray(ITEM_STACK_TYPE).isEmpty(),
"ME chest cell should be available");
}).thenExecute("verify all reshuffler access modes", () -> {
ReshuffleActionSource source = new ReshuffleActionSource(fixture.controller);
IMEInventoryHandler<IAEItemStack> driveInventory = fixture.sourceDrive.getCellArray(ITEM_STACK_TYPE)
.get(0);
IMEInventoryHandler<IAEItemStack> chestInventory = fixture.meChest.getCellArray(ITEM_STACK_TYPE)
.get(0);
List<IMEInventoryHandler<IAEItemStack>> inventories = Arrays.asList(driveInventory, chestInventory);
Block[] storedBlocks = { Blocks.cobblestone, Blocks.dirt };
Block[] insertedBlocks = { Blocks.dirt, Blocks.cobblestone };
for (AccessRestriction access : AccessRestriction.values()) {
fixture.sourceDrive.getConfigManager().putSetting(Settings.RESHUFFLE_ACCESS, access);
fixture.meChest.getConfigManager().putSetting(Settings.RESHUFFLE_ACCESS, access);
for (int i = 0; i < inventories.size(); i++) {
IMEInventoryHandler<IAEItemStack> inventory = inventories.get(i);
boolean extractionAllowed = inventory
.extractItems(itemStack(storedBlocks[i], 1), Actionable.SIMULATE, source) != null;
boolean insertionAllowed = inventory
.injectItems(itemStack(insertedBlocks[i], 1), Actionable.SIMULATE, source) == null;
helper.assertEquals(
access,
inventory.getReshuffleAccess(),
"Storage should report " + access);
helper.assertEquals(
access.hasPermission(AccessRestriction.READ),
extractionAllowed,
access + " should control reshuffler extraction");
helper.assertEquals(
access.hasPermission(AccessRestriction.WRITE),
insertionAllowed,
access + " should control reshuffler insertion");
}
}
}).thenSucceed();
}
@GameTest(template = TEMPLATE, timeoutTicks = 100)
public static void voidCellsRespectDriveAndChestReshuffleAccess(GameTestHelper helper) {
Fixture fixture = placeFixture(helper);
ItemStack driveCell = AEApi.instance().definitions().items().cellVoid().maybeStack(1).get();
ItemStack chestCell = AEApi.instance().definitions().items().cellVoid().maybeStack(1).get();
helper.startSequence()
.thenWaitUntil(
"wait for void cell network activation",
40,
() -> { assertFixtureActive(helper, fixture); })
.thenExecute("install void cells", () -> {
helper.setSlot(SOURCE_DRIVE, 0, driveCell);
helper.setSlot(ME_CHEST, 1, chestCell);
}).thenWaitUntil("wait for void cell handlers", 20, () -> {
helper.assertFalse(
fixture.sourceDrive.getCellArray(ITEM_STACK_TYPE).isEmpty(),
"Drive void cell missing");
helper.assertFalse(
fixture.meChest.getCellArray(ITEM_STACK_TYPE).isEmpty(),
"Chest void cell missing");
}).thenExecute("verify void cell access", () -> {
ReshuffleActionSource reshuffleSource = new ReshuffleActionSource(fixture.controller);
MachineSource ordinarySource = new MachineSource(fixture.controller);
IMEInventoryHandler<IAEItemStack> driveInventory = fixture.sourceDrive.getCellArray(ITEM_STACK_TYPE)
.get(0);
IMEInventoryHandler<IAEItemStack> chestInventory = fixture.meChest.getCellArray(ITEM_STACK_TYPE)
.get(0);
List<IMEInventoryHandler<IAEItemStack>> inventories = Arrays.asList(driveInventory, chestInventory);
AccessRestriction[] accessModes = AccessRestriction.values();
for (int i = 0; i < accessModes.length; i++) {
AccessRestriction[] configuredAccess = { accessModes[i],
accessModes[(i + 1) % accessModes.length] };
fixture.sourceDrive.getConfigManager()
.putSetting(Settings.RESHUFFLE_ACCESS, configuredAccess[0]);
fixture.meChest.getConfigManager().putSetting(Settings.RESHUFFLE_ACCESS, configuredAccess[1]);
for (int host = 0; host < inventories.size(); host++) {
IMEInventoryHandler<IAEItemStack> inventory = inventories.get(host);
AccessRestriction access = configuredAccess[host];
helper.assertEquals(
access,
inventory.getReshuffleAccess(),
"Void cell access should follow host");
helper.assertEquals(
access.hasPermission(AccessRestriction.WRITE),
inventory.injectItems(
itemStack(Blocks.cobblestone, 1),
Actionable.SIMULATE,
reshuffleSource) == null,
"Void cell should enforce reshuffler insertion access");
helper.assertTrue(
inventory.injectItems(
itemStack(Blocks.cobblestone, 1),
Actionable.SIMULATE,
ordinarySource) == null,
"Ordinary insertion should remain allowed");
}
}
}).thenSucceed();
}
@GameTest(template = TEMPLATE, timeoutTicks = 160)
@MethodSource("insertOrders")
public static void insertOrderControlsConstrainedCellPacking(GameTestHelper helper, boolean largeStacksFirst) {
@@ -205,6 +334,60 @@ public final class StorageReshuffleTests {
}).thenSucceed();
}
@GameTest(template = TEMPLATE, timeoutTicks = 140)
public static void accessModesControlExtractionAndInsertion(GameTestHelper helper) {
Fixture fixture = placeFixture(helper);
ItemStack readableCell = cell1k();
ItemStack writableCell = cell1k();
ItemStack inaccessibleCell = cell1k();
insertItems(helper, readableCell, Blocks.cobblestone, 64);
insertItems(helper, writableCell, Blocks.dirt, 32);
insertItems(helper, inaccessibleCell, Blocks.gravel, 16);
helper.startSequence()
.thenWaitUntil(
"wait for access-controlled network activation",
40,
() -> { assertFixtureActive(helper, fixture); })
.thenExecute("configure reshuffler access and install cells", () -> {
fixture.sourceDrive.setPriority(0);
fixture.sourceDrive.getConfigManager()
.putSetting(Settings.RESHUFFLE_ACCESS, AccessRestriction.READ);
fixture.targetDrive.setPriority(100);
fixture.targetDrive.getConfigManager()
.putSetting(Settings.RESHUFFLE_ACCESS, AccessRestriction.WRITE);
fixture.meChest.setPriority(200);
fixture.meChest.getConfigManager()
.putSetting(Settings.RESHUFFLE_ACCESS, AccessRestriction.NO_ACCESS);
helper.setSlot(SOURCE_DRIVE, 0, readableCell);
helper.setSlot(TARGET_DRIVE, 0, writableCell);
helper.setSlot(ME_CHEST, 1, inaccessibleCell);
}).thenWaitUntil("wait for access-controlled contents", 20, () -> {
assertNetworkStoredAmount(helper, fixture.controller, Blocks.cobblestone, 64);
assertNetworkStoredAmount(helper, fixture.controller, Blocks.dirt, 32);
assertNetworkStoredAmount(helper, fixture.controller, Blocks.gravel, 16);
}).thenExecute("start access-controlled reshuffle", fixture.reshuffler::startReshuffle)
.thenWaitUntil(
"wait for access-controlled reshuffle completion",
60,
() -> assertDone(helper, fixture.reshuffler))
.thenExecute("verify access-controlled routing", () -> {
assertStoredAmount(helper, fixture.sourceDrive.getStackInSlot(0), Blocks.cobblestone, 0);
assertStoredAmount(helper, fixture.targetDrive.getStackInSlot(0), Blocks.cobblestone, 64);
assertStoredAmount(helper, fixture.targetDrive.getStackInSlot(0), Blocks.dirt, 32);
assertStoredAmount(helper, fixture.meChest.getStackInSlot(1), Blocks.gravel, 16);
assertStoredAmount(helper, fixture.meChest.getStackInSlot(1), Blocks.cobblestone, 0);
ReshuffleReport report = fixture.reshuffler.getReshuffleReport();
helper.assertEquals(64.0, report.extractedItems, "Only readable storage should be extracted");
helper.assertEquals(64.0, report.injectedItems, "Writable storage should receive extracted items");
helper.assertTrue(report.cantExtract.isEmpty(), "Unreadable storage should be skipped");
helper.assertTrue(report.cantInject.isEmpty(), "Writable storage should accept every item");
helper.assertTrue(report.lostItems.isEmpty(), "Access controls should not lose items");
helper.assertTrue(report.gainedItems.isEmpty(), "Access controls should not duplicate items");
}).thenSucceed();
}
@GameTest(template = TEMPLATE, timeoutTicks = 140)
public static void missingDestinationRestoresItemsToTheirSource(GameTestHelper helper) {
Fixture fixture = placeFixture(helper);
@@ -220,6 +403,9 @@ public final class StorageReshuffleTests {
40,
() -> { assertFixtureActive(helper, fixture); })
.thenExecute("install rollback sources", () -> {
fixture.sourceDrive.getConfigManager()
.putSetting(Settings.RESHUFFLE_ACCESS, AccessRestriction.READ);
fixture.meChest.getConfigManager().putSetting(Settings.RESHUFFLE_ACCESS, AccessRestriction.READ);
helper.setSlot(SOURCE_DRIVE, 0, firstSourceCell);
helper.setSlot(ME_CHEST, 1, secondSourceCell);
})
@@ -268,7 +454,11 @@ public final class StorageReshuffleTests {
"wait for cancellation network activation",
40,
() -> { assertFixtureActive(helper, fixture); })
.thenExecute("install cancellation source", () -> { helper.setSlot(SOURCE_DRIVE, 0, sourceCell); })
.thenExecute("install read-only cancellation source", () -> {
fixture.sourceDrive.getConfigManager()
.putSetting(Settings.RESHUFFLE_ACCESS, AccessRestriction.READ);
helper.setSlot(SOURCE_DRIVE, 0, sourceCell);
})
.thenWaitUntil(
"wait for cancellation source contents",
20,
@@ -11,9 +11,11 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.common.util.Constants.NBT;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.config.ReshufflePhase;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.security.MachineSource;
import appeng.api.networking.security.ReshuffleActionSource;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.IMEMonitor;
@@ -34,7 +36,8 @@ public class ReshuffleTask {
// slowdown because working too fast, nobody gonna believe that real working
public static final long stacks_per_tick = 8;
private final BaseActionSource src;
private final ReshuffleActionSource src;
private final MachineSource rollbackSrc;
private final IStorageGrid sg;
private final AEStackTypeFilter typeFilters;
@@ -104,8 +107,9 @@ public class ReshuffleTask {
}
public ReshuffleTask(AEStackTypeFilter typeFilters, IStorageGrid sg, IItemList<IAEStack<?>> cantInject,
BaseActionSource src, boolean includeSubnets, boolean insertOrder) {
ReshuffleActionSource src, boolean includeSubnets, boolean insertOrder) {
this.src = src;
this.rollbackSrc = new MachineSource(src.via);
this.sg = sg;
this.cantInject = cantInject;
this.typeFilters = typeFilters;
@@ -170,7 +174,9 @@ public class ReshuffleTask {
while (i.hasNext()) {
final IMEInventoryHandler cellHandler = i.next();
if (cellHandler == null || cellHandler.isAutoCraftingInventory()) continue;
if (cellHandler == null || cellHandler.isAutoCraftingInventory()
|| extract && !cellHandler.getReshuffleAccess().hasPermission(AccessRestriction.READ))
continue;
final IAEStackType<?> currentType = cellHandler.getStackType();
final IMENetworkInventory<?> subnet = cellHandler.getExternalNetworkInventory();
if (subnet instanceof NetworkInventoryHandler nextNetwork) {
@@ -343,7 +349,7 @@ public class ReshuffleTask {
final IAEStack<?> stack = pending.stack.copy().setStackSize(amount);
IAEStack<?> rejected = stack;
try {
rejected = source.source.injectItems(stack, Actionable.MODULATE, this.src);
rejected = source.source.injectItems(stack, Actionable.MODULATE, this.rollbackSrc);
} catch (Exception e) {
AELog.error(e, "Failed to restore a storage reshuffle stack to its source");
}
@@ -22,6 +22,7 @@ import appeng.api.config.Actionable;
import appeng.api.config.IncludeExclude;
import appeng.api.config.StorageFilter;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.security.ReshuffleActionSource;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEInventoryHandler;
import appeng.api.storage.IMENetworkInventory;
@@ -99,7 +100,8 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
@Override
public T injectItems(final T input, final Actionable type, final BaseActionSource src) {
if (!this.canAccept(input)) {
if (!this.canAccept(input) || src instanceof ReshuffleActionSource
&& !this.getReshuffleAccess().hasPermission(AccessRestriction.WRITE)) {
return input;
}
@@ -108,7 +110,8 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
@Override
public T extractItems(final T request, final Actionable type, final BaseActionSource src) {
if (!this.hasReadAccess) {
if (!this.hasReadAccess || src instanceof ReshuffleActionSource
&& !this.getReshuffleAccess().hasPermission(AccessRestriction.READ)) {
return null;
}
if (this.isExtractFilterActive() && !this.myExtractPartitionList.isEmpty()) {
@@ -255,6 +258,11 @@ public class MEInventoryHandler<T extends IAEStack<T>> implements IMEInventoryHa
return isSticky || this.internal.getSticky();
}
@Override
public AccessRestriction getReshuffleAccess() {
return this.internal.getReshuffleAccess();
}
@Override
@SuppressWarnings("unchecked")
public IMENetworkInventory<T> getExternalNetworkInventory() {
@@ -138,6 +138,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, IFluidHan
this.config.registerSetting(Settings.SORT_BY, SortOrder.NAME);
this.config.registerSetting(Settings.VIEW_MODE, ViewItems.ALL);
this.config.registerSetting(Settings.SORT_DIRECTION, SortDir.ASCENDING);
this.config.registerSetting(Settings.RESHUFFLE_ACCESS, AccessRestriction.READ_WRITE);
this.setInternalPublicPowerStorage(true);
this.setInternalPowerFlow(AccessRestriction.WRITE);
}
@@ -244,7 +245,13 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, IFluidHan
return null;
}
final MEInventoryHandler ih = new MEInventoryHandler(h, h.getStackType());
final MEInventoryHandler ih = new MEInventoryHandler(h, h.getStackType()) {
@Override
public AccessRestriction getReshuffleAccess() {
return TileChest.this.getReshuffleAccess();
}
};
ih.setPriority(this.priority);
final MEMonitorHandler<StackType> g = new ChestMonitorHandler<StackType>(ih);
@@ -686,7 +693,14 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, IFluidHan
}
@Override
public void updateSetting(final IConfigManager manager, final Enum settingName, final Enum newValue) {}
public void updateSetting(final IConfigManager manager, final Enum settingName, final Enum newValue) {
this.markDirty();
}
@Override
public AccessRestriction getReshuffleAccess() {
return (AccessRestriction) this.config.getSetting(Settings.RESHUFFLE_ACCESS);
}
public boolean openGui(final EntityPlayer p, final ICellHandler ch, final ItemStack cell, final int side) {
for (IAEStackType<?> type : AEStackTypeRegistry.getAllTypes()) {
@@ -31,6 +31,8 @@ import net.minecraftforge.common.util.ForgeDirection;
import com.google.common.base.Optional;
import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Settings;
import appeng.api.config.Upgrades;
import appeng.api.implementations.tiles.IChestOrDrive;
import appeng.api.implementations.tiles.IColorableTile;
@@ -61,6 +63,8 @@ import appeng.api.storage.data.IAEStackType;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.api.util.DimensionalCoord;
import appeng.api.util.IConfigManager;
import appeng.api.util.IConfigurableObject;
import appeng.helpers.IPrimaryGuiIconProvider;
import appeng.helpers.IPriorityHost;
import appeng.items.AEBaseCell;
@@ -73,12 +77,14 @@ import appeng.tile.events.TileEventType;
import appeng.tile.grid.AENetworkInvTile;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.tile.inventory.InvOperation;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.IterationCounter;
import appeng.util.Platform;
import io.netty.buffer.ByteBuf;
public class TileDrive extends AENetworkInvTile
implements IChestOrDrive, IPriorityHost, IGridTickable, IColorableTile, IPrimaryGuiIconProvider {
public class TileDrive extends AENetworkInvTile implements IChestOrDrive, IPriorityHost, IGridTickable, IColorableTile,
IPrimaryGuiIconProvider, IConfigurableObject, IConfigManagerHost {
private static final int INV_SIZE = 10;
/**
@@ -93,6 +99,7 @@ public class TileDrive extends AENetworkInvTile
private final ICellHandler[] handlersBySlot = new ICellHandler[INV_SIZE];
private final MEInventoryHandler<IAEItemStack>[] invBySlot = new MEInventoryHandler[INV_SIZE];
private final BaseActionSource mySrc;
private final IConfigManager config = new ConfigManager(this);
private boolean isCached = false;
@SuppressWarnings("rawtypes")
private final Map<IAEStackType<?>, List<IMEInventoryHandler>> cellsMap = new IdentityHashMap<>();
@@ -110,6 +117,7 @@ public class TileDrive extends AENetworkInvTile
public TileDrive() {
this.mySrc = new MachineSource(this);
this.getProxy().setFlags(GridFlags.REQUIRE_CHANNEL);
this.config.registerSetting(Settings.RESHUFFLE_ACCESS, AccessRestriction.READ_WRITE);
}
@TileEvent(TileEventType.NETWORK_WRITE)
@@ -236,6 +244,7 @@ public class TileDrive extends AENetworkInvTile
@TileEvent(TileEventType.WORLD_NBT_READ)
public void readFromNBT_TileDrive(final NBTTagCompound data) {
this.isCached = false;
this.config.readFromNBT(data);
this.priority = data.getInteger("priority");
if (data.hasKey("paintedColor")) {
this.paintedColor = AEColor.fromOrdinal(data.getByte("paintedColor"));
@@ -245,6 +254,7 @@ public class TileDrive extends AENetworkInvTile
@TileEvent(TileEventType.WORLD_NBT_WRITE)
public void writeToNBT_TileDrive(final NBTTagCompound data) {
this.config.writeToNBT(data);
data.setInteger("priority", this.priority);
data.setByte("paintedColor", (byte) this.paintedColor.ordinal());
}
@@ -356,7 +366,8 @@ public class TileDrive extends AENetworkInvTile
final MEInventoryHandler<IAEItemStack> ih = new DriveWatcher<IAEItemStack>(
cell,
cell.getStackType());
cell.getStackType(),
this);
ih.setPriority(this.priority);
this.invBySlot[x] = ih;
this.cellsMap.get(type).add(ih);
@@ -378,8 +389,16 @@ public class TileDrive extends AENetworkInvTile
/// https://github.com/GTNewHorizons/Applied-Energistics-2-Unofficial/issues/1225
private static class DriveWatcher<T extends IAEStack<T>> extends MEInventoryHandler<T> {
public DriveWatcher(final IMEInventory<T> i, final IAEStackType<T> type) {
private final TileDrive drive;
public DriveWatcher(final IMEInventory<T> i, final IAEStackType<T> type, final TileDrive drive) {
super(i, type);
this.drive = drive;
}
@Override
public AccessRestriction getReshuffleAccess() {
return this.drive.getReshuffleAccess();
}
}
@@ -420,6 +439,21 @@ public class TileDrive extends AENetworkInvTile
}
}
@Override
public IConfigManager getConfigManager() {
return this.config;
}
@Override
public void updateSetting(final IConfigManager manager, final Enum settingName, final Enum newValue) {
this.markDirty();
}
@Override
public AccessRestriction getReshuffleAccess() {
return (AccessRestriction) this.config.getSetting(Settings.RESHUFFLE_ACCESS);
}
@Override
public void saveChanges(final IMEInventory cellInventory) {
this.worldObj.markTileEntityChunkModified(this.xCoord, this.yCoord, this.zCoord, this);
@@ -720,6 +720,11 @@ gui.tooltips.appliedenergistics2.ReshuffleIncludeSubnetsOff=Disabled - only the
gui.tooltips.appliedenergistics2.ReshuffleInsertOrder=Insert order
gui.tooltips.appliedenergistics2.ReshuffleInsertOrderOn=Insert big stacks first
gui.tooltips.appliedenergistics2.ReshuffleInsertOrderOff=Insert small stacks first
gui.tooltips.appliedenergistics2.ReshuffleAccess=Storage Reshuffle Access
gui.tooltips.appliedenergistics2.ReshuffleReadWrite=Extract and insert
gui.tooltips.appliedenergistics2.ReshuffleWrite=Insert only - extraction denied
gui.tooltips.appliedenergistics2.ReshuffleNone=Extraction and insertion denied
gui.tooltips.appliedenergistics2.ReshuffleRead=Extract only - insertion denied
gui.tooltips.appliedenergistics2.OpenReshuffle=Open Reshuffle
gui.tooltips.appliedenergistics2.OpenReshuffleDesc=Open the Storage Reshuffle GUI
gui.tooltips.appliedenergistics2.OpenReshuffleOffDesc=No Storage Reshuffle block found on this network
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB