mirror of
https://github.com/GTNewHorizons/Applied-Energistics-2-Unofficial.git
synced 2026-10-25 20:22:23 +00:00
Limit channels per controller face (#1638)
This commit is contained in:
1 parent
59c002bc5a
commit
3640653615
11 files changed
+493
-1
No files matched your search
@@ -37,6 +37,7 @@ dependencies {
|
||||
}
|
||||
compileOnly('curse.maven:rotarycraft-235596:4721191')
|
||||
compileOnly('com.github.GTNewHorizons:Baubles-Expanded:2.2.23-GTNH:dev')
|
||||
compileOnly('com.github.GTNewHorizons:RemoteIO:2.7.10:dev') { transitive = false }
|
||||
compileOnly("org.jetbrains:annotations:26.0.2")
|
||||
compileOnly("com.github.GTNewHorizons:Postea:1.2.6:dev")
|
||||
compileOnly("com.github.GTNewHorizons:InventoryBogoSorter:1.3.50-GTNH:dev")
|
||||
@@ -58,6 +59,7 @@ dependencies {
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:Postea:1.2.6:dev")
|
||||
runtimeOnlyNonPublishable('com.github.GTNewHorizons:waila:1.19.34:dev') {transitive = false}
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:DuraDisplay:1.4.6:dev")
|
||||
runtimeOnlyNonPublishable('com.github.GTNewHorizons:RemoteIO:2.7.10:dev') { transitive = false }
|
||||
runtimeOnlyNonPublishable('com.github.GTNewHorizons:Baubles-Expanded:2.2.23-GTNH:dev')
|
||||
runtimeOnlyNonPublishable('thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev') {
|
||||
exclude module: "Baubles"
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package appeng.test.me;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGridHost;
|
||||
import appeng.me.GridConnection;
|
||||
import appeng.me.GridNode;
|
||||
import appeng.me.pathfinding.PathingCalculation;
|
||||
import appeng.test.mockme.MockGridBlock;
|
||||
import appeng.test.mockme.MockGridMachine;
|
||||
import appeng.tile.networking.TileController;
|
||||
|
||||
public class ControllerFaceChannelsFunctionalTest {
|
||||
|
||||
private final List<GridNode> nodes = new ArrayList<>();
|
||||
|
||||
@AfterEach
|
||||
public void destroyGrid() {
|
||||
for (final GridNode node : this.nodes) {
|
||||
node.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectionsOnTheSameControllerFaceShareItsChannelCapacity() throws Exception {
|
||||
final GridNode controller = this.node(new TileController(), GridFlags.CANNOT_CARRY, GridFlags.DENSE_CAPACITY);
|
||||
|
||||
for (int i = 0; i < 33; i++) {
|
||||
new GridConnection(
|
||||
controller,
|
||||
this.node(new MockGridMachine(), GridFlags.REQUIRE_CHANNEL),
|
||||
ForgeDirection.NORTH);
|
||||
}
|
||||
new GridConnection(
|
||||
controller,
|
||||
this.node(new MockGridMachine(), GridFlags.REQUIRE_CHANNEL),
|
||||
ForgeDirection.SOUTH);
|
||||
|
||||
final PathingCalculation calculation = new PathingCalculation(controller.getGrid());
|
||||
calculation.compute();
|
||||
|
||||
assertEquals(33, calculation.getChannelsInUse());
|
||||
}
|
||||
|
||||
private GridNode node(final IGridHost machine, final GridFlags... flags) {
|
||||
final EnumSet<GridFlags> nodeFlags = flags.length == 0 ? EnumSet.noneOf(GridFlags.class)
|
||||
: EnumSet.copyOf(Arrays.asList(flags));
|
||||
final GridNode node = new GridNode(new MockGridBlock() {
|
||||
|
||||
@Override
|
||||
public IGridHost getMachine() {
|
||||
return machine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<GridFlags> getFlags() {
|
||||
return nodeFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFlag(final GridFlags flag) {
|
||||
return nodeFlags.contains(flag);
|
||||
}
|
||||
});
|
||||
node.updateState();
|
||||
this.nodes.add(node);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
package appeng.gametests.compatibility.appliedenergistics2_remoteio;
|
||||
|
||||
import static appeng.gametests.AEGameTestHelpers.assertActive;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import com.gtnewhorizons.horizonqa.api.GameTestHelper;
|
||||
import com.gtnewhorizons.horizonqa.api.TestPos;
|
||||
import com.gtnewhorizons.horizonqa.api.TickCallbackHandle;
|
||||
import com.gtnewhorizons.horizonqa.api.annotation.GameTest;
|
||||
import com.gtnewhorizons.horizonqa.api.annotation.GameTestHolder;
|
||||
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.core.AppEng;
|
||||
import appeng.tile.networking.TileController;
|
||||
import appeng.tile.storage.TileDrive;
|
||||
import remoteio.common.core.TransferType;
|
||||
import remoteio.common.lib.DimensionalCoords;
|
||||
import remoteio.common.lib.ModBlocks;
|
||||
import remoteio.common.lib.ModItems;
|
||||
import remoteio.common.tile.TileRemoteInterface;
|
||||
|
||||
@GameTestHolder(value = AppEng.MOD_ID, requiredMods = "RIO")
|
||||
public class RemoteIOChannelCompatibilityTests {
|
||||
|
||||
private static final int CHANNEL_DEVICE_COUNT = 33;
|
||||
|
||||
@GameTest(template = "compatibility/remoteio/dense_cable", timeoutTicks = 100)
|
||||
public static void denseCableCarriesThirtyTwoChannels(GameTestHelper helper) {
|
||||
TileController controller = helper.assertTileEntityPresent(TileController.class, "controller");
|
||||
List<TileDrive> devices = channelDevices(helper, "channel_device_", CHANNEL_DEVICE_COUNT);
|
||||
connectRemoteInterface(helper, "remote_interface");
|
||||
|
||||
assertActiveDevices(helper, controller, devices, 32);
|
||||
}
|
||||
|
||||
@GameTest(template = "compatibility/remoteio/same_controller_face", timeoutTicks = 100)
|
||||
public static void sameControllerFaceSharesThirtyTwoChannels(GameTestHelper helper) {
|
||||
TileController controller = helper.assertTileEntityPresent(TileController.class, "controller");
|
||||
List<TileDrive> devices = dualChannelDevices(helper);
|
||||
connectRemoteInterface(helper, "remote_interface_a");
|
||||
connectRemoteInterface(helper, "remote_interface_b");
|
||||
|
||||
assertActiveDevices(helper, controller, devices, 32);
|
||||
}
|
||||
|
||||
@GameTest(template = "compatibility/remoteio/different_controller_faces", timeoutTicks = 100)
|
||||
public static void differentControllerFacesHaveIndependentChannels(GameTestHelper helper) {
|
||||
TileController controller = helper.assertTileEntityPresent(TileController.class, "controller");
|
||||
moveSecondRemoteInterfaceToNorthSide(helper);
|
||||
List<TileDrive> devices = dualChannelDevices(helper);
|
||||
connectRemoteInterface(helper, "remote_interface_a");
|
||||
connectRemoteInterface(helper, "remote_interface_b_north");
|
||||
|
||||
assertActiveDevices(helper, controller, devices, 33);
|
||||
}
|
||||
|
||||
private static List<TileDrive> dualChannelDevices(GameTestHelper helper) {
|
||||
List<TileDrive> devices = channelDevices(helper, "channel_device_a_", 16);
|
||||
devices.addAll(channelDevices(helper, "channel_device_b_", 17));
|
||||
return devices;
|
||||
}
|
||||
|
||||
private static List<TileDrive> channelDevices(GameTestHelper helper, String labelPrefix, int count) {
|
||||
List<TileDrive> devices = new ArrayList<>();
|
||||
for (int i = 1; i <= count; i++) {
|
||||
devices.add(helper.assertTileEntityPresent(TileDrive.class, labelPrefix + i));
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
private static void connectRemoteInterface(GameTestHelper helper, String label) {
|
||||
TileRemoteInterface remoteInterface = helper.assertTileEntityPresent(TileRemoteInterface.class, label);
|
||||
TestPos controller = helper.absolute("controller");
|
||||
remoteInterface.transferChips
|
||||
.setInventorySlotContents(0, new ItemStack(ModItems.transferChip, 1, TransferType.NETWORK_AE));
|
||||
remoteInterface.setRemotePosition(
|
||||
new DimensionalCoords(helper.getWorld(), controller.x(), controller.y(), controller.z()));
|
||||
}
|
||||
|
||||
private static void moveSecondRemoteInterfaceToNorthSide(GameTestHelper helper) {
|
||||
helper.destroyBlock("remote_interface_b");
|
||||
helper.destroyBlock("remote_interface_b_north");
|
||||
helper.setBlock("channel_device_b_4", AEApi.instance().definitions().blocks().drive().maybeBlock().get());
|
||||
helper.setBlock("remote_interface_b_north", ModBlocks.remoteInterface);
|
||||
}
|
||||
|
||||
private static void assertActiveDevices(GameTestHelper helper, TileController controller, List<TileDrive> devices,
|
||||
int expectedActive) {
|
||||
Runnable assertAllocation = () -> {
|
||||
assertActive(helper, controller.getProxy(), "Controller should become active");
|
||||
IGridNode controllerNode = controller.getProxy().getNode();
|
||||
int active = 0;
|
||||
for (TileDrive device : devices) {
|
||||
IGridNode deviceNode = device.getProxy().getNode();
|
||||
helper.assertNotNull(deviceNode, "Every ME drive should have a grid node");
|
||||
helper.assertSame(
|
||||
controllerNode.getGrid(),
|
||||
deviceNode.getGrid(),
|
||||
"Every ME drive should join the controller grid through RemoteIO");
|
||||
if (deviceNode.isActive()) {
|
||||
active++;
|
||||
}
|
||||
}
|
||||
helper.assertEquals(expectedActive, active, "Unexpected number of active devices");
|
||||
};
|
||||
TickCallbackHandle stableAllocation = helper
|
||||
.onEachTickDisabled("RemoteIO channel allocation remains stable", assertAllocation);
|
||||
|
||||
helper.startSequence().thenWaitUntil("wait for RemoteIO channel allocation", 60, assertAllocation)
|
||||
.thenExecute("begin stable channel-allocation observation", stableAllocation::enable).thenIdle(20)
|
||||
.thenExecute("finish stable channel-allocation observation", stableAllocation::disable).thenSucceed();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,16 +12,23 @@ package appeng.me.pathfinding;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import appeng.api.networking.GridFlags;
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.IGridMultiblock;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.features.AEFeature;
|
||||
import appeng.me.GridConnection;
|
||||
import appeng.me.GridNode;
|
||||
import appeng.tile.networking.TileController;
|
||||
@@ -34,13 +41,16 @@ import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
||||
* <p>
|
||||
* First, a BFS is performed starting from the controllers. This establishes a tree that connects all path items to a
|
||||
* controller. As nodes that require channels are visited, they are assigned a channel if possible. This is done by
|
||||
* checking the channel count of a few key nodes (max 3) along the path.
|
||||
* checking the controller face and a few key nodes along the path.
|
||||
* <p>
|
||||
* Second, a DFS is performed to propagate the channel count upwards.
|
||||
*/
|
||||
public class PathingCalculation {
|
||||
|
||||
private static final int CONTROLLER_FACE_CHANNELS = 32;
|
||||
|
||||
private final IGrid grid;
|
||||
private final int controllerFaceCapacity;
|
||||
/**
|
||||
* Path items that are part of a multiblock that was already granted a channel.
|
||||
*/
|
||||
@@ -62,6 +72,10 @@ public class PathingCalculation {
|
||||
* are checked and updated.
|
||||
*/
|
||||
private final Reference2IntOpenHashMap<GridNode> channelBottlenecks = new Reference2IntOpenHashMap<>();
|
||||
/**
|
||||
* Associates every path item with the controller face that supplies its channels.
|
||||
*/
|
||||
private final Map<IPathItem, ControllerFace> controllerFaces = new IdentityHashMap<>();
|
||||
/**
|
||||
* Nodes that have been granted a channel during the BFS pass.
|
||||
*/
|
||||
@@ -80,13 +94,21 @@ public class PathingCalculation {
|
||||
*/
|
||||
public PathingCalculation(IGrid grid) {
|
||||
this.grid = grid;
|
||||
this.controllerFaceCapacity = AEConfig.instance.isFeatureEnabled(AEFeature.Channels) ? CONTROLLER_FACE_CHANNELS
|
||||
: Integer.MAX_VALUE;
|
||||
|
||||
// Add every outgoing connection of the controllers (that doesn't point to another controller) to the list.
|
||||
for (IGridNode node : grid.getMachines(TileController.class)) {
|
||||
visited.add((IPathItem) node);
|
||||
final Map<ForgeDirection, ControllerFace> faces = new EnumMap<>(ForgeDirection.class);
|
||||
for (var gcc : node.getConnections()) {
|
||||
var gc = (GridConnection) gcc;
|
||||
if (!(gc.getOtherSide(node).getMachine() instanceof TileController)) {
|
||||
controllerFaces.put(
|
||||
gc,
|
||||
faces.computeIfAbsent(
|
||||
gc.getDirection(node),
|
||||
ignored -> new ControllerFace(this.controllerFaceCapacity)));
|
||||
enqueue(gc, 0);
|
||||
gc.setControllerRoute((GridNode) node);
|
||||
}
|
||||
@@ -94,9 +116,15 @@ public class PathingCalculation {
|
||||
}
|
||||
for (IGridNode node : grid.getMachines(TileCreativeEnergyController.class)) {
|
||||
visited.add((IPathItem) node);
|
||||
final Map<ForgeDirection, ControllerFace> faces = new EnumMap<>(ForgeDirection.class);
|
||||
for (var gcc : node.getConnections()) {
|
||||
var gc = (GridConnection) gcc;
|
||||
if (!(gc.getOtherSide(node).getMachine() instanceof TileController)) {
|
||||
controllerFaces.put(
|
||||
gc,
|
||||
faces.computeIfAbsent(
|
||||
gc.getDirection(node),
|
||||
ignored -> new ControllerFace(this.controllerFaceCapacity)));
|
||||
enqueue(gc, 0);
|
||||
gc.setControllerRoute((GridNode) node);
|
||||
}
|
||||
@@ -143,6 +171,7 @@ public class PathingCalculation {
|
||||
if (!this.visited.contains(pi)) {
|
||||
// Set BFS parent.
|
||||
pi.setControllerRoute(i);
|
||||
this.controllerFaces.put(pi, this.controllerFaces.get(i));
|
||||
|
||||
if (pi.hasFlag(GridFlags.REQUIRE_CHANNEL)) {
|
||||
if (!this.multiblocksWithChannel.contains(pi)) {
|
||||
@@ -188,6 +217,11 @@ public class PathingCalculation {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ControllerFace controllerFace = this.controllerFaces.get(start);
|
||||
if (!controllerFace.canUseChannel()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the allocation is possible.
|
||||
GridNode pi = start;
|
||||
while (pi != null) {
|
||||
@@ -205,10 +239,29 @@ public class PathingCalculation {
|
||||
pi = pi.getHighestSimilarAncestor();
|
||||
}
|
||||
|
||||
controllerFace.useChannel();
|
||||
channelNodes.add(start);
|
||||
return true;
|
||||
}
|
||||
|
||||
static final class ControllerFace {
|
||||
|
||||
private final int capacity;
|
||||
private int usedChannels;
|
||||
|
||||
ControllerFace(final int capacity) {
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
boolean canUseChannel() {
|
||||
return this.usedChannels < this.capacity;
|
||||
}
|
||||
|
||||
void useChannel() {
|
||||
this.usedChannels++;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Object SUBTREE_END = new Object();
|
||||
|
||||
/**
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"format_version": 2,
|
||||
"size": [9, 1, 8],
|
||||
"palette": {
|
||||
"A": {"name": "RIO:tile.remote_interface", "meta": 0, "label": "Remote Interface"},
|
||||
"B": {"name": "appliedenergistics2:tile.BlockCableBus", "meta": 0, "label": "AE2 Cable and/or Bus"},
|
||||
"C": {"name": "appliedenergistics2:tile.BlockCreativeEnergyController", "meta": 1, "label": "ME Self-Powered Controller"},
|
||||
"D": {"name": "appliedenergistics2:tile.BlockDrive", "meta": 0, "label": "ME Drive"}
|
||||
},
|
||||
"layers": [
|
||||
[
|
||||
"....C....",
|
||||
".........",
|
||||
"....A....",
|
||||
"BBBBBBBBB",
|
||||
"DDDDDDDDD",
|
||||
"DDDDDDDDD",
|
||||
"DDDDDDDDD",
|
||||
"DDDDDD..."
|
||||
]
|
||||
],
|
||||
"annotations": {
|
||||
"labels": {
|
||||
"channel_device_1": [0, 0, 4],
|
||||
"channel_device_10": [0, 0, 5],
|
||||
"channel_device_11": [1, 0, 5],
|
||||
"channel_device_12": [2, 0, 5],
|
||||
"channel_device_13": [3, 0, 5],
|
||||
"channel_device_14": [4, 0, 5],
|
||||
"channel_device_15": [5, 0, 5],
|
||||
"channel_device_16": [6, 0, 5],
|
||||
"channel_device_17": [7, 0, 5],
|
||||
"channel_device_18": [8, 0, 5],
|
||||
"channel_device_19": [0, 0, 6],
|
||||
"channel_device_2": [1, 0, 4],
|
||||
"channel_device_20": [1, 0, 6],
|
||||
"channel_device_21": [2, 0, 6],
|
||||
"channel_device_22": [3, 0, 6],
|
||||
"channel_device_23": [4, 0, 6],
|
||||
"channel_device_24": [5, 0, 6],
|
||||
"channel_device_25": [6, 0, 6],
|
||||
"channel_device_26": [7, 0, 6],
|
||||
"channel_device_27": [8, 0, 6],
|
||||
"channel_device_28": [0, 0, 7],
|
||||
"channel_device_29": [1, 0, 7],
|
||||
"channel_device_3": [2, 0, 4],
|
||||
"channel_device_30": [2, 0, 7],
|
||||
"channel_device_31": [3, 0, 7],
|
||||
"channel_device_32": [4, 0, 7],
|
||||
"channel_device_33": [5, 0, 7],
|
||||
"channel_device_4": [3, 0, 4],
|
||||
"channel_device_5": [4, 0, 4],
|
||||
"channel_device_6": [5, 0, 4],
|
||||
"channel_device_7": [6, 0, 4],
|
||||
"channel_device_8": [7, 0, 4],
|
||||
"channel_device_9": [8, 0, 4],
|
||||
"controller": [4, 0, 0],
|
||||
"controller_face": [4, 0, 1],
|
||||
"dense_cable_1": [0, 0, 3],
|
||||
"dense_cable_2": [1, 0, 3],
|
||||
"dense_cable_3": [2, 0, 3],
|
||||
"dense_cable_4": [3, 0, 3],
|
||||
"dense_cable_5": [4, 0, 3],
|
||||
"dense_cable_6": [5, 0, 3],
|
||||
"dense_cable_7": [6, 0, 3],
|
||||
"dense_cable_8": [7, 0, 3],
|
||||
"dense_cable_9": [8, 0, 3],
|
||||
"remote_interface": [4, 0, 2]
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
+74
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"format_version": 2,
|
||||
"size": [15, 1, 9],
|
||||
"palette": {
|
||||
"A": {"name": "RIO:tile.remote_interface", "meta": 0, "label": "Remote Interface"},
|
||||
"B": {"name": "appliedenergistics2:tile.BlockCableBus", "meta": 0, "label": "AE2 Cable and/or Bus"},
|
||||
"C": {"name": "appliedenergistics2:tile.BlockCreativeEnergyController", "meta": 1, "label": "ME Self-Powered Controller"},
|
||||
"D": {"name": "appliedenergistics2:tile.BlockDrive", "meta": 0, "label": "ME Drive"}
|
||||
},
|
||||
"layers": [
|
||||
[
|
||||
".......C.......",
|
||||
"...............",
|
||||
".A...........A.",
|
||||
"BBBB.......BBBB",
|
||||
"DDDD.......DDDD",
|
||||
"DDDD.......DDDD",
|
||||
"DDDD.......DDDD",
|
||||
"DDDD.......DDDD",
|
||||
"...........D..."
|
||||
]
|
||||
],
|
||||
"annotations": {
|
||||
"labels": {
|
||||
"channel_device_a_1": [0, 0, 4],
|
||||
"channel_device_a_10": [1, 0, 6],
|
||||
"channel_device_a_11": [2, 0, 6],
|
||||
"channel_device_a_12": [3, 0, 6],
|
||||
"channel_device_a_13": [0, 0, 7],
|
||||
"channel_device_a_14": [1, 0, 7],
|
||||
"channel_device_a_15": [2, 0, 7],
|
||||
"channel_device_a_16": [3, 0, 7],
|
||||
"channel_device_a_2": [1, 0, 4],
|
||||
"channel_device_a_3": [2, 0, 4],
|
||||
"channel_device_a_4": [3, 0, 4],
|
||||
"channel_device_a_5": [0, 0, 5],
|
||||
"channel_device_a_6": [1, 0, 5],
|
||||
"channel_device_a_7": [2, 0, 5],
|
||||
"channel_device_a_8": [3, 0, 5],
|
||||
"channel_device_a_9": [0, 0, 6],
|
||||
"channel_device_b_1": [11, 0, 4],
|
||||
"channel_device_b_10": [12, 0, 6],
|
||||
"channel_device_b_11": [13, 0, 6],
|
||||
"channel_device_b_12": [14, 0, 6],
|
||||
"channel_device_b_13": [11, 0, 7],
|
||||
"channel_device_b_14": [12, 0, 7],
|
||||
"channel_device_b_15": [13, 0, 7],
|
||||
"channel_device_b_16": [14, 0, 7],
|
||||
"channel_device_b_17": [11, 0, 8],
|
||||
"channel_device_b_2": [12, 0, 4],
|
||||
"channel_device_b_3": [13, 0, 4],
|
||||
"channel_device_b_4": [13, 0, 2],
|
||||
"channel_device_b_5": [11, 0, 5],
|
||||
"channel_device_b_6": [12, 0, 5],
|
||||
"channel_device_b_7": [13, 0, 5],
|
||||
"channel_device_b_8": [14, 0, 5],
|
||||
"channel_device_b_9": [11, 0, 6],
|
||||
"controller": [7, 0, 0],
|
||||
"controller_face_a": [6, 0, 0],
|
||||
"controller_face_b": [8, 0, 0],
|
||||
"dense_cable_a_1": [0, 0, 3],
|
||||
"dense_cable_a_2": [1, 0, 3],
|
||||
"dense_cable_a_3": [2, 0, 3],
|
||||
"dense_cable_a_4": [3, 0, 3],
|
||||
"dense_cable_b_1": [11, 0, 3],
|
||||
"dense_cable_b_2": [12, 0, 3],
|
||||
"dense_cable_b_3": [13, 0, 3],
|
||||
"dense_cable_b_4": [14, 0, 3],
|
||||
"remote_interface_a": [1, 0, 2],
|
||||
"remote_interface_b": [13, 0, 2],
|
||||
"remote_interface_b_north": [14, 0, 4]
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
+72
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"format_version": 2,
|
||||
"size": [15, 1, 9],
|
||||
"palette": {
|
||||
"A": {"name": "RIO:tile.remote_interface", "meta": 0, "label": "Remote Interface"},
|
||||
"B": {"name": "appliedenergistics2:tile.BlockCableBus", "meta": 0, "label": "AE2 Cable and/or Bus"},
|
||||
"C": {"name": "appliedenergistics2:tile.BlockCreativeEnergyController", "meta": 1, "label": "ME Self-Powered Controller"},
|
||||
"D": {"name": "appliedenergistics2:tile.BlockDrive", "meta": 0, "label": "ME Drive"}
|
||||
},
|
||||
"layers": [
|
||||
[
|
||||
".......C.......",
|
||||
"...............",
|
||||
".A...........A.",
|
||||
"BBBB.......BBBB",
|
||||
"DDDD.......DDDD",
|
||||
"DDDD.......DDDD",
|
||||
"DDDD.......DDDD",
|
||||
"DDDD.......DDDD",
|
||||
"...........D..."
|
||||
]
|
||||
],
|
||||
"annotations": {
|
||||
"labels": {
|
||||
"channel_device_a_1": [0, 0, 4],
|
||||
"channel_device_a_10": [1, 0, 6],
|
||||
"channel_device_a_11": [2, 0, 6],
|
||||
"channel_device_a_12": [3, 0, 6],
|
||||
"channel_device_a_13": [0, 0, 7],
|
||||
"channel_device_a_14": [1, 0, 7],
|
||||
"channel_device_a_15": [2, 0, 7],
|
||||
"channel_device_a_16": [3, 0, 7],
|
||||
"channel_device_a_2": [1, 0, 4],
|
||||
"channel_device_a_3": [2, 0, 4],
|
||||
"channel_device_a_4": [3, 0, 4],
|
||||
"channel_device_a_5": [0, 0, 5],
|
||||
"channel_device_a_6": [1, 0, 5],
|
||||
"channel_device_a_7": [2, 0, 5],
|
||||
"channel_device_a_8": [3, 0, 5],
|
||||
"channel_device_a_9": [0, 0, 6],
|
||||
"channel_device_b_1": [11, 0, 4],
|
||||
"channel_device_b_10": [12, 0, 6],
|
||||
"channel_device_b_11": [13, 0, 6],
|
||||
"channel_device_b_12": [14, 0, 6],
|
||||
"channel_device_b_13": [11, 0, 7],
|
||||
"channel_device_b_14": [12, 0, 7],
|
||||
"channel_device_b_15": [13, 0, 7],
|
||||
"channel_device_b_16": [14, 0, 7],
|
||||
"channel_device_b_17": [11, 0, 8],
|
||||
"channel_device_b_2": [12, 0, 4],
|
||||
"channel_device_b_3": [13, 0, 4],
|
||||
"channel_device_b_4": [14, 0, 4],
|
||||
"channel_device_b_5": [11, 0, 5],
|
||||
"channel_device_b_6": [12, 0, 5],
|
||||
"channel_device_b_7": [13, 0, 5],
|
||||
"channel_device_b_8": [14, 0, 5],
|
||||
"channel_device_b_9": [11, 0, 6],
|
||||
"controller": [7, 0, 0],
|
||||
"controller_face_b": [7, 0, 1],
|
||||
"dense_cable_a_1": [0, 0, 3],
|
||||
"dense_cable_a_2": [1, 0, 3],
|
||||
"dense_cable_a_3": [2, 0, 3],
|
||||
"dense_cable_a_4": [3, 0, 3],
|
||||
"dense_cable_b_1": [11, 0, 3],
|
||||
"dense_cable_b_2": [12, 0, 3],
|
||||
"dense_cable_b_3": [13, 0, 3],
|
||||
"dense_cable_b_4": [14, 0, 3],
|
||||
"remote_interface_a": [1, 0, 2],
|
||||
"remote_interface_b": [13, 0, 2]
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
package appeng.me.pathfinding;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public final class PathingCalculationTest {
|
||||
|
||||
@Test
|
||||
public void controllerFaceEnforcesItsChannelCapacity() {
|
||||
final PathingCalculation.ControllerFace face = new PathingCalculation.ControllerFace(32);
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
assertTrue(face.canUseChannel());
|
||||
face.useChannel();
|
||||
}
|
||||
|
||||
assertFalse(face.canUseChannel());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user