Skip to content

Commit

Permalink
feat: ✨ Added support to compress / uncompress items with nbt (compon…
Browse files Browse the repository at this point in the history
…ents) to Compression upgrade
  • Loading branch information
P3pp3rF1y committed Jan 24, 2025
1 parent ed9be91 commit 9931945
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 62 deletions.
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ loader_version_range=[4,)
mod_id=sophisticatedstorage
mod_name=Sophisticated Storage
mod_license=GNU General Public License v3.0
mod_version=1.2.10
mod_version=1.2.11
mod_group_id=sophisticatedstorage
mod_authors=P3pp3rF1y, Ridanisaurus
mod_description=Fancy and functional storage containers.
Expand All @@ -35,7 +35,7 @@ jade_cf_file_id=5109393
chipped_cf_file_id=5506938
resourcefullib_cf_file_id=5483169
athena_cf_file_id=5431579
sc_version=[1.21.1-1.1.2,1.22)
sc_version=[1.21.1-1.1.6,1.22)
sb_version=[1.21,1.22)

# publish
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private void calculateStacks(boolean initial) {
}

int lastNonEmptySlot = getLastNonEmptySlot(existingStacks);
setSlotDefinitions(getSlotDefinitions(existingStacks.get(lastNonEmptySlot).getItem(), lastNonEmptySlot, existingStacks), initial);
setSlotDefinitions(getSlotDefinitions(existingStacks.get(lastNonEmptySlot), lastNonEmptySlot, existingStacks), initial);

compactInternalSlots();
updateCalculatedStacks();
Expand All @@ -88,21 +88,21 @@ private Integer getLastNonEmptySlot(Map<Integer, ItemStack> existingStacks) {
return -1;
}

