Skip to content

Commit

Permalink
Rework (badly-implemented) compression chains to ensure immutability
Browse files Browse the repository at this point in the history
  • Loading branch information
62832 committed Jan 17, 2025
1 parent 592a8bd commit 39fa6f1
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ public class BulkCellInventory implements StorageCell {
unitCount = stack.getOrDefault(MEGAComponents.BULK_CELL_UNIT_COUNT, BigInteger.ZERO);

compressionEnabled = cell.getUpgrades(stack).isInstalled(MEGAItems.COMPRESSION_CARD);
compressionChain = CompressionService.getChain(storedItem != null ? storedItem : filterItem)
.orElseGet(CompressionChain::new);
compressionChain = CompressionService.getChain(storedItem != null ? storedItem : filterItem);
unitFactor = compressionChain.unitFactor(storedItem != null ? storedItem : filterItem);

// Check newly-calculated factor against what's already recorded in order to adjust for a compression chain that
Expand Down Expand Up @@ -132,7 +131,7 @@ public Set<IPatternDetails> getDecompressionPatterns() {
decompressionPatterns.add(new DecompressionPattern(decompressed.item(), variant, false));
}

var remainingChain = compressionChain.subList(decompressionChain.size() - 1, compressionChain.size());
var remainingChain = compressionChain.trailing(decompressionChain.size() - 1);

for (var variant : remainingChain) {
if (variant == remainingChain.getFirst()) {
Expand Down Expand Up @@ -271,7 +270,7 @@ public void getAvailableStacks(KeyCounter out) {
if (storedItem != null) {
if (compressionEnabled && storedItem.equals(filterItem) && !compressionChain.isEmpty()) {
var count = unitCount;
var chain = compressionChain.limited(compressionCutoff).lastMultiplierSwapped();
var chain = compressionChain.lastMultiplierSwapped(compressionCutoff);

for (var variant : chain) {
var compressionFactor = BigInteger.valueOf(variant.factor());
Expand Down
72 changes: 48 additions & 24 deletions src/main/java/gripe/_90/megacells/misc/CompressionChain.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,77 @@

import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;

import net.minecraft.world.item.Item;

import appeng.api.stacks.AEItemKey;

public class CompressionChain extends ObjectArrayList<CompressionChain.Variant> {
void add(AEItemKey item, int factor) {
add(new Variant(item, factor));
public class CompressionChain {
private final List<Variant> variants;

CompressionChain(List<Variant> variants) {
this.variants = Collections.unmodifiableList(variants);
}

public boolean isEmpty() {
return variants.isEmpty();
}

public boolean containsVariant(AEItemKey item) {
return stream().anyMatch(v -> v.item().equals(item));
for (var variant : variants) {
if (variant.item().equals(item)) {
return true;
}
}

return false;
}

public Variant get(int index) {
return variants.get(index);
}

public BigInteger unitFactor(AEItemKey item) {
return stream()
.filter(v -> v.item().equals(item))
.findFirst()
.map(i -> IntStream.rangeClosed(0, indexOf(i))
.mapToObj(this::get)
for (var variant : variants) {
if (variant.item().equals(item)) {
return limited(variants.indexOf(variant) + 1).stream()
.map(v -> BigInteger.valueOf(v.factor()))
.reduce(BigInteger.ONE, BigInteger::multiply))
.orElse(BigInteger.ONE);
.reduce(BigInteger.ONE, BigInteger::multiply);
}
}

return BigInteger.ONE;
}

public CompressionChain lastMultiplierSwapped() {
var multipliers = stream().map(Variant::factor).collect(Collectors.toList());
public List<Variant> limited(int limit) {
return variants.subList(0, limit);
}

public List<Variant> trailing(int start) {
return variants.subList(start, variants.size());
}

public int size() {
return variants.size();
}

public List<Variant> lastMultiplierSwapped(int cutoff) {
var subChain = limited(cutoff);
var multipliers = subChain.stream().map(Variant::factor).collect(Collectors.toList());
Collections.rotate(multipliers, -1);

var items = stream().map(Variant::item).toList();
var chain = new CompressionChain();
var items = subChain.stream().map(Variant::item).toList();
var swapped = new ObjectArrayList<Variant>();

for (var i = 0; i < items.size(); i++) {
chain.add(items.get(i), multipliers.get(i));
swapped.add(new Variant(items.get(i), multipliers.get(i)));
}

return chain;
}

public CompressionChain limited(int limit) {
var chain = new CompressionChain();
chain.addAll(subList(0, limit));
return chain;
return Collections.unmodifiableList(swapped);
}

public record Variant(AEItemKey item, int factor) {
Expand Down
44 changes: 26 additions & 18 deletions src/main/java/gripe/_90/megacells/misc/CompressionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;

import net.minecraft.core.RegistryAccess;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
Expand All @@ -29,6 +30,7 @@

public class CompressionService {
private static final Logger LOGGER = LoggerFactory.getLogger(CompressionService.class);
private static final CompressionChain EMPTY = new CompressionChain(List.of());

// Each chain is a list of "variants", where each variant consists of the item itself along with an associated value
// dictating how much of the previous variant's item is needed to compress into that variant.
Expand All @@ -40,11 +42,19 @@ public class CompressionService {
// based on its usually irreversible recipe.
private static final Set<Override> overrides = new HashSet<>();

public static Optional<CompressionChain> getChain(AEItemKey item) {
return chains.stream().filter(chain -> chain.containsVariant(item)).findFirst();
public static CompressionChain getChain(AEItemKey item) {
for (var chain : chains) {
if (chain.containsVariant(item)) {
return chain;
}
}

return EMPTY;
}

public static void init() {
GridServices.register(DecompressionService.class, DecompressionService.class);

NeoForge.EVENT_BUS.addListener((ServerStartedEvent event) -> {
var server = event.getServer();
CompressionService.loadRecipes(server.getRecipeManager(), server.registryAccess());
Expand All @@ -57,8 +67,6 @@ public static void init() {
CompressionService.loadRecipes(server.getRecipeManager(), server.registryAccess());
}
});

GridServices.register(DecompressionService.class, DecompressionService.class);
}

private static void loadRecipes(RecipeManager recipeManager, RegistryAccess access) {
Expand Down Expand Up @@ -90,9 +98,9 @@ private static void loadRecipes(RecipeManager recipeManager, RegistryAccess acce

// Pull all available compression chains from the recipe shortlist and add these to the cache
Stream.concat(compressed.stream(), decompressed.stream()).forEach(recipe -> {
var baseVariant = recipe.getResultItem(access).getItem();
var baseVariant = AEItemKey.of(recipe.getResultItem(access).getItem());

if (getChain(AEItemKey.of(baseVariant)).isEmpty()) {
if (getChain(baseVariant).isEmpty()) {
chains.add(generateChain(baseVariant, compressed, decompressed, access));
}
});
Expand All @@ -101,17 +109,17 @@ private static void loadRecipes(RecipeManager recipeManager, RegistryAccess acce
}

private static CompressionChain generateChain(
Item baseVariant,
AEItemKey baseVariant,
List<CraftingRecipe> compressed,
List<CraftingRecipe> decompressed,
RegistryAccess access) {
var variants = new LinkedList<Item>();
var variants = new LinkedList<AEItemKey>();
var multipliers = new LinkedList<Integer>();

variants.addFirst(baseVariant);

for (var lower = getNextVariant(baseVariant, decompressed, false, access); lower != null; ) {
var item = lower.item().getItem();
var item = lower.item();

if (variants.contains(item)) {
if (lower.factor() != 1) {
Expand All @@ -129,10 +137,10 @@ private static CompressionChain generateChain(
}

multipliers.addFirst(1);
var chain = new CompressionChain();
var chain = new ObjectArrayList<CompressionChain.Variant>();

for (var i = 0; i < variants.size(); i++) {
chain.add(AEItemKey.of(variants.get(i)), multipliers.get(i));
chain.add(new CompressionChain.Variant(variants.get(i), multipliers.get(i)));
}

for (var higher = getNextVariant(baseVariant, compressed, true, access); higher != null; ) {
Expand All @@ -147,28 +155,28 @@ private static CompressionChain generateChain(
}

chain.add(higher);
higher = getNextVariant(higher.item().getItem(), compressed, true, access);
higher = getNextVariant(higher.item(), compressed, true, access);
}

LOGGER.debug("Gathered bulk compression chain: {}", chain);
return chain;
return new CompressionChain(chain);
}

private static CompressionChain.Variant getNextVariant(
Item item, List<CraftingRecipe> recipes, boolean compressed, RegistryAccess access) {
AEItemKey item, List<CraftingRecipe> recipes, boolean compressed, RegistryAccess access) {
for (var override : overrides) {
if (compressed && override.smaller.equals(item)) {
if (compressed && override.smaller.equals(item.getItem())) {
return new CompressionChain.Variant(override.larger, override.factor);
}

if (!compressed && override.larger.equals(item)) {
if (!compressed && override.larger.equals(item.getItem())) {
return new CompressionChain.Variant(override.smaller, override.factor);
}
}

for (var recipe : recipes) {
for (var input : recipe.getIngredients().getFirst().getItems()) {
if (input.getItem().equals(item)) {
if (input.getItem().equals(item.getItem())) {
return new CompressionChain.Variant(
recipe.getResultItem(access).getItem(),
compressed
Expand Down

0 comments on commit 39fa6f1

Please sign in to comment.