reworked HideHelper and uncovered recipes dumper

This commit is contained in:
rlnt 2024-03-14 20:49:36 +01:00
parent 09873d3d9b
commit ba959f41ea
No known key found for this signature in database
9 changed files with 137 additions and 183 deletions

View file

@ -7,9 +7,9 @@ import com.almostreliable.unified.config.UnifyConfig;
import com.almostreliable.unified.recipe.RecipeDumper;
import com.almostreliable.unified.recipe.RecipeTransformer;
import com.almostreliable.unified.recipe.unifier.RecipeHandlerFactory;
import com.almostreliable.unified.utils.MissingRecipesDumper;
import com.almostreliable.unified.utils.ReplacementMap;
import com.almostreliable.unified.utils.TagMap;
import com.almostreliable.unified.utils.UncoveredRecipesDumper;
import com.google.gson.JsonElement;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
@ -56,7 +56,10 @@ public final class AlmostUnifiedRuntimeImpl implements AlmostUnifiedRuntime {
dumper.dump(debugConfig.dumpOverview, debugConfig.dumpUnification, debugConfig.dumpDuplicates);
debugConfig.logRecipes(recipes, "recipes_after_unification.txt");
MissingRecipesDumper.write(this, debugConfig.dumpPotentialMissingRecipes, recipes);
if (debugConfig.dumpUncoveredRecipes) {
UncoveredRecipesDumper.write(recipes);
}
}
@Override

View file

@ -45,7 +45,7 @@ public class AlmostEMI implements EmiPlugin {
.orElse(false);
if (emiDisabled) return;
for (ItemStack item : HideHelper.createHidingList(AlmostUnified.getRuntime())) {
for (ItemStack item : HideHelper.getStacksToHide()) {
registry.removeEmiStacks(EmiStack.of(item));
}
}

View file

@ -42,7 +42,7 @@ public class AlmostJEI implements IModPlugin {
.orElse(false);
if (jeiDisabled) return;
Collection<ItemStack> items = HideHelper.createHidingList(AlmostUnified.getRuntime());
Collection<ItemStack> items = HideHelper.getStacksToHide();
if (!items.isEmpty()) {
jei.getIngredientManager().removeIngredientsAtRuntime(VanillaTypes.ITEM_STACK, items);
}

View file

@ -55,7 +55,7 @@ public class AlmostREI implements REIClientPlugin {
.orElse(false);
if (reiDisabled) return List.of();
return EntryIngredients.ofItemStacks(HideHelper.createHidingList(AlmostUnified.getRuntime()));
return EntryIngredients.ofItemStacks(HideHelper.getStacksToHide());
});
}

View file

