-
Notifications
You must be signed in to change notification settings - Fork 6
Make recipe viewer slots more generic and fix some emi stuff #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: recipeviewers
Are you sure you want to change the base?
Changes from all commits
23918a8
e0b9ab8
bd3a527
06b1bb0
5a23f75
c8bc64e
40890cb
c60390d
b4c8114
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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(); | ||
| } | ||
|
|
||
| private void rebuildEmiSlot() { | ||
| if (value instanceof ItemEntryList itemEntryList) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On second thought, this entire subclass should be calls to |
||
|
|
||
| public static EmiIngredient toEmiIngredient(ItemEntryList list, float xeiChance, | ||
| UnaryOperator<ItemStack> realStack) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
|---|---|---|
| @@ -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 { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why does everything return |
||
| 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()); | ||
| } | ||
|
|
||
| } | ||
| } | ||
There was a problem hiding this comment.
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