private Map<Integer, SlotDefinition> getSlotDefinitions(Item firstItem, int lastSlot, Map<Integer, ItemStack> existingStacks) {
private Map<Integer, SlotDefinition> getSlotDefinitions(ItemStack firstItem, int lastSlot, Map<Integer, ItemStack> existingStacks) {
Map<Integer, SlotDefinition> ret = new HashMap<>();
addPreviousItems(ret, lastSlot, firstItem);

Item prevItem = firstItem;
ItemStack prevItem = firstItem;
for (int slot = lastSlot; slot >= slotRange.firstSlot(); slot--) {
if (existingStacks.containsKey(slot) && existingStacks.get(slot).getItem() != prevItem) {
if (existingStacks.containsKey(slot) && !ItemStack.isSameItemSameComponents(existingStacks.get(slot), prevItem)) {
ret.clear(); //clearing any compressible definition added before as the compression should no longer compress if there are incompatible items present
break;
} else {
Optional<RecipeHelper.CompactingShape> compressionShape = getCompressionShape(prevItem);
if (compressionShape.isPresent()) {
RecipeHelper.CompactingShape shape = compressionShape.get();
ret.put(slot, new SlotDefinition(prevItem, shape.getNumberOfIngredients(), true));
prevItem = RecipeHelper.getCompactingResult(prevItem, shape).getResult().getItem();
prevItem = RecipeHelper.getCompactingResult(prevItem, shape).getResult();
} else {
ret.put(slot, new SlotDefinition(prevItem, 1, true));
break;
Expand All @@ -120,7 +120,7 @@ private void updateSlotLimits(Map<Integer, SlotDefinition> definitions) {
int totalLimit = 0;
for (int slot = slotRange.firstSlot(); slot < slotRange.firstSlot() + slotRange.numberOfSlots(); slot++) {
if (definitions.containsKey(slot) && definitions.get(slot).isAccessible()) {
totalLimit = intMaxCappedAddition(parent.getBaseStackLimit(new ItemStack(definitions.get(slot).item)), intMaxCappedMultiply(definitions.get(slot).prevSlotMultiplier, totalLimit));
totalLimit = intMaxCappedAddition(parent.getBaseStackLimit(definitions.get(slot).item), intMaxCappedMultiply(definitions.get(slot).prevSlotMultiplier, totalLimit));

definitions.get(slot).setSlotLimit(totalLimit);
}
Expand All @@ -143,7 +143,7 @@ private void updateCalculatedStacks() {
totalCalculated = Integer.MAX_VALUE / slotDefinition.prevSlotMultiplier() < totalCalculated ? Integer.MAX_VALUE : totalCalculated * slotDefinition.prevSlotMultiplier();
totalCalculated = Integer.MAX_VALUE - internalCount < totalCalculated ? Integer.MAX_VALUE : totalCalculated + internalCount;

ItemStack calculatedStack = new ItemStack(slotDefinition.item(), totalCalculated);
ItemStack calculatedStack = slotDefinition.item().copyWithCount(totalCalculated);

int internalLimit = parent.getBaseStackLimit(calculatedStack);
int maxStackSize = calculatedStack.getMaxStackSize();
Expand Down Expand Up @@ -184,7 +184,7 @@ private void updateInaccessibleAndCompressible(Map<Integer, SlotDefinition> defi
for (int slot = slotRange.firstSlot(); slot < slotRange.firstSlot() + slotRange.numberOfSlots(); slot++) {
definitions.computeIfAbsent(slot, s -> {
if (existingStacks.containsKey(s)) {
return new SlotDefinition(existingStacks.get(s).getItem(), 1, true);
return new SlotDefinition(existingStacks.get(s), 1, true);
}
return SlotDefinition.inaccesible();
});
Expand All @@ -203,31 +203,31 @@ private void clearCollections() {
parent.onFilterItemsChanged();
}

private Optional<RecipeHelper.CompactingShape> getCompressionShape(Item item) {
Set<RecipeHelper.CompactingShape> compactingShapes = RecipeHelper.getItemCompactingShapes(item);
private Optional<RecipeHelper.CompactingShape> getCompressionShape(ItemStack stack) {
Set<RecipeHelper.CompactingShape> compactingShapes = RecipeHelper.getItemCompactingShapes(stack);

if (compactingShapes.contains(RecipeHelper.CompactingShape.THREE_BY_THREE_UNCRAFTABLE)) {
return Optional.of(RecipeHelper.CompactingShape.THREE_BY_THREE_UNCRAFTABLE);
} else if (compactingShapes.contains(RecipeHelper.CompactingShape.TWO_BY_TWO_UNCRAFTABLE)) {
return Optional.of(RecipeHelper.CompactingShape.TWO_BY_TWO_UNCRAFTABLE);
} else if (compactingShapes.contains(RecipeHelper.CompactingShape.THREE_BY_THREE)) {
Item compressedItem = RecipeHelper.getCompactingResult(item, RecipeHelper.CompactingShape.THREE_BY_THREE).getResult().getItem();
Item compressedItem = RecipeHelper.getCompactingResult(stack, RecipeHelper.CompactingShape.THREE_BY_THREE).getResult().getItem();
return getDecompressionResultFromConfig(compressedItem).isPresent() ? Optional.of(RecipeHelper.CompactingShape.THREE_BY_THREE_UNCRAFTABLE) : Optional.empty();
} else if (compactingShapes.contains(RecipeHelper.CompactingShape.TWO_BY_TWO)) {
Item compressedItem = RecipeHelper.getCompactingResult(item, RecipeHelper.CompactingShape.TWO_BY_TWO).getResult().getItem();
Item compressedItem = RecipeHelper.getCompactingResult(stack, RecipeHelper.CompactingShape.TWO_BY_TWO).getResult().getItem();
return getDecompressionResultFromConfig(compressedItem).isPresent() ? Optional.of(RecipeHelper.CompactingShape.TWO_BY_TWO_UNCRAFTABLE) : Optional.empty();
}
return Optional.empty();
}


private void addPreviousItems(Map<Integer, SlotDefinition> slotDefinitions, int firstFilledSlot, Item firstFilledItem) {
Item currentItem = firstFilledItem;
private void addPreviousItems(Map<Integer, SlotDefinition> slotDefinitions, int firstFilledSlot, ItemStack firstFilledItem) {
ItemStack currentItem = firstFilledItem;
for (int slot = firstFilledSlot + 1; slot < slotRange.firstSlot() + slotRange.numberOfSlots(); slot++) {
RecipeHelper.UncompactingResult uncompactingResult = RecipeHelper.getUncompactingResult(currentItem);
if (uncompactingResult.getCompactUsingShape() == RecipeHelper.CompactingShape.NONE) {
Optional<RecipeHelper.UncompactingResult> decompressionResult = getDecompressionResultFromConfig(currentItem);
if (decompressionResult.isEmpty()) {
Optional<RecipeHelper.UncompactingResult> decompressionResult = getDecompressionResultFromConfig(currentItem.getItem());
if (!currentItem.getComponents().isEmpty() || decompressionResult.isEmpty()) {
break;
}
uncompactingResult = decompressionResult.get();
Expand Down Expand Up @@ -299,7 +299,7 @@ private ItemStack extractItem(int slot, int amount, boolean simulate, ToIntFunct
SlotDefinition slotDefinition = slotDefinitions.get(slot);
ItemStack slotStack = parent.getSlotStack(slot);
toExtract = Math.min(toExtract, getLimit.applyAsInt(slotStack));
ItemStack result = slotDefinition.isCompressible() ? new ItemStack(slotDefinition.item(), toExtract) : slotStack.copyWithCount(toExtract);
ItemStack result = slotDefinition.isCompressible() ? slotDefinition.item().copyWithCount(toExtract) : slotStack.copyWithCount(toExtract);

if (!simulate) {
if (slotDefinition.isCompressible()) {
Expand Down Expand Up @@ -382,7 +382,7 @@ private void updateInternalStacksWithCounts(Map<Integer, Integer> toUpdate) {
if (count == 0) {
parent.setSlotStack(s, ItemStack.EMPTY);
} else if (slotStack.isEmpty()) {
parent.setSlotStack(s, new ItemStack(slotDefinitions.get(s).item(), count));
parent.setSlotStack(s, slotDefinitions.get(s).item().copyWithCount(count));
} else {
slotStack.setCount(count);
parent.setSlotStack(s, slotStack);
Expand Down Expand Up @@ -461,7 +461,7 @@ private ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
Map<Integer, SlotDefinition> definitions = slotDefinitions;

if (definitions.isEmpty()) {
definitions = getSlotDefinitions(stack.getItem(), slot, Map.of());
definitions = getSlotDefinitions(stack, slot, Map.of());
}

int limit = getStackLimit(definitions.get(slot));
Expand Down Expand Up @@ -521,7 +521,7 @@ private boolean canNotBeInserted(int slot, ItemStack stack) {
}

SlotDefinition slotDefinition = slotDefinitions.get(slot);
return !slotDefinition.isAccessible() || slotDefinition.item() != stack.getItem();
return !slotDefinition.isAccessible() || !ItemStack.isSameItemSameComponents(slotDefinition.item(), stack);
}

private void insertIntoInternalAndCalculated(int slotToStartFrom, long amountToInsert) {
Expand Down Expand Up @@ -583,7 +583,7 @@ private void insertIntoInternalAndCalculated(int slotToStartFrom, long amountToI
private void addToCalculatedStack(int slot, int countToAdd) {
if (!calculatedStacks.containsKey(slot) || calculatedStacks.get(slot).isEmpty()) {
SlotDefinition slotDefinition = slotDefinitions.get(slot);
calculatedStacks.put(slot, new ItemStack(slotDefinition.item(), countToAdd));
calculatedStacks.put(slot, slotDefinition.item().copyWithCount(countToAdd));
return;
}
ItemStack currentCalculated = calculatedStacks.get(slot);
Expand Down Expand Up @@ -624,7 +624,7 @@ public boolean isItemValid(int slot, ItemStack stack) {
}

SlotDefinition slotDefinition = slotDefinitions.get(slot);
return slotDefinition.isAccessible() && slotDefinition.item() == stack.getItem();
return slotDefinition.isAccessible() && ItemStack.isSameItemSameComponents(slotDefinition.item(), stack);
}

@Override
Expand Down Expand Up @@ -655,7 +655,7 @@ public Pair<ResourceLocation, ResourceLocation> getNoItemIcon(int slot) {

@Override
public Item getFilterItem(int slot) {
return slotDefinitions.containsKey(slot) ? slotDefinitions.get(slot).item() : Items.AIR;
return slotDefinitions.containsKey(slot) ? slotDefinitions.get(slot).item().getItem() : Items.AIR;
}

@Override
Expand All @@ -676,7 +676,7 @@ public void onSlotFilterChanged(int slot) {
@Override
public boolean isFilterItem(Item item) {
for (SlotDefinition slotDefinition : slotDefinitions.values()) {
if (slotDefinition.item() == item) {
if (slotDefinition.item().getItem() == item) {
return true;
}
}
Expand All @@ -689,33 +689,33 @@ public Map<Item, Set<Integer>> getFilterItems() {
for (Map.Entry<Integer, SlotDefinition> entry : slotDefinitions.entrySet()) {
SlotDefinition slotDefinition = entry.getValue();
if (slotDefinition.isAccessible()) {
filterItems.computeIfAbsent(slotDefinition.item(), k -> new HashSet<>()).add(entry.getKey());
filterItems.computeIfAbsent(slotDefinition.item().getItem(), k -> new HashSet<>()).add(entry.getKey());
}
}
return filterItems;
}

private static final class SlotDefinition {
private final Item item;
private final ItemStack item;
private final int prevSlotMultiplier;
private int slotLimit;
private final boolean isAccessible;

private boolean isCompressible = false;

private SlotDefinition(Item item, int prevSlotMultiplier, int slotLimit, boolean isAccessible) {
this.item = item;
private SlotDefinition(ItemStack item, int prevSlotMultiplier, int slotLimit, boolean isAccessible) {
this.item = item.copyWithCount(1);
this.prevSlotMultiplier = prevSlotMultiplier;
this.slotLimit = slotLimit;
this.isAccessible = isAccessible;
}

public static SlotDefinition inaccesible() {
return new SlotDefinition(Items.AIR, 0, 0, false);
return new SlotDefinition(ItemStack.EMPTY, 0, 0, false);
}

public SlotDefinition(Item item, int prevSlotMultiplier, boolean isAccessible) {
this(item, prevSlotMultiplier, -1, isAccessible);
public SlotDefinition(ItemStack stack, int prevSlotMultiplier, boolean isAccessible) {
this(stack, prevSlotMultiplier, -1, isAccessible);
}

public void setSlotLimit(int slotLimit) {
Expand All @@ -726,7 +726,7 @@ public void setCompressible(boolean compressible) {
isCompressible = compressible;
}

public Item item() {
public ItemStack item() {
return item;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.neoforged.neoforge.common.ModConfigSpec;
import net.p3pp3rf1y.sophisticatedcore.util.RecipeHelper;
Expand Down Expand Up @@ -58,7 +59,7 @@ public Optional<RecipeHelper.UncompactingResult> getDecompressionResult(Item ite
int count = Integer.parseInt(matcher.group(2));
Item toItem = BuiltInRegistries.ITEM.get(ResourceLocation.parse(matcher.group(3)));
if (fromItem != Items.AIR && toItem != Items.AIR && (count == 4 || count == 9)) {
additionalDecompressibleItemsMap.put(fromItem, new RecipeHelper.UncompactingResult(toItem, count == 4 ? RecipeHelper.CompactingShape.TWO_BY_TWO_UNCRAFTABLE : RecipeHelper.CompactingShape.THREE_BY_THREE_UNCRAFTABLE));
additionalDecompressibleItemsMap.put(fromItem, new RecipeHelper.UncompactingResult(new ItemStack(toItem), count == 4 ? RecipeHelper.CompactingShape.TWO_BY_TWO_UNCRAFTABLE : RecipeHelper.CompactingShape.THREE_BY_THREE_UNCRAFTABLE));
}
}
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package net.p3pp3rf1y.sophisticatedstorage.upgrades.compression;

import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.p3pp3rf1y.sophisticatedcore.api.IStorageWrapper;
import net.p3pp3rf1y.sophisticatedcore.common.gui.UpgradeSlotChangeResult;
import net.p3pp3rf1y.sophisticatedcore.inventory.InventoryHandler;
Expand Down Expand Up @@ -62,32 +60,32 @@ public List<UpgradeConflictDefinition> getUpgradeConflicts() {

private UpgradeSlotChangeResult canUseForCompression(IStorageWrapper storageWrapper, SlotRange slotRange) {
boolean allRemainingSlotsMustBeEmpty = false;
Item nextItemToMatch = Items.AIR;
ItemStack nextItemToMatch = ItemStack.EMPTY;
Set<Integer> errorSlots = new LinkedHashSet<>();
InventoryHandler inventoryHandler = storageWrapper.getInventoryHandler();
MemorySettingsCategory memorySettingsCategory = storageWrapper.getSettingsHandler().getTypeCategory(MemorySettingsCategory.class);
for (int slot = slotRange.firstSlot() + slotRange.numberOfSlots() - 1; slot >= slotRange.firstSlot(); slot--) {
Item item;
ItemStack stackToMatch;
ItemStack slotStack = inventoryHandler.getSlotStack(slot);
if (!slotStack.isEmpty()) {
item = slotStack.getItem();
stackToMatch = slotStack;
} else {
item = memorySettingsCategory.getSlotFilterStack(slot, false).map(ItemStack::getItem).orElse(Items.AIR);
stackToMatch = memorySettingsCategory.getSlotFilterStack(slot, false).orElse(ItemStack.EMPTY);
}
if (item != Items.AIR) {
if (!stackToMatch.isEmpty()) {
if (allRemainingSlotsMustBeEmpty) {
errorSlots.add(slot);
} else {
if (nextItemToMatch != Items.AIR && nextItemToMatch != item) {
if (!nextItemToMatch.isEmpty() && !ItemStack.isSameItemSameComponents(nextItemToMatch, stackToMatch)) {
errorSlots.add(slot);
break;
}

boolean hasSlotBeforeThisOne = slot - 1 >= slotRange.firstSlot();
if (hasSlotBeforeThisOne) {
RecipeHelper.CompactingShape compactingShape = RecipeHelper.getItemCompactingShapes(item).stream().filter(RecipeHelper.CompactingShape::isUncraftable).findFirst().orElse(RecipeHelper.CompactingShape.NONE);
RecipeHelper.CompactingShape compactingShape = RecipeHelper.getItemCompactingShapes(stackToMatch).stream().filter(RecipeHelper.CompactingShape::isUncraftable).findFirst().orElse(RecipeHelper.CompactingShape.NONE);
if (compactingShape == RecipeHelper.CompactingShape.TWO_BY_TWO_UNCRAFTABLE || compactingShape == RecipeHelper.CompactingShape.THREE_BY_THREE_UNCRAFTABLE) {
nextItemToMatch = RecipeHelper.getCompactingResult(item, compactingShape).getResult().getItem();
nextItemToMatch = RecipeHelper.getCompactingResult(stackToMatch, compactingShape).getResult();
} else {
allRemainingSlotsMustBeEmpty = true;
}
Expand Down
Loading

0 comments on commit 9931945

Please sign in to comment.