Skip to content

Commit 99f8737

Browse files
committed
more work on list and tests
1 parent 47be64d commit 99f8737

File tree

2 files changed

+77
-40
lines changed

2 files changed

+77
-40
lines changed

src/main/java/gregtech/api/capability/impl/ItemHandlerList.java

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package gregtech.api.capability.impl;
22

3-
import it.unimi.dsi.fastutil.objects.Object2IntMap;
4-
53
import net.minecraft.item.ItemStack;
64
import net.minecraftforge.items.IItemHandler;
75
import net.minecraftforge.items.IItemHandlerModifiable;
@@ -10,6 +8,7 @@
108
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
119
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
1210
import it.unimi.dsi.fastutil.objects.Object2IntMap;
11+
import it.unimi.dsi.fastutil.objects.ObjectIterator;
1312
import org.jetbrains.annotations.NotNull;
1413

1514
import java.util.*;
@@ -22,19 +21,24 @@ public class ItemHandlerList extends AbstractList<IItemHandler> implements IItem
2221
private final Int2ObjectMap<IItemHandler> handlerBySlotIndex = new Int2ObjectOpenHashMap<>();
2322
private final Object2IntMap<IItemHandler> baseIndexOffset = new Object2IntArrayMap<>();
2423

25-
private final List<IItemHandler> handlerList = new ArrayList<>();
24+
public ItemHandlerList() {}
2625

