Skip to content
Open
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 @@ -5,6 +5,8 @@
import brachy.modularui.screen.viewport.GuiContext;
import brachy.modularui.theme.WidgetTheme;

import brachy.modularui.widgets.TextWidget;

import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentContents;
Expand Down Expand Up @@ -62,6 +64,11 @@ private Component getComp() {
return getComp().getVisualOrderText();
}

@Override
public TextWidget<?> asWidget() {
return new TextWidget<>(this::getComp);
}

@Override
public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) {
Component comp = getComp();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package brachy.modularui.integration.emi;

import brachy.modularui.drawable.ClientTooltipComponentIcon;
import brachy.modularui.drawable.GuiTextures;
import brachy.modularui.integration.recipeviewer.RecipeSlotRole;
import brachy.modularui.integration.recipeviewer.RecipeViewerSlotWidget;
import brachy.modularui.integration.recipeviewer.entry.EntryList;
import brachy.modularui.integration.recipeviewer.entry.fluid.FluidEntryList;
import brachy.modularui.integration.recipeviewer.entry.fluid.FluidStackList;
import brachy.modularui.integration.recipeviewer.entry.fluid.FluidTagList;
import brachy.modularui.integration.recipeviewer.entry.item.ItemEntryList;
import brachy.modularui.integration.recipeviewer.entry.item.ItemStackList;
import brachy.modularui.integration.recipeviewer.entry.item.ItemTagList;

import brachy.modularui.screen.viewport.ModularGuiContext;
import brachy.modularui.theme.WidgetThemeEntry;

import dev.emi.emi.api.forge.ForgeEmiStack;
import dev.emi.emi.api.stack.EmiIngredient;
import dev.emi.emi.api.stack.EmiStack;
import dev.emi.emi.api.widget.SlotWidget;

import dev.emi.emi.api.widget.TankWidget;

import lombok.Getter;
import lombok.experimental.Accessors;

import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;

import org.jetbrains.annotations.ApiStatus;

import java.util.ArrayList;
import java.util.List;
import java.util.function.UnaryOperator;

public class EmiRecipeViewerSlot extends RecipeViewerSlotWidget<EmiRecipeViewerSlot> {

@ApiStatus.Internal
@Getter
private SlotWidget slotWidget;
private int x, y;

@Accessors(fluent = true)
@Getter
private RecipeSlotRole recipeSlotRole;
private EntryList<?> value;
private float chance = 1f;

public EmiRecipeViewerSlot() {
super();
slotWidget = new SlotWidget(EmiIngredient.of(Ingredient.EMPTY), 0, 0);
recipeSlotRole = RecipeSlotRole.RENDER_ONLY;

size(18, 18);

tooltipAutoUpdate(true);
tooltipDynamic(tooltip -> {
for (ClientTooltipComponent ctc : this.slotWidget.getTooltip(getContext().getAbsMouseX(), getContext().getAbsMouseY())) {
tooltip.addDrawableLine(new ClientTooltipComponentIcon(ctc));
}
});
}

@Override
public EmiRecipeViewerSlot recipeSlotRole(RecipeSlotRole recipeSlotRole) {
this.recipeSlotRole = recipeSlotRole;
slotWidget.catalyst(recipeSlotRole == RecipeSlotRole.CATALYST);
return getThis();
}

@Override
public EmiRecipeViewerSlot value(FluidEntryList fluidEntryList) {
value = fluidEntryList;
rebuildEmiSlot();
background(GuiTextures.SLOT_FLUID);
return getThis();
}

@Override
public EmiRecipeViewerSlot value(ItemEntryList itemEntryList) {
value = itemEntryList;
rebuildEmiSlot();
background(GuiTextures.SLOT_ITEM);
return getThis();
}

@Override
public EmiRecipeViewerSlot chance(float chance) {
this.chance = chance;
return getThis();
}
Comment on lines +89 to +93
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe use a fluent accessor for this


private void rebuildEmiSlot() {
if (value instanceof ItemEntryList itemEntryList) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this hardcoded to items and fluids?

slotWidget = new SlotWidget(EmiIngredientHandler.toEmiIngredient(itemEntryList, chance, UnaryOperator.identity()), 0, 0);
} else {
slotWidget = new TankWidget(EmiIngredientHandler.toEmiIngredient((FluidEntryList)value, chance), 0, 0, 18, 18, 1);
Comment on lines +98 to +99
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check the cast here, you cannot know what type that object actually is.

}
slotWidget.drawBack(false);
}

@Override
public void draw(ModularGuiContext context, WidgetThemeEntry<?> widgetTheme) {
context.getGraphics().pose().translate(-this.x, -this.y, 0);
this.slotWidget.render(context.getGraphics(), context.getMouseX(), context.getMouseY(), context.getRenderPartialTicks());
context.getGraphics().pose().translate(this.x, this.y, 0);
}

@Override
public Result onMousePressed(int button) {
this.slotWidget.mouseClicked(getContext().getMouseX(), getContext().getAbsMouseY(), button);
return Result.SUCCESS;
}

@Override
public Result onKeyPressed(int keyCode, int scanCode, int modifiers) {
return this.slotWidget.keyPressed(keyCode, scanCode, modifiers) ? Result.SUCCESS : Result.ACCEPT;
}

public static class EmiIngredientHandler {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need to put the util methods into an inner class, as this is (should be) only loaded with EMI loaded.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, this entire subclass should be calls to EmiStackConverter instead.


public static EmiIngredient toEmiIngredient(ItemEntryList list, float xeiChance,
UnaryOperator<ItemStack> realStack) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDK if realStack should even exist? What's it actually used for?

List<EmiIngredient> ingredients = new ArrayList<>();
if (list instanceof ItemTagList tagList) {
ingredients.addAll(tagList.getEntries().stream()
.map(ItemTagList.ItemTagEntry::stacks)
.map(stream -> EmiIngredient.of(stream.map(realStack).map(EmiStack::of).toList()).setChance(xeiChance)).toList());
}
if (list instanceof ItemStackList stackList) {
ingredients.add(EmiIngredient.of(stackList.stream().map(realStack).map(EmiStack::of).toList()).setChance(xeiChance));
}

if (ingredients.isEmpty()) return EmiIngredient.of(Ingredient.EMPTY);
if (ingredients.size() == 1) return ingredients.get(0);
return EmiIngredient.of(ingredients);
}

public static EmiIngredient toEmiIngredient(FluidEntryList list, float xeiChance) {

List<EmiIngredient> ingredients = new ArrayList<>();

if (list instanceof FluidTagList tagList) {
ingredients.addAll(tagList.getEntries().stream()
.map(FluidTagList.FluidTagEntry::stacks)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of this, get the list entries' tags and create EMI tag ingredients from those

.map(stream -> EmiIngredient.of(stream.map(ForgeEmiStack::of).toList()).setChance(xeiChance))
.toList()
);
}

if (list instanceof FluidStackList stackList) {
ingredients.add(EmiIngredient.of(stackList.stream().map(ForgeEmiStack::of).toList()).setChance(xeiChance));
}

if (ingredients.isEmpty()) return EmiIngredient.of(Ingredient.EMPTY);
if (ingredients.size() == 1) return ingredients.get(0);
return EmiIngredient.of(ingredients);
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package brachy.modularui.integration.emi.recipe;

import brachy.modularui.ModularUI;
import brachy.modularui.api.IThemeApi;
import brachy.modularui.api.drawable.IRichTextBuilder;
import brachy.modularui.api.widget.ITooltip;
import brachy.modularui.api.widget.IWidget;
import brachy.modularui.drawable.text.RichText;
import brachy.modularui.integration.emi.EmiRecipeViewerSlot;
import brachy.modularui.integration.recipeviewer.RecipeSlotRole;
import brachy.modularui.integration.recipeviewer.handlers.IngredientProvider;
import brachy.modularui.screen.EmbedHandler;
import brachy.modularui.screen.ModularPanel;
import brachy.modularui.screen.ModularScreen;
import brachy.modularui.screen.RichTooltip;
import brachy.modularui.theme.WidgetThemeKey;
import brachy.modularui.widgets.slot.FluidSlot;

import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
Expand All @@ -27,7 +24,6 @@
import dev.emi.emi.api.stack.EmiStack;
import dev.emi.emi.api.widget.Bounds;
import dev.emi.emi.api.widget.SlotWidget;
import dev.emi.emi.api.widget.TankWidget;
import dev.emi.emi.api.widget.Widget;
import dev.emi.emi.api.widget.WidgetHolder;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -118,41 +114,14 @@ public ModularPanel<?> transform(ModularPanel<?> panel) {
}

public IWidget transformWidget(IWidget widget, Iterator<EmiIngredient> in, Iterator<EmiStack> out) {
if (!(widget instanceof IngredientProvider<?> provider)) return widget;

RecipeSlotRole role = provider.getRecipeRole();
if (role == RecipeSlotRole.RENDER_ONLY) return widget;
if (!(widget instanceof EmiRecipeViewerSlot recipeViewerSlot)) return widget;

EmiIngredient ingr = EmiStack.EMPTY;
if (role == RecipeSlotRole.INPUT && in.hasNext()) {
ingr = in.next();
} else if (role == RecipeSlotRole.OUTPUT && out.hasNext()) {
ingr = out.next();
if (recipeViewerSlot.recipeSlotRole() == RecipeSlotRole.OUTPUT) {
recipeViewerSlot.getSlotWidget().recipeContext(this);
}

SlotWidget emiSlot = null;
WidgetThemeKey<?> widgetThemeKey = null;
if (widget instanceof FluidSlot slot) {
if (!slot.isAlwaysShowFull()) {
emiSlot = new TankWidget(ingr, 0, 0, slot.getArea().width, slot.getArea().height, slot.getCapacity());
}
widgetThemeKey = IThemeApi.FLUID_SLOT;
}
if (emiSlot == null) emiSlot = new SlotWidget(ingr, 0, 0);
if (widgetThemeKey == null) widgetThemeKey = IThemeApi.ITEM_SLOT;

emiSlot.drawBack(false);

if (role == RecipeSlotRole.CATALYST) {
emiSlot.catalyst(true);
} else if (role == RecipeSlotRole.OUTPUT) {
emiSlot.recipeContext(this);
}

return new EMISlotWidgetWrapper<>(emiSlot)
.copyResizerOf(widget)
.copyVisualsOf(widget)
.widgetTheme(widgetThemeKey);
return recipeViewerSlot;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package brachy.modularui.integration.jei;

import brachy.modularui.integration.recipeviewer.RecipeViewerSlotWidget;
import brachy.modularui.integration.recipeviewer.entry.fluid.FluidEntryList;

import brachy.modularui.integration.recipeviewer.entry.item.ItemEntryList;

import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.runtime.IIngredientManager;
import mezz.jei.common.input.ClickableIngredient;

import mezz.jei.common.util.ImmutableRect2i;

import net.minecraft.world.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;

import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

import static brachy.modularui.integration.jei.ModularUIJeiPlugin.jeiHelpers;

public class JeiRecipeViewerSlot {

public static class JeiIngredientHandler {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto for the inner class comment


public static List<Object> toJeiIngredient(FluidEntryList list) {
return list.getStacks()
.stream()
.filter(stack -> !stack.isEmpty())
.map(JeiIngredientHandler::getJEIFluid)
.toList();
}

public static List<Object> toJeiIngredientClickable(FluidEntryList list, int x, int y, int w, int h) {
return list.getStacks()
.stream()
.filter(stack -> !stack.isEmpty())
.map(stack -> getJEIFluidClickable(stack, x, y, w, h))
.toList();
}

public static Object getJEIFluid(FluidStack fluidStack) {
return jeiHelpers.getPlatformFluidHelper().create(fluidStack.getFluid(), fluidStack.getAmount(), fluidStack.getTag());
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the mod only supports forge/neoforge, you don't need to bother with this; the stack this returns is equal to the one you put in.

}

public static @Nullable Object getJEIFluidClickable(FluidStack fluidStack, int x, int y, int w, int h) {
var ingredient = jeiHelpers.getPlatformFluidHelper().create(fluidStack.getFluid(), fluidStack.getAmount(), fluidStack.getTag());
return jeiHelpers.getIngredientManager().createTypedIngredient(ingredient)
.map(typedIngredient -> new ClickableIngredient<>(typedIngredient, new ImmutableRect2i(x, y, w, h)))
.orElse(null);
}

public static @Nullable Object getJEIStackClickable(ItemStack stack, int x, int y, int w, int h) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does everything return Object?

IIngredientManager ingredientManager = jeiHelpers.getIngredientManager();
return ingredientManager.createTypedIngredient(VanillaTypes.ITEM_STACK, stack)
.map(typedIngredient -> new ClickableIngredient<>(typedIngredient, new ImmutableRect2i(x, y, w, h)))
.orElse(null);
}

public static List<Object> toJeiIngredient(ItemEntryList list, UnaryOperator<ItemStack> realStack) {
return list.getStacks()
.stream()
.filter(stack -> !stack.isEmpty())
.map(realStack)
.collect(Collectors.toList());
}

public static List<Object> toJeiIngredientClickable(ItemEntryList list, int x, int y, int w, int h,
UnaryOperator<ItemStack> realStack) {
return list.getStacks()
.stream()
.filter(stack -> !stack.isEmpty())
.map(realStack)
.map(stack -> getJEIStackClickable(stack, x, y, w, h))
.collect(Collectors.toList());
}

}
}
Loading