Skip to content

Commit

Permalink
Add comparison support (#6)
Browse files Browse the repository at this point in the history
* Add support for custom item comparisons

* Bump version

* Mmmm eclipse is eating rocks

* Apply changes from PR review

* Add changelog file

* Rename Comparisons.Predicate -> Comparisons.EqualityPredicate and extend BiPredicate
  • Loading branch information
Sollace authored Oct 19, 2024
1 parent 48dd8e5 commit f3c7b02
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 10 deletions.
1 change: 1 addition & 0 deletions changelog/1.2.1+1.21.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Add support for custom item comparisons
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ minecraft_version=1.21
yarn_mappings=1.21+build.9
loader_version=0.16.5

mod_version=1.2.0
mod_version=1.2.1

fabric_version=0.102.0+1.21
rei_version=16.0.783
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@
import dev.emi.emi.api.EmiPlugin;
import dev.emi.emi.api.EmiRegistry;
import dev.emi.emi.api.recipe.EmiRecipeCategory;
import dev.emi.emi.api.stack.Comparison;
import dev.emi.emi.api.stack.EmiIngredient;
import dev.emi.emi.api.widget.Bounds;
import io.github.mattidragon.tlaapi.api.StackDragHandler;
import io.github.mattidragon.tlaapi.api.gui.TlaBounds;
import io.github.mattidragon.tlaapi.api.plugin.Comparisons;
import io.github.mattidragon.tlaapi.api.plugin.PluginContext;
import io.github.mattidragon.tlaapi.api.plugin.PluginLoader;
import io.github.mattidragon.tlaapi.api.plugin.RecipeViewer;
import io.github.mattidragon.tlaapi.api.recipe.TlaCategory;
import io.github.mattidragon.tlaapi.api.recipe.TlaIngredient;
import io.github.mattidragon.tlaapi.api.recipe.TlaRecipe;
import io.github.mattidragon.tlaapi.api.recipe.TlaStackComparison;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.ItemConvertible;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.recipe.RecipeType;
Expand All @@ -38,6 +43,9 @@ private static final class EmiImplementation implements PluginContext {
private final EmiRegistry registry;
private final Map<TlaCategory, EmiRecipeCategory> categories = new HashMap<>();

private final Comparisons<ItemConvertible> itemComparisons = new EmiComparisons<>();
private final Comparisons<Fluid> fluidComparisons = new EmiComparisons<>();

private EmiImplementation(EmiRegistry registry) {
this.registry = registry;
}
Expand Down Expand Up @@ -132,6 +140,16 @@ public <T extends Screen> void addExclusionZoneProvider(Class<T> clazz, Function
});
}

@Override
public Comparisons<ItemConvertible> getItemComparisons() {
return itemComparisons;
}

@Override
public Comparisons<Fluid> getFluidComparisons() {
return fluidComparisons;
}

