Skip to content

Commit 670d34b

Browse files
committed
Reduce memory impact of empty components by just using a single empty instance and initializing as needed
1 parent 8a06989 commit 670d34b

37 files changed

+318
-311
lines changed

src/api/java/mekanism/api/chemical/BasicChemicalTank.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,10 @@ public long setStackSize(long amount, Action action) {
185185
@Override
186186
public long growStack(long amount, Action action) {
187187
long current = getStored();
188-
if (amount > 0) {
188+
if (current == 0) {
189+
//"Fail quick" if our stack is empty, so we can't grow it
190+
return 0;
191+
} else if (amount > 0) {
189192
//Cap adding amount at how much we need, so that we don't risk long overflow
190193
amount = Math.min(Math.min(amount, getNeeded()), getRate(null));
191194
} else if (amount < 0) {

src/api/java/mekanism/api/chemical/IChemicalTank.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ default long setStackSize(long amount, Action action) {
220220
*/
221221
default long growStack(long amount, Action action) {
222222
long current = getStored();
223-
if (amount > 0) {
223+
if (current == 0) {
224+
//"Fail quick" if our stack is empty, so we can't grow it
225+
return 0;
226+
} else if (amount > 0) {
224227
//Cap adding amount at how much we need, so that we don't risk long overflow
225228
amount = Math.min(amount, getNeeded());
226229
}

src/api/java/mekanism/api/fluid/IExtendedFluidTank.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@ default int setStackSize(int amount, Action action) {
167167
*/
168168
default int growStack(int amount, Action action) {
169169
int current = getFluidAmount();
170-
if (amount > 0) {
170+
if (current == 0) {
171+
//"Fail quick" if our stack is empty, so we can't grow it
172+
return 0;
173+
} else if (amount > 0) {
171174
//Cap adding amount at how much we need, so that we don't risk integer overflow
172175
amount = Math.min(amount, getNeeded());
173176
}

src/api/java/mekanism/api/inventory/IInventorySlot.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,10 @@ default int setStackSize(int amount, Action action) {
235235
*/
236236
default int growStack(int amount, Action action) {
237237
int current = getCount();
238-
if (amount > 0) {
238+
if (current == 0) {
239+
//"Fail quick" if our stack is empty, so we can't grow it
240+
return 0;
241+
} else if (amount > 0) {
239242
//Cap adding amount at how much we need, so that we don't risk integer overflow
240243
amount = Math.min(amount, getLimit(getStack()));
241244
}

src/main/java/mekanism/common/attachments/containers/ComponentBackedContainer.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package mekanism.common.attachments.containers;
22

3-
import java.util.function.Supplier;
43
import mekanism.api.IContentsListener;
5-
import net.minecraft.core.component.DataComponentType;
4+
import mekanism.api.annotations.NothingNullByDefault;
65
import net.minecraft.world.item.ItemStack;
7-
import org.jetbrains.annotations.Nullable;
86

7+
@NothingNullByDefault
98
public abstract class ComponentBackedContainer<TYPE, ATTACHED extends IAttachedContainers<TYPE, ATTACHED>> implements IContentsListener {
109

1110
protected final ItemStack attachedTo;
@@ -20,37 +19,39 @@ protected ComponentBackedContainer(ItemStack attachedTo, int containerIndex) {
2019

2120
protected abstract boolean isEmpty(TYPE value);
2221

23-
protected abstract Supplier<? extends DataComponentType<ATTACHED>> dataComponentType();
22+
protected abstract ContainerType<?, ATTACHED, ?> containerType();
2423

25-
@Nullable
2624
protected ATTACHED getAttached() {
27-
return attachedTo.get(dataComponentType());
25+
return containerType().getOrEmpty(attachedTo);
2826
}
2927

3028
protected TYPE getContents(ATTACHED attached) {
31-
return attached.get(containerIndex);
29+
return attached.getOrDefault(containerIndex);
3230
}
3331

34-
protected void setContents(TYPE value) {
35-
//TODO - 1.20.5: Comment about why we have the overload that accepts attachedItems
36-
ATTACHED attached = getAttached();
37-
if (attached != null) {
38-
setContents(attached, value);
32+
protected void setContents(ATTACHED attached, TYPE value) {
33+
//If we don't actually have an attachment present yet, we need to ensure we try to create a new one
34+
if (attached.isEmpty()) {
35+
//If we don't have an attachment, attempt to create a new one
36+
attached = containerType().createNewAttachment(attachedTo);
37+
if (attached.isEmpty()) {
38+
//If we can't figure out how to handle the attachment for the item, just exit
39+
// Note: We don't need to consider removing an existing attachment as we know we don't have one
40+
return;
41+
}
42+
}
43+
if (shouldUpdate(attached, value)) {
44+
attachedTo.set(containerType().getComponentType(), attached.with(containerIndex, copy(value)));
45+
onContentsChanged();
3946
}
40-
//TODO - 1.20.5: Else initialize to whatever the default size is meant to be?
41-
// I think we might always end up actually doing so when accessing this from the container type?
42-
// Though maybe not if it isn't going through capability systems
4347
}
4448

45-
protected void setContents(ATTACHED attached, TYPE value) {
49+
protected boolean shouldUpdate(ATTACHED attached, TYPE value) {
4650
//If both stacks are empty we don't do anything
47-
if (!isEmpty(value) || !isEmpty(getContents(attached))) {
48-
//TODO - 1.20.5: Do we want to do a matches check instead of just seeing if both are empty
49-
// Or maybe only do that in the non overloaded setStack so as a way to potentially avoid the extra lookup here when we know
50-
// we only call this method if something has changed
51-
attachedTo.set(dataComponentType(), attached.with(containerIndex, copy(value)));
52-
onContentsChanged();
53-
}
51+
//TODO - 1.20.5: Do we want to do a matches check instead of just seeing if both are empty
52+
// Or maybe only do that in the non overloaded setStack so as a way to potentially avoid the extra lookup here when we know
53+
// we only call this method if something has changed
54+
return !isEmpty(value) || !isEmpty(getContents(attached));
5455
}
5556

5657
@Override

src/main/java/mekanism/common/attachments/containers/ComponentBackedHandler.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package mekanism.common.attachments.containers;
22

33
import java.util.Arrays;
4-
import java.util.Collections;
54
import java.util.List;
65
import mekanism.api.IContentsListener;
76
import mekanism.api.annotations.NothingNullByDefault;
@@ -14,33 +13,41 @@
1413
public abstract class ComponentBackedHandler<TYPE, CONTAINER extends INBTSerializable<CompoundTag>, ATTACHED extends IAttachedContainers<TYPE, ATTACHED>>
1514
implements IContentsListener {
1615

17-
private final List<CONTAINER> containers;
1816
protected final ItemStack attachedTo;
17+
private final int totalContainers;
18+
19+
@Nullable
20+
private List<CONTAINER> containers;
1921
private int numNotInitialized;
2022

2123
//TODO - 1.20.5: Do we want to validate slot indices are within range?
22-
protected ComponentBackedHandler(ItemStack attachedTo) {
24+
protected ComponentBackedHandler(ItemStack attachedTo, int totalContainers) {
2325
this.attachedTo = attachedTo;
24-
ATTACHED attached = getAttached();
25-
if (attached == null || attached.isEmpty()) {
26-
//TODO - 1.20.5: Is this meant to be zero if there is no attachment, or is it meant to be what the default is?
27-
numNotInitialized = 0;
28-
containers = Collections.emptyList();
29-
} else {
30-
numNotInitialized = attached.size();
31-
//Note: Use an Arrays#asList to allow for null elements and force it to be the size we want it to be
32-
containers = Arrays.asList((CONTAINER[]) new INBTSerializable[numNotInitialized]);
33-
}
26+
this.totalContainers = totalContainers;
3427
}
3528

3629
protected abstract ContainerType<CONTAINER, ATTACHED, ?> containerType();
3730

38-
@Nullable
3931
protected ATTACHED getAttached() {
40-
return attachedTo.get(containerType().getComponentType());
32+
return containerType().getOrEmpty(attachedTo);
33+
}
34+
35+
protected TYPE getContents(int index) {
36+
return getAttached().getOrDefault(index);
37+
}
38+
39+
private List<CONTAINER> containers() {
40+
//Lazily initialize the list of containers
41+
if (containers == null) {
42+
//Note: Use an Arrays#asList to allow for null elements and force it to be the size we want it to be
43+
containers = Arrays.asList((CONTAINER[]) new INBTSerializable[totalContainers]);
44+
numNotInitialized = totalContainers;
45+
}
46+
return containers;
4147
}
4248

4349
public List<CONTAINER> getContainers() {
50+
List<CONTAINER> containers = containers();
4451
//Ensure all our containers are initialized. This short circuits if they are, and if they aren't it initializes any ones that haven't been initialized yet
4552
for (int i = 0, size = containers.size(); numNotInitialized > 0 && i < size; i++) {
4653
if (containers.get(i) == null) {
@@ -51,22 +58,21 @@ public List<CONTAINER> getContainers() {
5158
}
5259

5360
private CONTAINER initializeContainer(int index) {
54-
//TODO - 1.20.5: ??
61+
//Create a new container for the given index, and set it as initialized
5562
CONTAINER container = containerType().createContainer(attachedTo, index);
56-
containers.set(index, container);
63+
containers().set(index, container);
5764
numNotInitialized--;
5865
return container;
5966
}
6067

6168
protected CONTAINER getContainer(int index) {
62-
CONTAINER container = containers.get(index);
69+
CONTAINER container = containers().get(index);
6370
//Lazily initialize the containers
6471
return container == null ? initializeContainer(index) : container;
6572
}
6673

6774
protected int containerCount() {
68-
ATTACHED attached = getAttached();
69-
return attached == null ? 0 : attached.size();
75+
return totalContainers;
7076
}
7177

7278
@Override

0 commit comments

Comments
 (0)