@ -4,122 +4,110 @@ import com.almostreliable.unified.AlmostUnified;
import com.almostreliable.unified.AlmostUnifiedRuntime;
import com.almostreliable.unified.utils.ReplacementMap;
import com.almostreliable.unified.utils.TagOwnerships;
import com.almostreliable.unified.utils.UnifyTag;
import com.almostreliable.unified.utils.Utils;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public final class HideHelper {
private HideHelper() {}
public static Collection<ItemStack> createHidingList(AlmostUnifiedRuntime runtime) {
public static Multimap<UnifyTag<Item>, ResourceLocation> createHidingMap() {
AlmostUnifiedRuntime runtime = AlmostUnified.getRuntime();
ReplacementMap repMap = runtime.getReplacementMap().orElse(null);
var tagMap = runtime.getFilteredTagMap().orElse(null);
if (repMap == null || tagMap == null) return new ArrayList<>();
Set<ResourceLocation> hidingList = new HashSet<>();
Multimap<UnifyTag<Item>, ResourceLocation> hidingMap = HashMultimap.create();
if (repMap == null || tagMap == null) return hidingMap;
TagOwnerships ownerships = repMap.getTagOwnerships();
for (var unifyTag : tagMap.getTags()) {
var itemsByTag = tagMap.getEntriesByTag(unifyTag);
// avoid handling single entries and tags that only contain the same namespace for all items
if (Utils.allSameNamespace(itemsByTag)) continue;
Set<ResourceLocation> replacements = new HashSet<>();
for (ResourceLocation item : itemsByTag) {
replacements.add(getReplacementForItem(repMap, item));
}
ResourceLocation preferredItem = repMap.getPreferredItemForTag(unifyTag, $ -> true);
if (preferredItem == null) continue;
Set<ResourceLocation> toHide = new HashSet<>();
for (ResourceLocation item : itemsByTag) {
if (!replacements.contains(item)) {
toHide.add(item);
}
}
Set<ResourceLocation> itemsToHide = getItemsToHide(unifyTag, itemsByTag, preferredItem);
if (itemsToHide == null) continue;
hidingMap.putAll(unifyTag, itemsToHide);
if (toHide.isEmpty()) continue;
AlmostUnified.LOG.info(
"[AutoHiding] Hiding {}/{} items for tag '#{}' -> {}",
toHide.size(),
itemsByTag.size(),
unifyTag.location(),
toHide
);
hidingList.addAll(toHide);
Set<ResourceLocation> refItemsToHide = getRefItemsToHide(unifyTag, ownerships, preferredItem);
hidingMap.putAll(unifyTag, refItemsToHide);
}
hidingList.addAll(getRefItems(repMap));
return hidingList
.stream()
.flatMap(rl -> BuiltInRegistries.ITEM.getOptional(rl).stream())
.map(ItemStack::new)
.collect(Collectors.toList());
return hidingMap;
}
/**
* Returns the replacement for the given item, or the item itself if no replacement is found.
* <p>
* Returning the item itself is important for stone strata detection.
*
* @param repMap The replacement map.
* @param item The item to get the replacement for.
* @return The replacement for the given item, or the item itself if no replacement is found.
*/
private static ResourceLocation getReplacementForItem(ReplacementMap repMap, ResourceLocation item) {
var replacement = repMap.getReplacementForItem(item);
if (replacement == null) return item;
return replacement;
@Nullable
private static Set<ResourceLocation> getItemsToHide(UnifyTag<Item> unifyTag, Set<ResourceLocation> itemsByTag, ResourceLocation preferredItem) {
Set<ResourceLocation> itemsToHide = new HashSet<>();
for (ResourceLocation item : itemsByTag) {
if (!item.equals(preferredItem)) {
itemsToHide.add(item);
}
}
if (itemsToHide.isEmpty()) return null;
AlmostUnified.LOG.info(
"[AutoHiding] Hiding {}/{} items for tag '#{}' -> {}",
itemsToHide.size(),
itemsByTag.size(),
unifyTag.location(),
itemsToHide
);
return itemsToHide;
}
/**
* Returns a set of all items that are contained in the reference tags.
*
* @return A set of all items that are contained in the reference tags.
*/
private static Set<ResourceLocation> getRefItems(ReplacementMap repMap) {
Set<ResourceLocation> hidingList = new HashSet<>();
TagOwnerships ownerships = repMap.getTagOwnerships();
private static Set<ResourceLocation> getRefItemsToHide(UnifyTag<Item> unifyTag, TagOwnerships ownerships, ResourceLocation preferredItem) {
var refTags = ownerships.getRefsByOwner(unifyTag);
Set<ResourceLocation> refItemsToHide = new HashSet<>();
ownerships.getRefs().forEach(ref -> {
var owner = ownerships.getOwnerByTag(ref);
assert owner != null;
for (var refTag : refTags) {
var asTagKey = TagKey.create(Registries.ITEM, refTag.location());
var dominantItem = repMap.getPreferredItemForTag(owner, $ -> true);
TagKey<Item> asTagKey = TagKey.create(Registries.ITEM, ref.location());
Set<ResourceLocation> refItems = new HashSet<>();
BuiltInRegistries.ITEM.getTagOrEmpty(asTagKey).forEach(holder -> {
ResourceLocation item = BuiltInRegistries.ITEM.getKey(holder.value());
if (item.equals(dominantItem)) return; // don't hide if the item is a dominant one
refItems.add(item);
if (item.equals(preferredItem)) return;
refItemsToHide.add(item);
});
if (refItems.isEmpty()) return;
if (refItemsToHide.isEmpty()) continue;
AlmostUnified.LOG.info(
"[AutoHiding] Hiding reference tag '#{}' of owner tag '#{}' -> {}",
ref.location(),
owner.location(),
refItems
refTag.location(),
unifyTag.location(),
refItemsToHide
);
}
hidingList.addAll(refItems);
});
return refItemsToHide;
}
return hidingList;
public static Collection<ItemStack> getStacksToHide() {
var hidingMap = createHidingMap();
if (hidingMap.isEmpty()) return List.of();
return hidingMap
.entries()
.stream()
.flatMap(rl -> BuiltInRegistries.ITEM.getOptional(rl.getValue()).stream())
.map(ItemStack::new)
.toList();
}
}

View file

@ -21,15 +21,15 @@ public class DebugConfig extends Config {
public final boolean dumpUnification;
public final boolean dumpOverview;
public final boolean dumpRecipes;
public final boolean dumpPotentialMissingRecipes;
public final boolean dumpUncoveredRecipes;
public DebugConfig(boolean dumpTagMap, boolean dumpDuplicates, boolean dumpUnification, boolean dumpOverview, boolean dumpRecipes, boolean dumpPotentialMissingRecipes) {
public DebugConfig(boolean dumpTagMap, boolean dumpDuplicates, boolean dumpUnification, boolean dumpOverview, boolean dumpRecipes, boolean dumpUncoveredRecipes) {
this.dumpTagMap = dumpTagMap;
this.dumpDuplicates = dumpDuplicates;
this.dumpUnification = dumpUnification;
this.dumpOverview = dumpOverview;
this.dumpRecipes = dumpRecipes;
this.dumpPotentialMissingRecipes = dumpPotentialMissingRecipes;
this.dumpUncoveredRecipes = dumpUncoveredRecipes;
}
public void logUnifyTagDump(TagMap<Item> tagMap) {
@ -73,7 +73,7 @@ public class DebugConfig extends Config {
public static final String DUMP_UNIFICATION = "dumpUnification";
public static final String DUMP_OVERVIEW = "dumpOverview";
public static final String DUMP_RECIPES = "dumpRecipes";
public static final String DUMP_POTENTIAL_MISSING_RECIPES = "dumpPotentialMissingRecipes";
public static final String DUMP_UNCOVERED_RECIPES = "dumpUncoveredRecipes";
@Override
public DebugConfig deserialize(JsonObject json) {
@ -83,7 +83,7 @@ public class DebugConfig extends Config {
safeGet(() -> json.get(DUMP_UNIFICATION).getAsBoolean(), false),
safeGet(() -> json.get(DUMP_OVERVIEW).getAsBoolean(), false),
safeGet(() -> json.get(DUMP_RECIPES).getAsBoolean(), false),
safeGet(() -> json.get(DUMP_POTENTIAL_MISSING_RECIPES).getAsBoolean(), false)
safeGet(() -> json.get(DUMP_UNCOVERED_RECIPES).getAsBoolean(), false)
);
}
@ -95,7 +95,7 @@ public class DebugConfig extends Config {
json.addProperty(DUMP_UNIFICATION, src.dumpUnification);
json.addProperty(DUMP_OVERVIEW, src.dumpOverview);
json.addProperty(DUMP_RECIPES, src.dumpRecipes);
json.addProperty(DUMP_POTENTIAL_MISSING_RECIPES, src.dumpPotentialMissingRecipes);
json.addProperty(DUMP_UNCOVERED_RECIPES, src.dumpUncoveredRecipes);
return json;
}
}

View file

@ -1,95 +0,0 @@
package com.almostreliable.unified.utils;
import com.almostreliable.unified.AlmostUnifiedPlatform;
import com.almostreliable.unified.AlmostUnifiedRuntime;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class MissingRecipesDumper {
public static void write(AlmostUnifiedRuntime runtime, boolean dumpPotentialMissingRecipes, Map<ResourceLocation, JsonElement> recipes) {
if (!dumpPotentialMissingRecipes) return;
var itemsPerTag = getHidingIds(runtime);
FileUtils.write(AlmostUnifiedPlatform.INSTANCE.getLogPath(), "recipe_hiding_check.txt", sb -> {
recipes.forEach(((recipe, json) -> {
if (json instanceof JsonObject obj) {
write(recipe, obj, itemsPerTag, sb);
}
}));
});
}
private static void write(ResourceLocation recipe, JsonObject json, Multimap<UnifyTag<Item>, ResourceLocation> itemsPerTag, StringBuilder sb) {
String jsonStr = json.toString();
Multimap<UnifyTag<Item>, ResourceLocation> found = HashMultimap.create();
itemsPerTag.asMap().forEach((tag, items) -> {
for (ResourceLocation item : items) {
if (jsonStr.contains(item.toString())) {
found.put(tag, item);
}
}
});
if (found.isEmpty()) return;
String type = Optional.ofNullable(json.get("type")).map(JsonElement::getAsString).orElse("");
sb
.append("Recipe ")
.append(recipe)
.append(" (")
.append(type)
.append(") contains potentially hiding items:")
.append("\n")
.append("Json: ")
.append(jsonStr)
.append("\n")
.append("Items: ")
.append("\n");
found.asMap().forEach((tag, items) -> {
for (ResourceLocation item : items) {
sb.append("\t").append(item).append(" (#").append(tag.location()).append(")").append("\n");
}
});
sb.append("\n");
}
public static Multimap<UnifyTag<Item>, ResourceLocation> getHidingIds(AlmostUnifiedRuntime runtime) {
ReplacementMap repMap = runtime.getReplacementMap().orElse(null);
var tagMap = runtime.getFilteredTagMap().orElse(null);
Multimap<UnifyTag<Item>, ResourceLocation> hidings = HashMultimap.create();
if (repMap == null || tagMap == null) return hidings;
for (var unifyTag : tagMap.getTags()) {
var itemsByTag = tagMap.getEntriesByTag(unifyTag);
if (Utils.allSameNamespace(itemsByTag)) continue;
ResourceLocation kingItem = repMap.getPreferredItemForTag(unifyTag, $ -> true);
if (kingItem == null) continue;
Set<ResourceLocation> r = new HashSet<>();
for (ResourceLocation item : itemsByTag) {
if (!item.equals(kingItem)) {
r.add(item);
}
}
hidings.putAll(unifyTag, r);
}
return hidings;
}
}

View file

@ -134,11 +134,12 @@ public class TagOwnerships {
}
/**
* Gets all reference tags for all owner tags.
* Gets all reference tags for the provided owner tag.
*
* @return A set of all reference tags.
* @param tag The owner tag to get the references for.
* @return A collection of all reference tags.
*/
public Set<UnifyTag<Item>> getRefs() {
return refsToOwner.keySet();
public Collection<UnifyTag<Item>> getRefsByOwner(UnifyTag<Item> tag) {
return ownerToRefs.get(tag);
}
}

View file

@ -0,0 +1,57 @@
package com.almostreliable.unified.utils;
import com.almostreliable.unified.AlmostUnifiedPlatform;
import com.almostreliable.unified.compat.HideHelper;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import java.util.Map;
import java.util.Optional;
public final class UncoveredRecipesDumper {
private UncoveredRecipesDumper() {}
public static void write(Map<ResourceLocation, JsonElement> recipes) {
var hidingMap = HideHelper.createHidingMap();
FileUtils.write(AlmostUnifiedPlatform.INSTANCE.getLogPath(), "uncovered_recipes.txt", sb -> {
recipes.forEach((recipeId, json) -> {
if (json instanceof JsonObject obj) {
write(recipeId, obj, hidingMap, sb);
}
});
});
}
private static void write(ResourceLocation recipeId, JsonObject json, Multimap<UnifyTag<Item>, ResourceLocation> hidingMap, StringBuilder sb) {
String jsonStr = json.toString();
Multimap<UnifyTag<Item>, ResourceLocation> foundEntries = HashMultimap.create();
hidingMap.asMap().forEach((tag, items) -> {
for (ResourceLocation item : items) {
if (jsonStr.contains(item.toString())) {
foundEntries.put(tag, item);
}
}
});
if (foundEntries.isEmpty()) return;
String type = Optional.ofNullable(json.get("type")).map(JsonElement::getAsString).orElse("");
sb
.append("Id: ").append(recipeId).append("\n")
.append("Type: ").append(type).append("\n")
.append("Json: ").append(jsonStr).append("\n")
.append("Items: ").append("\n");
foundEntries.asMap().forEach((tag, items) -> {
for (ResourceLocation item : items) {
sb.append("\t").append(item).append(" (#").append(tag.location()).append(")").append("\n");
}
});
sb.append("\n");
}
}