@Override
public RecipeViewer getActiveViewer() {
return RecipeViewer.EMI;
Expand All @@ -141,5 +159,15 @@ public RecipeViewer getActiveViewer() {
public String toString() {
return "EMI plugin handler";
}

private class EmiComparisons<T> implements Comparisons<T> {
@Override
public void register(T key, TlaStackComparison comparison) {
registry.setDefaultComparison(key, Comparison.of(
(a, b) -> comparison.equalityPredicate().test(EmiUtils.convertStack(a), EmiUtils.convertStack(b)),
stack -> comparison.hashFunction().hash(EmiUtils.convertStack(stack)))
);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
import com.google.common.collect.Multimap;
import io.github.mattidragon.tlaapi.api.StackDragHandler;
import io.github.mattidragon.tlaapi.api.gui.TlaBounds;
import io.github.mattidragon.tlaapi.api.plugin.Comparisons;
import io.github.mattidragon.tlaapi.api.plugin.PluginContext;
import io.github.mattidragon.tlaapi.api.plugin.PluginLoader;
import io.github.mattidragon.tlaapi.api.plugin.RecipeViewer;
import io.github.mattidragon.tlaapi.api.recipe.TlaCategory;
import io.github.mattidragon.tlaapi.api.recipe.TlaIngredient;
import io.github.mattidragon.tlaapi.api.recipe.TlaRecipe;
import io.github.mattidragon.tlaapi.api.recipe.TlaStack;
import io.github.mattidragon.tlaapi.api.recipe.TlaStackComparison;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.fabric.constants.FabricTypes;
import mezz.jei.api.gui.handlers.IGhostIngredientHandler;
import mezz.jei.api.gui.handlers.IGuiClickableArea;
import mezz.jei.api.gui.handlers.IGuiContainerHandler;
Expand All @@ -21,10 +25,13 @@
import mezz.jei.api.registration.IRecipeCatalystRegistration;
import mezz.jei.api.registration.IRecipeCategoryRegistration;
import mezz.jei.api.registration.IRecipeRegistration;
import mezz.jei.api.registration.ISubtypeRegistration;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.util.math.Rect2i;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.ItemConvertible;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.recipe.RecipeManager;
Expand All @@ -34,6 +41,7 @@

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand All @@ -48,37 +56,62 @@ public class TlaApiJeiPlugin implements IModPlugin, PluginContext {
private final List<GhostHandler<?>> ghostHandlers = new ArrayList<>();
private final List<ScreenSizeProvider<?>> sizeProviders = new ArrayList<>();
private final List<ExclusionZoneProvider<?>> exclusionZoneProviders = new ArrayList<>();

private final List<Consumer<ISubtypeRegistration>> subTypeProviders = new ArrayList<>();

private final Map<TlaCategory, TlaRecipeCategory> preparedCategories = new HashMap<>();


private final Comparisons<ItemConvertible> itemComparisons = new Comparisons<>() {
@Override
public void register(ItemConvertible item, TlaStackComparison comparison) {
subTypeProviders.add(registration -> registration.registerSubtypeInterpreter(item.asItem(), (stack, context) -> {
return comparison.hashFunction().hash(TlaStack.of(stack)) + "";
}));
}

};
private final Comparisons<Fluid> fluidComparisons = new Comparisons<>() {
@Override
public void register(Fluid fluid, TlaStackComparison comparison) {
subTypeProviders.add(registration -> registration.registerSubtypeInterpreter(FabricTypes.FLUID_STACK, fluid, (fluidVariant, context) -> {
return comparison.hashFunction().hash(TlaStack.bucketOf(fluidVariant.getFluidVariant())) + "";
}));
}
};

@Override
public Identifier getPluginUid() {
return Identifier.of("tla-api", "plugin");
}

private void init() {
categories.clear();
recipeFunctions.clear();
workstations.clear();
preparedCategories.clear();
subTypeProviders.clear();
PluginLoader.loadPlugins(this);
}

@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
// This is the earliest event, and we don't get anything before that.
init();

for (var category : categories) {
var jeiCategory = new TlaRecipeCategory(registration.getJeiHelpers(), category);
preparedCategories.put(category, jeiCategory);
registration.addRecipeCategories(jeiCategory);
}
}

@Override
public void registerItemSubtypes(ISubtypeRegistration registration) {
subTypeProviders.forEach(provider -> provider.accept(registration));
}

@Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
workstations.forEach((category, workstations) ->
workstations.forEach((category, workstations) ->
JeiUtils.convertIngredient(registration.getJeiHelpers(), workstations).forEach(workstation -> addCatalyst(registration, category, workstation)));
}

Expand Down Expand Up @@ -112,7 +145,7 @@ public Collection<IGuiClickableArea> getGuiClickableAreas(T containerScreen, dou
}
});
}

<T extends Screen> void addSizeProvider(ScreenSizeProvider<T> provider) {
registration.addGuiScreenHandler(provider.clazz, screen -> {
var bounds = provider.provider.apply(screen);
Expand Down Expand Up @@ -201,7 +234,7 @@ public List<Rect2i> getGuiExtraAreas(T containerScreen) {
sizeProviders.forEach(adders::addSizeProvider);
exclusionZoneProviders.forEach(adders::addExclusionZoneProvider);
}

@Override
public void addCategory(TlaCategory category) {
categories.add(category);
Expand Down Expand Up @@ -242,13 +275,23 @@ public <T extends Screen> void addScreenSizeProvider(Class<T> clazz, Function<T,
sizeProviders.add(new ScreenSizeProvider<>(clazz, provider));
}

@SuppressWarnings("unchecked")
@Override
public <T extends Screen> void addExclusionZoneProvider(Class<T> clazz, Function<T, ? extends Iterable<TlaBounds>> provider) {
if (!HandledScreen.class.isAssignableFrom(clazz)) return; // JEI only supports exclusion zones on handled screens
//noinspection unchecked
exclusionZoneProviders.add(new ExclusionZoneProvider<>((Class<HandledScreen<?>>) clazz, (Function<HandledScreen<?>, ? extends Iterable<TlaBounds>>) provider));
}

@Override
public Comparisons<ItemConvertible> getItemComparisons() {
return itemComparisons;
}

@Override
public Comparisons<Fluid> getFluidComparisons() {
return fluidComparisons;
}

@Override
public RecipeViewer getActiveViewer() {
return RecipeViewer.JEI;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,18 @@ public static EntryIngredient convertIngredient(TlaIngredient ingredient) {

public static TlaStack convertStack(EntryStack<?> stack) {
if (stack.getValue() instanceof FluidStack fluidStack) {
return TlaStack.of(FluidVariant.of(fluidStack.getFluid(), fluidStack.getPatch()), fluidStack.getAmount());
return convertStack(fluidStack);
} else if (stack.getValue() instanceof ItemStack itemStack) {
return TlaStack.of(itemStack);
} else {
return TlaStack.empty();
}
}

public static TlaStack convertStack(FluidStack fluidStack) {
return TlaStack.of(FluidVariant.of(fluidStack.getFluid(), fluidStack.getPatch()), fluidStack.getAmount());
}

public static TlaIngredient convertIngredient(EntryIngredient ingredient) {
if (ingredient.isEmpty()) return TlaIngredient.EMPTY;
if (ingredient.size() == 1) return TlaIngredient.ofStacks(convertStack(ingredient.getFirst()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

import dev.architectury.fluid.FluidStack;
import io.github.mattidragon.tlaapi.api.StackDragHandler;
import io.github.mattidragon.tlaapi.api.gui.TlaBounds;
import io.github.mattidragon.tlaapi.api.plugin.Comparisons;
import io.github.mattidragon.tlaapi.api.plugin.PluginContext;
import io.github.mattidragon.tlaapi.api.plugin.PluginLoader;
import io.github.mattidragon.tlaapi.api.plugin.RecipeViewer;
import io.github.mattidragon.tlaapi.api.recipe.TlaCategory;
import io.github.mattidragon.tlaapi.api.recipe.TlaIngredient;
import io.github.mattidragon.tlaapi.api.recipe.TlaRecipe;
import io.github.mattidragon.tlaapi.api.recipe.TlaStack;
import io.github.mattidragon.tlaapi.api.recipe.TlaStackComparison;
import io.github.mattidragon.tlaapi.impl.rei.util.TlaDragHandler;
import io.github.mattidragon.tlaapi.impl.rei.util.TlaExclusionZoneProvider;
import io.github.mattidragon.tlaapi.impl.rei.util.TlaScreenSizeProvider;
Expand All @@ -20,11 +25,18 @@
import me.shedaniel.rei.api.client.registry.screen.ExclusionZones;
import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry;
import me.shedaniel.rei.api.client.registry.screen.SimpleClickArea;
import me.shedaniel.rei.api.common.entry.comparison.EntryComparator;
import me.shedaniel.rei.api.common.entry.comparison.FluidComparatorRegistry;
import me.shedaniel.rei.api.common.entry.comparison.ItemComparatorRegistry;
import me.shedaniel.rei.api.common.plugins.PluginManager;
import me.shedaniel.rei.api.common.registry.ReloadStage;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.Item;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.recipe.RecipeType;
Expand All @@ -43,6 +55,26 @@ public class TlaApiReiPlugin implements REIClientPlugin, PluginContext {
private final List<TlaScreenSizeProvider<?>> screenSizeProviders = new ArrayList<>();
private final List<TlaExclusionZoneProvider<?>> exclusionZoneProviders = new ArrayList<>();
private final List<ClickAreaTuple<?>> clickAreas = new ArrayList<>();
private final List<Comparator<Item, ItemStack>> itemComparators = new ArrayList<>();
private final List<Comparator<Fluid, FluidStack>> fluidComparators = new ArrayList<>();

private final Comparisons<ItemConvertible> itemComparisons = new Comparisons<>() {
@Override
public void register(ItemConvertible item, TlaStackComparison comparison) {
itemComparators.add(new Comparator<>(item.asItem(), (context, stack) -> {
return comparison.hashFunction().hash(TlaStack.of(stack));
}));
}

};
private final Comparisons<Fluid> fluidComparisons = new Comparisons<>() {
@Override
public void register(Fluid fluid, TlaStackComparison comparison) {
fluidComparators.add(new Comparator<>(fluid, (context, stack) -> {
return comparison.hashFunction().hash(ReiUtil.convertStack(stack));
}));
}
};

@Override
public void preStage(PluginManager<REIClientPlugin> manager, ReloadStage stage) {
Expand Down Expand Up @@ -121,6 +153,16 @@ public void registerExclusionZones(ExclusionZones zones) {
exclusionZoneProviders.forEach(provider -> zones.register(provider.clazz, provider));
}

@Override
public void registerItemComparators(ItemComparatorRegistry registry) {
itemComparators.forEach(comparator -> registry.register(comparator.comparator(), comparator.key()));
}

@Override
public void registerFluidComparators(FluidComparatorRegistry registry) {
fluidComparators.forEach(comparator -> registry.register(comparator.comparator(), comparator.key()));
}

@Override
public void addCategory(TlaCategory category) {
categories.put(category, new TlaDisplayCategory(category));
Expand Down Expand Up @@ -170,6 +212,16 @@ public <T extends Screen> void addExclusionZoneProvider(Class<T> clazz, Function
exclusionZoneProviders.add(new TlaExclusionZoneProvider<>(clazz, provider));
}

@Override
public Comparisons<ItemConvertible> getItemComparisons() {
return itemComparisons;
}

@Override
public Comparisons<Fluid> getFluidComparisons() {
return fluidComparisons;
}

@Override
public RecipeViewer getActiveViewer() {
return RecipeViewer.REI;
Expand All @@ -180,6 +232,7 @@ public String toString() {
return "REI plugin handler";
}

private record Comparator<T, S>(T key, EntryComparator<S> comparator) {}
private record RecipeGenerator<T extends Recipe<?>>(RecipeType<T> type, Function<RecipeEntry<T>, TlaRecipe> generator) {}
private record ClickAreaTuple<T extends Screen>(Class<T> clazz, TlaCategory category, Function<T, TlaBounds> boundsFunction, boolean handledScreenCoords) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.github.mattidragon.tlaapi.api.plugin;

import io.github.mattidragon.tlaapi.api.recipe.TlaStackComparison;

public interface Comparisons<T> {
/**
* Adds a default comparison method for a stack for its key.
* @param item The key for the object to compare.
* @param comparison The comparison and hash function
*/
void register(T key, TlaStackComparison comparison);

/**
* Adds a default comparison method for a stack for its key.
* @param keys The keys for the object to compare.
* @param comparison The comparison and hash function
*/
default void register(TlaStackComparison comparison, @SuppressWarnings("unchecked") T... keys) {
for (T key : keys) {
register(key, comparison);
}
}

/**
* Adds a default comparison method for a stack for its key.
* @param keys The keys for the object to compare.
* @param comparison The comparison and hash function
*/
default void register(TlaStackComparison comparison, Iterable<T> keys) {
for (T key : keys) {
register(key, comparison);
}
}
}
Loading

0 comments on commit f3c7b02

Please sign in to comment.