mirror of
https://github.com/GTNewHorizons/Applied-Energistics-2-Unofficial.git
synced 2026-11-13 17:04:17 +00:00
Add reshuffler access configuration (#1613)
This commit is contained in:
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 |
Reference in new issue
Block a user