27-
public ItemHandlerList(List<? extends IItemHandler> itemHandlerList) {
26+
public ItemHandlerList(Collection<? extends IItemHandler> itemHandlerList) {
2827
addAll(itemHandlerList);
2928
}
3029

30+
public ItemHandlerList(ItemHandlerList parent, IItemHandler... additional) {
31+
addAll(parent.getBackingHandlers());
32+
Collections.addAll(this, additional);
33+
}
34+
3135
public int getIndexOffset(IItemHandler handler) {
3236
return baseIndexOffset.getOrDefault(handler, -1);
3337
}
3438

3539
@Override
3640
public int getSlots() {
37-
return size();
41+
return handlerBySlotIndex.size();
3842
}
3943

4044
@Override
@@ -81,14 +85,19 @@ public ItemStack extractItem(int slot, int amount, boolean simulate) {
8185
return itemHandler.extractItem(slot - baseIndexOffset.getInt(itemHandler), amount, simulate);
8286
}
8387

88+
private boolean invalidSlot(int slot) {
89+
if (handlerBySlotIndex.isEmpty()) return false;
90+
return slot < 0 || slot >= handlerBySlotIndex.size();
91+
}
92+
8493
@NotNull
8594
public Collection<IItemHandler> getBackingHandlers() {
86-
return Collections.unmodifiableCollection(handlerList);
95+
return Collections.unmodifiableCollection(baseIndexOffset.keySet());
8796
}
8897

8998
@Override
9099
public int size() {
91-
return handlerList.size();
100+
return baseIndexOffset.size();
92101
}
93102

94103
@Override
@@ -99,12 +108,18 @@ public boolean add(IItemHandler handler) {
99108
}
100109

101110
@Override
102-
public void add(int index, IItemHandler element) {
103-
// Objects.checkIndex(index, size());
104-
if (handlerList.contains(element)) {
111+
public void add(int unused, IItemHandler element) {
112+
Objects.requireNonNull(element);
113+
if (baseIndexOffset.containsKey(element)) {
105114
throw new IllegalArgumentException("Attempted to add item handler " + element + " twice");
106115
}
107-
handlerList.add(index, element);
116+
if (element instanceof ItemHandlerList list) {
117+
// possible infinite recursion
118+
// throw instead?
119+
addAll(list);
120+
return;
121+
}
122+
108123
int offset = handlerBySlotIndex.size();
109124
baseIndexOffset.put(element, offset);
110125
for (int slotIndex = 0; slotIndex < element.getSlots(); slotIndex++) {
@@ -114,33 +129,48 @@ public void add(int index, IItemHandler element) {
114129

115130
@Override
116131
public IItemHandler get(int index) {
117-
return handlerList.get(index);
132+
if (invalidIndex(index)) throw new IndexOutOfBoundsException();
133+
ObjectIterator<IItemHandler> itr = baseIndexOffset.keySet().iterator();
134+
itr.skip(index); // skip n-1 elements
135+
return itr.next(); // get nth element
118136
}
119137

120138
@Override
121139
public IItemHandler remove(int index) {
122-
// Objects.checkIndex(index, size());
123-
var handler2 = get(index);
124-
int offset2 = baseIndexOffset.getInt(handler2);
125-
126-
for (int i = index; i < size(); i++) {
127-
int offset = baseIndexOffset.removeInt(get(i));
128-
for (int j = 0; j < get(i).getSlots(); j++) {
129-
handlerBySlotIndex.remove(offset + j);
130-
}
140+
if (invalidIndex(index)) {
141+
throw new IndexOutOfBoundsException();
131142
}
132143

133-
var removed = handlerList.remove(index);
134-
for (var handler : handlerList) {
135-
if (baseIndexOffset.containsKey(handler))
136-
continue;
144+
IItemHandler handler = get(index);
137145

138-
int offset = handlerBySlotIndex.size();
139-
baseIndexOffset.put(handler, offset);
140-
for (int i = 0; i < handler.getSlots(); i++) {
141-
handlerBySlotIndex.put(offset + i, handler);
146+
// remove handler
147+
int lower = baseIndexOffset.removeInt(handler);
148+
149+
// remove slot indices
150+
int upper = lower + handler.getSlots();
151+
for (int i = lower; i < upper; i++) {
152+
handlerBySlotIndex.remove(i);
153+
}
154+
155+
// update slot indices ahead of the removed handler
156+
for (int slot = upper; slot < getSlots() + handler.getSlots(); slot++) {
157+
IItemHandler remove = handlerBySlotIndex.remove(slot);
158+
handlerBySlotIndex.put(slot - upper, remove);
159+
}
160+
161+
// update handlers ahead of the removed handler
162+
for (IItemHandler h : baseIndexOffset.keySet()) {
163+
int offset = baseIndexOffset.getInt(h);
164+
if (offset > lower) {
165+
baseIndexOffset.put(h, offset - handler.getSlots());
142166
}
143167
}
144-
return removed;
168+
169+
return handler;
170+
}
171+
172+
public boolean invalidIndex(int index) {
173+
if (baseIndexOffset.isEmpty()) return false;
174+
return index < 0 || index >= baseIndexOffset.size();
145175
}
146176
}

src/test/java/gregtech/api/capability/impl/ItemHandlerListTest.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
import gregtech.Bootstrap;
44

5+
import net.minecraftforge.items.IItemHandler;
56
import net.minecraftforge.items.ItemStackHandler;
67

78
import org.hamcrest.MatcherAssert;
89
import org.junit.jupiter.api.BeforeAll;
910
import org.junit.jupiter.api.Test;
1011

11-
import java.util.Collections;
12+
import java.util.Objects;
1213

1314
public class ItemHandlerListTest {
1415

@@ -19,18 +20,24 @@ public static void bootstrap() {
1920

2021
@Test
2122
public void testListOperations() {
22-
var list = new ItemHandlerList(Collections.emptyList());
23+
var list = new ItemHandlerList();
24+
ItemStackHandler firstHandler = new ItemStackHandler(16);
25+
ItemStackHandler secondHandler = new ItemStackHandler(16);
2326

2427
// test add
25-
list.add(new ItemStackHandler(16));
26-
// MatcherAssert.assertThat("size is wrong", list.getSlots() == 16);
27-
list.add(new ItemStackHandler(16));
28-
// MatcherAssert.assertThat("size is wrong", list.getSlots() == 32);
29-
// MatcherAssert.assertThat("size is wrong", list.size() == 2);
28+
list.add(firstHandler);
29+
MatcherAssert.assertThat("wrong number of slots!", list.getSlots() == 16);
30+
MatcherAssert.assertThat("wrong number of handlers!", list.size() == 1);
31+
list.add(secondHandler);
32+
MatcherAssert.assertThat("wrong number of slots!", list.getSlots() == 32);
33+
MatcherAssert.assertThat("wrong number of handlers!", list.size() == 2);
3034

3135
// test removal
32-
list.remove(0);
33-
// MatcherAssert.assertThat("size is wrong", list.getSlots() == 16);
34-
// MatcherAssert.assertThat("size is wrong", list.size() == 1);
36+
IItemHandler removed = list.remove(0);
37+
MatcherAssert.assertThat("wrong number of slots!", list.getSlots() == 16);
38+
MatcherAssert.assertThat("wrong number of handlers!", list.size() == 1);
39+
MatcherAssert.assertThat("removed handler is not the first handler!", Objects.equals(removed, firstHandler));
40+
int newIndex = list.getIndexOffset(secondHandler);
41+
MatcherAssert.assertThat("second handler was not updated!", newIndex == 0);
3542
}
3643
}

0 commit comments

Comments
 (0)