diff --git a/Common/src/main/java/com/almostreliable/unified/AlmostUnifiedRuntime.java b/Common/src/main/java/com/almostreliable/unified/AlmostUnifiedRuntime.java index 4aa56d7..eb78e94 100644 --- a/Common/src/main/java/com/almostreliable/unified/AlmostUnifiedRuntime.java +++ b/Common/src/main/java/com/almostreliable/unified/AlmostUnifiedRuntime.java @@ -10,7 +10,9 @@ import com.google.common.collect.HashBiMap; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; import net.minecraft.tags.TagManager; +import net.minecraft.world.item.Item; import javax.annotation.Nullable; import java.util.Collection; @@ -30,8 +32,8 @@ public class AlmostUnifiedRuntime { public void run(Map recipes) { config.load(); - RecipeTransformContext helper = createContext(config.getAllowedTags(), config.getModPriorities()); -// transformRecipes(recipes, helper); + RecipeTransformContext context = createContext(config.getAllowedTags(), config.getModPriorities()); + transformRecipes(recipes, context); } public void transformRecipes(Map recipes, RecipeTransformContext helper) { @@ -100,16 +102,16 @@ public class AlmostUnifiedRuntime { this.tagManager = tagManager; } - protected RecipeTransformContext createContext(List allowedTags, List modPriorities) { + protected RecipeTransformContext createContext(List> allowedTags, List modPriorities) { if (tagManager == null) { throw new IllegalStateException("Internal error. TagManager was not updated correctly"); } TagMap tagMap = TagMap.create(tagManager); - Map itemToTagMapping = new HashMap<>(allowedTags.size()); + Map> itemToTagMapping = new HashMap<>(allowedTags.size()); - for (ResourceLocation tag : allowedTags) { + for (TagKey tag : allowedTags) { Collection items = tagMap.getItems(tag); for (ResourceLocation item : items) { if (itemToTagMapping.containsKey(item)) { diff --git a/Common/src/main/java/com/almostreliable/unified/ModConfig.java b/Common/src/main/java/com/almostreliable/unified/ModConfig.java index 9aa7ee2..c347bdf 100644 --- a/Common/src/main/java/com/almostreliable/unified/ModConfig.java +++ b/Common/src/main/java/com/almostreliable/unified/ModConfig.java @@ -6,7 +6,10 @@ import com.electronwill.nightconfig.core.file.CommentedFileConfig; import com.electronwill.nightconfig.core.file.FileConfig; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; import javax.annotation.Nullable; import java.util.*; @@ -160,26 +163,27 @@ public class ModConfig { return currentConfig.get(UNIFICATION_MOD_PRIORITIES); } - public List getAllowedTags() { + public List> getAllowedTags() { if(currentConfig == null) { throw new IllegalStateException("Config is not loaded"); } Multimap variables = compileVariables(); - List collectedPattern = new ArrayList<>(); - Collection patterns = currentConfig.get(UNIFICATION_PATTERN); + List> collectedPattern = new ArrayList<>(); + Collection patterns = currentConfig.get(UNIFICATION_PATTERN); for (String pattern : patterns) { Collection compiledPattern = compilePattern(pattern, variables); if (pattern.startsWith("!")) { - collectedPattern.removeIf(p -> compiledPattern.contains(p.toString())); + collectedPattern.removeIf(p -> compiledPattern.contains(p.location().toString())); } else { for (String s : compiledPattern) { ResourceLocation rl = ResourceLocation.tryParse(s); if (rl == null) { AlmostUnified.LOG.warn("Invalid pattern: " + s); } else { - collectedPattern.add(rl); + TagKey tag = TagKey.create(Registry.ITEM_REGISTRY, rl); + collectedPattern.add(tag); } } } diff --git a/Common/src/main/java/com/almostreliable/unified/RecipeTransformContextImpl.java b/Common/src/main/java/com/almostreliable/unified/RecipeTransformContextImpl.java index ecfd999..d82bdc1 100644 --- a/Common/src/main/java/com/almostreliable/unified/RecipeTransformContextImpl.java +++ b/Common/src/main/java/com/almostreliable/unified/RecipeTransformContextImpl.java @@ -1,9 +1,12 @@ package com.almostreliable.unified; import com.almostreliable.unified.api.RecipeTransformContext; -import com.google.common.collect.Multimap; +import com.almostreliable.unified.api.ReplacementFallbackStrategy; +import com.almostreliable.unified.fallbacks.StoneStrataFallbackStrategy; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; import javax.annotation.Nullable; import java.util.*; @@ -12,15 +15,17 @@ public class RecipeTransformContextImpl implements RecipeTransformContext { private final Collection modPriorities; private final TagMap tagMap; - private final Map itemToTagMapping; + private final Map> itemToTagMapping; /** * Cache for replacements. Key is the item to replace, value is the replacement. */ private final Map replacementCache = new HashMap<>(); private final Set invalidCache = new HashSet<>(); + // TODO - In the future this may be a list of multiple fallbacks. + private final ReplacementFallbackStrategy fallbackStrategy = new StoneStrataFallbackStrategy(); - public RecipeTransformContextImpl(TagMap tagMap, Map itemToTagMapping, List modPriorities) { + public RecipeTransformContextImpl(TagMap tagMap, Map> itemToTagMapping, List modPriorities) { this.tagMap = tagMap; this.itemToTagMapping = itemToTagMapping; this.modPriorities = modPriorities; @@ -39,12 +44,12 @@ public class RecipeTransformContextImpl implements RecipeTransformContext { return replacement.toString(); } - ResourceLocation tag = itemToTagMapping.get(asLocation); + TagKey tag = itemToTagMapping.get(asLocation); if (!Registry.ITEM.containsKey(asLocation) || tag == null) { return null; } - ResourceLocation modReplacement = computeReplacement(asLocation, tag, tagMap.getItems(tag)); + ResourceLocation modReplacement = computeReplacement(asLocation, tag); if(modReplacement == null || modReplacement.equals(asLocation)) { invalidCache.add(asLocation); return null; @@ -56,26 +61,33 @@ public class RecipeTransformContextImpl implements RecipeTransformContext { } @Nullable - public ResourceLocation computeReplacement(ResourceLocation toReplace, ResourceLocation tag, Collection items) { + public ResourceLocation computeReplacement(ResourceLocation item, TagKey tag) { for (String mod : modPriorities) { + if(mod.equals(item.getNamespace())) { + return null; + } + List sameModItems = tagMap .getItems(tag) .stream() - .filter(item -> item.getNamespace().equals(mod) && Registry.ITEM.containsKey(item)) + .filter(i -> i.getNamespace().equals(mod) && Registry.ITEM.containsKey(i)) .toList(); if(sameModItems.size() == 1) { return sameModItems.get(0); } if(sameModItems.size() > 1) { - return findFittingItem(toReplace, tag, sameModItems); + ResourceLocation fallback = fallbackStrategy.getFallback(item, tag, sameModItems, tagMap); + if(fallback != null) { + if(fallback.equals(item)) { + throw new IllegalStateException("Fallback for " + item + " is the same as the item itself. This is not allowed."); + } + return fallback; + } } + } return null; } - - public ResourceLocation findFittingItem(ResourceLocation toReplace, ResourceLocation tag, List sameModItems) { - return null; - } } diff --git a/Common/src/main/java/com/almostreliable/unified/TagMap.java b/Common/src/main/java/com/almostreliable/unified/TagMap.java index b2cfa65..e3ef065 100644 --- a/Common/src/main/java/com/almostreliable/unified/TagMap.java +++ b/Common/src/main/java/com/almostreliable/unified/TagMap.java @@ -5,13 +5,15 @@ import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.Tag; +import net.minecraft.tags.TagKey; import net.minecraft.tags.TagManager; +import net.minecraft.world.item.Item; import java.util.*; public class TagMap { - private final Map> tagsToItems = new HashMap<>(); - private final Map> itemsToTags = new HashMap<>(); + private final Map, Set> tagsToItems = new HashMap<>(); + private final Map>> itemsToTags = new HashMap<>(); protected TagMap() {} @@ -29,30 +31,27 @@ public class TagMap { TagMap tagMap = new TagMap(); for (var entry : tags.entrySet()) { - ResourceLocation tag = entry.getKey(); + TagKey tag = TagKey.create(Registry.ITEM_REGISTRY, entry.getKey()); Tag> holderTag = entry.getValue(); for (Holder holder : holderTag.getValues()) { - ResourceLocation itemId = holder.unwrapKey().map(ResourceKey::location).orElse(null); - if (itemId != null) { - tagMap.put(tag, itemId); - } + holder.unwrapKey().map(ResourceKey::location).ifPresent(itemId -> tagMap.put(tag, itemId)); } } return tagMap; } - protected void put(ResourceLocation tag, ResourceLocation item) { + protected void put(TagKey tag, ResourceLocation item) { tagsToItems.computeIfAbsent(tag, k -> new HashSet<>()).add(item); itemsToTags.computeIfAbsent(item, k -> new HashSet<>()).add(tag); } - public Collection getItems(ResourceLocation tag) { + public Collection getItems(TagKey tag) { return Collections.unmodifiableSet(tagsToItems.getOrDefault(tag, Collections.emptySet())); } - public Collection getTags(ResourceLocation items) { + public Collection> getTags(ResourceLocation items) { return Collections.unmodifiableSet(itemsToTags.getOrDefault(items, Collections.emptySet())); } } diff --git a/Common/src/main/java/com/almostreliable/unified/api/ReplacementFallbackStrategy.java b/Common/src/main/java/com/almostreliable/unified/api/ReplacementFallbackStrategy.java new file mode 100644 index 0000000..613886a --- /dev/null +++ b/Common/src/main/java/com/almostreliable/unified/api/ReplacementFallbackStrategy.java @@ -0,0 +1,24 @@ +package com.almostreliable.unified.api; + +import com.almostreliable.unified.TagMap; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; + +import javax.annotation.Nullable; +import java.util.Collection; + +public interface ReplacementFallbackStrategy { + /** + * Determine a fallback for the given item. + * + * @param lookupItem the item to lookup + * @param tag the tag to replace the item with + * @param potentialItems the potential items to replace with + * @param tags the tag map to use for lookup + * @return the fallback item, or null if no fallback is available + * @throws IllegalStateException if returning the lookupItem + */ + @Nullable + ResourceLocation getFallback(ResourceLocation lookupItem, TagKey tag, Collection potentialItems, TagMap tags); +} diff --git a/Common/src/main/java/com/almostreliable/unified/fallbacks/StoneStrataFallbackStrategy.java b/Common/src/main/java/com/almostreliable/unified/fallbacks/StoneStrataFallbackStrategy.java new file mode 100644 index 0000000..43725fa --- /dev/null +++ b/Common/src/main/java/com/almostreliable/unified/fallbacks/StoneStrataFallbackStrategy.java @@ -0,0 +1,24 @@ +package com.almostreliable.unified.fallbacks; + +import com.almostreliable.unified.TagMap; +import com.almostreliable.unified.api.ReplacementFallbackStrategy; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; + +import java.util.Collection; +import java.util.Comparator; + +// TODO use config and not this :D +public class StoneStrataFallbackStrategy implements ReplacementFallbackStrategy { + @Override + public ResourceLocation getFallback(ResourceLocation lookupItem, TagKey tag, Collection potentialItems, TagMap tags) { + if (tag.location().getPath().contains("ores")) { + return potentialItems + .stream() + .min(Comparator.comparingInt(s -> s.getPath().length())) + .orElse(null); + } + return null; + } +} diff --git a/Common/src/main/java/com/almostreliable/unified/fallbacks/package-info.java b/Common/src/main/java/com/almostreliable/unified/fallbacks/package-info.java new file mode 100644 index 0000000..16d76f5 --- /dev/null +++ b/Common/src/main/java/com/almostreliable/unified/fallbacks/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.almostreliable.unified.fallbacks; + +import net.minecraft.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault;