Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ public enum Mixins implements IMixins {
THAUMCRAFT(new MixinBuilder()
.addClientMixins("thaumcraft.ClientTickEventsFMLMixin")
.setPhase(Phase.LATE)
.addRequiredMod(TargetedMod.THAUMCRAFT));
.addRequiredMod(TargetedMod.THAUMCRAFT)),
NEI(new MixinBuilder()
.addCommonMixins("nei.RecipeInfoMixin")
.setPhase(Phase.LATE)
.addRequiredMod(TargetedMod.NEI));

private final MixinBuilder builder;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

public enum TargetedMod implements ITargetMod {

THAUMCRAFT("Thaumcraft");
THAUMCRAFT("Thaumcraft"),
NEI("NotEnoughItems");

private final TargetModBuilder builder;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.cleanroommc.modularui.core.mixins.late.nei;


import com.cleanroommc.modularui.api.IMuiScreen;
import com.cleanroommc.modularui.integration.nei.INEIRecipeTransfer;
import com.cleanroommc.modularui.integration.nei.ModularUIGuiContainerStackPositioner;
import com.cleanroommc.modularui.integration.nei.NEIModularUIConfig;
import com.cleanroommc.modularui.screen.ModularContainer;

import net.minecraft.client.gui.inventory.GuiContainer;

import codechicken.nei.api.IOverlayHandler;
import codechicken.nei.api.IStackPositioner;
import codechicken.nei.recipe.RecipeInfo;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.Arrays;

/*
Mixin to properly handle idents for modular uis
*/
@Mixin(RecipeInfo.class)
public class RecipeInfoMixin {

@Inject(method = "hasOverlayHandler(Lnet/minecraft/client/gui/inventory/GuiContainer;Ljava/lang/String;)Z", remap = false, cancellable = true, at = @At("HEAD"))
private static void modularui$hasOverlayHandler(GuiContainer gui, String ident, CallbackInfoReturnable<Boolean> ci) {
if (gui instanceof IMuiScreen && gui.inventorySlots instanceof ModularContainer muc &&
muc instanceof INEIRecipeTransfer<?> tr && Arrays.asList(tr.getIdents()).contains(ident)) {
ci.setReturnValue(true);
}
}

@Inject(method = "getStackPositioner", remap = false, cancellable = true, at = @At("HEAD"))
private static void modularui$getStackPositioner(GuiContainer gui, String ident, CallbackInfoReturnable<IStackPositioner> ci) {
ModularUIGuiContainerStackPositioner<?> positioner = ModularUIGuiContainerStackPositioner.of(gui, ident);
if (positioner != null) {
ci.setReturnValue(positioner);
}
}

@Inject(method = "getOverlayHandler", remap = false, cancellable = true, at = @At("HEAD"))
private static void modularui$getOverlayHandler(GuiContainer gui, String ident, CallbackInfoReturnable<IOverlayHandler> ci) {
if (gui instanceof IMuiScreen && gui.inventorySlots instanceof ModularContainer muc &&
muc instanceof INEIRecipeTransfer<?> tr && Arrays.asList(tr.getIdents()).contains(ident)) {
ci.setReturnValue(NEIModularUIConfig.overlayHandler);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.cleanroommc.modularui.integration.nei;

import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;

import codechicken.nei.PositionedStack;
import codechicken.nei.recipe.GuiOverlayButton;
import codechicken.nei.recipe.IRecipeHandler;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public interface INEIRecipeTransfer<G extends GuiContainer> {

String[] getIdents();

default void overlayRecipe(G gui, IRecipeHandler recipe, int recipeIndex, boolean maxTransfer) {
transferRecipe(gui, recipe, recipeIndex, maxTransfer ? Integer.MAX_VALUE : 1);
}

int transferRecipe(G gui, IRecipeHandler recipe, int recipeIndex, int multiplier);

default boolean canFillCraftingGrid(G gui, IRecipeHandler recipe, int recipeIndex) {
return true;
}

default boolean craft(G gui, IRecipeHandler recipe, int recipeIndex, int multiplier) {
return false;
}

default boolean canCraft(G gui, IRecipeHandler recipe, int recipeIndex) {
return false;
}

default List<GuiOverlayButton.ItemOverlayState> presenceOverlay(G gui, IRecipeHandler recipe, int recipeIndex) {
final List<GuiOverlayButton.ItemOverlayState> itemPresenceSlots = new ArrayList<>();
final List<PositionedStack> ingredients = recipe.getIngredientStacks(recipeIndex);
final List<ItemStack> invStacks = gui.inventorySlots.inventorySlots.stream()
.filter(
s -> s != null && s.getStack() != null
&& s.getStack().stackSize > 0
&& s.isItemValid(s.getStack())
&& s.canTakeStack(gui.mc.thePlayer))
.map(s -> s.getStack().copy()).collect(Collectors.toList());

for (PositionedStack stack : ingredients) {
Optional<ItemStack> used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is))
.findAny();

itemPresenceSlots.add(new GuiOverlayButton.ItemOverlayState(stack, used.isPresent()));

if (used.isPresent()) {
ItemStack is = used.get();
is.stackSize -= 1;
}
}

return itemPresenceSlots;
}

default ArrayList<PositionedStack> positionStacks(G gui, ArrayList<PositionedStack> stacks) {
return stacks;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.cleanroommc.modularui.integration.nei;

import com.cleanroommc.modularui.api.IMuiScreen;
import com.cleanroommc.modularui.screen.GuiContainerWrapper;
import com.cleanroommc.modularui.screen.ModularContainer;

import net.minecraft.client.gui.inventory.GuiContainer;

import codechicken.nei.api.IOverlayHandler;
import codechicken.nei.recipe.GuiOverlayButton;
import codechicken.nei.recipe.IRecipeHandler;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class ModularUIGuiContainerStackOverlay implements IOverlayHandler {

private interface Action<T, G extends GuiContainer & IMuiScreen> {
T doAction(G gui, INEIRecipeTransfer<G> tr);
}

@SuppressWarnings("unchecked")
private static <T, G extends GuiContainer & IMuiScreen> T doAction(GuiContainer gui, Action<T, G> action) {
if (gui instanceof IMuiScreen && gui.inventorySlots instanceof ModularContainer mc && mc instanceof INEIRecipeTransfer<?> tr) {
return action.doAction((G) gui, (INEIRecipeTransfer<G>) tr);
}
return null;
}

@Override
public void overlayRecipe(GuiContainer gui, IRecipeHandler recipe, int recipeIndex, boolean maxTransfer) {
doAction(gui, (mui, tr) -> {
tr.overlayRecipe(mui, recipe, recipeIndex, maxTransfer);
return null;
});
}

@Override
public int transferRecipe(GuiContainer gui, IRecipeHandler recipe, int recipeIndex, int multiplier) {
var res = doAction(gui, (mui, tr) -> tr.transferRecipe(mui, recipe, recipeIndex, multiplier));
return res != null ? res : IOverlayHandler.super.transferRecipe(gui, recipe, recipeIndex, multiplier);
}

@Override
public boolean canFillCraftingGrid(GuiContainer gui, IRecipeHandler recipe, int recipeIndex) {
var res = doAction(gui, (mui, tr) -> tr.canFillCraftingGrid(mui, recipe, recipeIndex));
return res != null ? res : IOverlayHandler.super.canFillCraftingGrid(gui, recipe, recipeIndex);
}

@Override
public boolean craft(GuiContainer gui, IRecipeHandler recipe, int recipeIndex, int multiplier) {
var res = doAction(gui, (mui, tr) -> tr.craft(mui, recipe, recipeIndex, multiplier));
return res != null ? res : IOverlayHandler.super.craft(gui, recipe, recipeIndex, multiplier);
}

@Override
public boolean canCraft(GuiContainer gui, IRecipeHandler recipe, int recipeIndex) {
var res = doAction(gui, (mui, tr) -> tr.canCraft(mui, recipe, recipeIndex));
return res != null ? res : IOverlayHandler.super.canCraft(gui, recipe, recipeIndex);
}

@Override
public List<GuiOverlayButton.ItemOverlayState> presenceOverlay(GuiContainer gui, IRecipeHandler recipe, int recipeIndex) {
var res = doAction(gui, (mui, tr) -> tr.presenceOverlay(mui, recipe, recipeIndex));
return res != null ? res : IOverlayHandler.super.presenceOverlay(gui, recipe, recipeIndex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.cleanroommc.modularui.integration.nei;

import com.cleanroommc.modularui.api.IMuiScreen;
import com.cleanroommc.modularui.screen.ModularContainer;

import net.minecraft.client.gui.inventory.GuiContainer;

import codechicken.nei.PositionedStack;
import codechicken.nei.api.IStackPositioner;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Arrays;

public class ModularUIGuiContainerStackPositioner<G extends GuiContainer & IMuiScreen> implements IStackPositioner {

@Nullable
@SuppressWarnings("unchecked")
public static <G extends GuiContainer & IMuiScreen> ModularUIGuiContainerStackPositioner<G> of(GuiContainer gui, String ident) {
if (gui instanceof IMuiScreen && gui.inventorySlots instanceof ModularContainer mc &&
mc instanceof INEIRecipeTransfer<?> tr && Arrays.asList(tr.getIdents()).contains(ident)) {
return new ModularUIGuiContainerStackPositioner<>((G) gui, (INEIRecipeTransfer<G>) tr);
}
return null;
}

public final G wrapper;
public final INEIRecipeTransfer<G> recipeTransfer;

public ModularUIGuiContainerStackPositioner(G wrapper, INEIRecipeTransfer<G> recipeTransfer) {
this.wrapper = wrapper;
this.recipeTransfer = recipeTransfer;
}

@Override
public ArrayList<PositionedStack> positionStacks(ArrayList<PositionedStack> ai) {
return recipeTransfer.positionStacks(wrapper, ai);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
@SuppressWarnings("unused")
public class NEIModularUIConfig implements IConfigureNEI {

public static final ModularUIGuiContainerStackOverlay overlayHandler = new ModularUIGuiContainerStackOverlay();

@Override
public void loadConfig() {
GuiContainerManager.addInputHandler(new ModularUIContainerInputHandler());
Expand Down