jei/rei/emi for edify and craft phial

This commit is contained in:
yrsegal@gmail.com 2022-08-09 13:49:57 -04:00
parent 027a3d0139
commit cbe1c77433
22 changed files with 754 additions and 35 deletions

View file

@ -0,0 +1,55 @@
package at.petrak.hexcasting.interop.utils;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.common.items.magic.ItemManaBattery;
import at.petrak.hexcasting.common.lib.HexItems;
import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Pair;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import java.util.List;
public class PhialRecipeStackBuilder {
private static ItemStack makeBattery(int unit, int size) {
return ItemManaBattery.withMana(new ItemStack(HexItems.BATTERY), unit * size, unit * size);
}
public static Pair<List<ItemStack>, List<ItemStack>> createStacks() {
List<ItemStack> inputItems = Lists.newArrayList();
List<ItemStack> outputItems = Lists.newArrayList();
int dust = HexConfig.common().dustManaAmount();
int shard = HexConfig.common().shardManaAmount();
int charged = HexConfig.common().chargedCrystalManaAmount();
if (dust > 0) {
inputItems.add(new ItemStack(HexItems.AMETHYST_DUST, 1));
outputItems.add(makeBattery(dust, 1));
inputItems.add(new ItemStack(HexItems.AMETHYST_DUST, 64));
outputItems.add(makeBattery(dust, 64));
}
if (shard > 0) {
inputItems.add(new ItemStack(Items.AMETHYST_SHARD, 1));
outputItems.add(makeBattery(shard, 1));
inputItems.add(new ItemStack(Items.AMETHYST_SHARD, 64));
outputItems.add(makeBattery(shard, 64));
}
if (charged > 0) {
inputItems.add(new ItemStack(HexItems.CHARGED_AMETHYST, 1));
outputItems.add(makeBattery(charged, 1));
inputItems.add(new ItemStack(HexItems.CHARGED_AMETHYST, 64));
outputItems.add(makeBattery(charged, 64));
}
return new Pair<>(inputItems, outputItems);
}
public static boolean shouldAddRecipe() {
return HexConfig.common().dustManaAmount() > 0 ||
HexConfig.common().shardManaAmount() > 0 ||
HexConfig.common().chargedCrystalManaAmount() > 0;
}
}

View file

@ -147,6 +147,8 @@
"tag.hexcasting.akashic_planks": "Edified Planks",
"tag.hexcasting.phial_base": "Empty Phials",
"emi.category.hexcasting.brainsweep": "Flay Mind",
"emi.category.hexcasting.craft.battery": "Craft Phial",
"emi.category.hexcasting.edify": "Edify Sapling",
"emi.category.hexcasting.villager_leveling": "Trade Leveling",
"emi.category.hexcasting.villager_profession": "Villager Profession",

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -50,7 +50,7 @@ public record EmiBrainsweepRecipe(EmiIngredient blockInput,
@Override
public void addWidgets(WidgetHolder widgets) {
widgets.addTexture(OVERLAY, 0, 0, 118, 85, 0, 0, 118, 85, 128, 128);
widgets.addTexture(OVERLAY, 0, 0, getDisplayWidth(), getDisplayHeight(), 0, 0, getDisplayWidth(), getDisplayHeight(), 128, 128);
widgets.addSlot(blockInput, 11, 34).drawBack(false).custom(null, 0, 0, 19, 19);
widgets.add(new TheCoolerSlotWidget(villagerInput, 37, 19, 2.75f).useOffset(false).customShift(-8.5f, 2.485f))

View file

@ -0,0 +1,81 @@
package at.petrak.hexcasting.fabric.interop.emi;
import at.petrak.hexcasting.common.lib.HexBlocks;
import dev.emi.emi.api.recipe.EmiRecipe;
import dev.emi.emi.api.recipe.EmiRecipeCategory;
import dev.emi.emi.api.stack.EmiIngredient;
import dev.emi.emi.api.stack.EmiStack;
import dev.emi.emi.api.widget.WidgetHolder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.ItemTags;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class EmiEdifyRecipe implements EmiRecipe {
private static final ResourceLocation OVERLAY = modLoc("textures/gui/edify_jei.png");
private final EmiIngredient saplings;
private final EmiIngredient leaves;
private final EmiIngredient log;
public EmiEdifyRecipe() {
this.saplings = EmiIngredient.of(ItemTags.SAPLINGS);
this.leaves = EmiIngredient.of(List.of(
EmiStack.of(HexBlocks.AKASHIC_LEAVES1),
EmiStack.of(HexBlocks.AKASHIC_LEAVES2),
EmiStack.of(HexBlocks.AKASHIC_LEAVES3)
));
this.log = EmiStack.of(HexBlocks.AKASHIC_LOG);
}
@Override
public EmiRecipeCategory getCategory() {
return HexEMIPlugin.EDIFY;
}
@Override
public @Nullable ResourceLocation getId() {
return HexEMIPlugin.EDIFY_ID;
}
@Override
public List<EmiIngredient> getInputs() {
return List.of(saplings);
}
@Override
public List<EmiStack> getOutputs() {
return Stream.concat(leaves.getEmiStacks().stream(), log.getEmiStacks().stream()).collect(Collectors.toList());
}
@Override
public int getDisplayWidth() {
return 79;
}
@Override
public int getDisplayHeight() {
return 61;
}
@Override
public boolean supportsRecipeTree() {
return false;
}
@Override
public void addWidgets(WidgetHolder widgets) {
widgets.addTexture(OVERLAY, 0, 0, getDisplayWidth(), getDisplayHeight(), 0, 0, getDisplayWidth(), getDisplayHeight(), 128, 128);
widgets.addSlot(saplings, 11, 21).drawBack(false).custom(null, 0, 0, 19, 19);
widgets.addGeneratedSlot(r -> {
var stacks = leaves.getEmiStacks();
return stacks.get(r.nextInt(stacks.size()));
}, 0, 50, 9).drawBack(false).recipeContext(this).custom(null, 0, 0, 19, 19);
widgets.addSlot(log, 50, 34).drawBack(false).recipeContext(this).custom(null, 0, 0, 19, 19);
}
}

View file

@ -0,0 +1,83 @@
package at.petrak.hexcasting.fabric.interop.emi;
import at.petrak.hexcasting.api.mod.HexItemTags;
import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder;
import dev.emi.emi.EmiUtil;
import dev.emi.emi.api.recipe.EmiRecipe;
import dev.emi.emi.api.recipe.EmiRecipeCategory;
import dev.emi.emi.api.stack.EmiIngredient;
import dev.emi.emi.api.stack.EmiStack;
import dev.emi.emi.api.widget.WidgetHolder;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.stream.Collectors;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class EmiPhialRecipe implements EmiRecipe {
private static final ResourceLocation OVERLAY = modLoc("textures/gui/phial_jei.png");
private final EmiIngredient inputs;
private final EmiIngredient bottle;
private final EmiIngredient outputs;
private final int uniq = EmiUtil.RANDOM.nextInt();
public EmiPhialRecipe() {
var stacks = PhialRecipeStackBuilder.createStacks();
this.inputs = EmiIngredient.of(stacks.getFirst().stream().map(EmiStack::of).collect(Collectors.toList()));
this.bottle = EmiIngredient.of(HexItemTags.PHIAL_BASE);
this.outputs = EmiIngredient.of(stacks.getSecond().stream().map(EmiStack::of).collect(Collectors.toList()));
}
@Override
public EmiRecipeCategory getCategory() {
return HexEMIPlugin.PHIAL;
}
@Override
public @Nullable ResourceLocation getId() {
return HexEMIPlugin.PHIAL_ID;
}
@Override
public List<EmiIngredient> getInputs() {
return List.of(inputs, bottle);
}
@Override
public List<EmiStack> getOutputs() {
return outputs.getEmiStacks();
}
@Override
public int getDisplayWidth() {
return 113;
}
@Override
public int getDisplayHeight() {
return 40;
}
@Override
public boolean supportsRecipeTree() {
return false;
}
@Override
public void addWidgets(WidgetHolder widgets) {
widgets.addTexture(OVERLAY, 0, 0, getDisplayWidth(), getDisplayHeight(), 0, 0, getDisplayWidth(), getDisplayHeight(), 128, 128);
widgets.addGeneratedSlot((r) -> {
var stacks = inputs.getEmiStacks();
return stacks.get(r.nextInt(stacks.size()));
}, uniq, 11, 11).drawBack(false).custom(null, 0, 0, 19, 19);
widgets.addSlot(bottle, 46, 11).drawBack(false).custom(null, 0, 0, 19, 19);
widgets.addGeneratedSlot((r) -> {
var stacks = outputs.getEmiStacks();
return stacks.get(r.nextInt(stacks.size()));
}, uniq, 84, 11).drawBack(false).recipeContext(this).custom(null, 0, 0, 19, 19);
}
}

View file

@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.mod.HexItemTags;
import at.petrak.hexcasting.common.recipe.BrainsweepRecipe;
import at.petrak.hexcasting.common.recipe.HexRecipeSerializers;
import at.petrak.hexcasting.common.recipe.ingredient.VillagerIngredient;
import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder;
import at.petrak.hexcasting.mixin.accessor.AccessorPoiType;
import dev.emi.emi.api.EmiPlugin;
import dev.emi.emi.api.EmiRegistry;
@ -28,6 +29,8 @@ import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class HexEMIPlugin implements EmiPlugin {
private static final ResourceLocation BRAINSWEEP_ID = modLoc("brainsweep");
public static final ResourceLocation PHIAL_ID = modLoc("craft/battery");
public static final ResourceLocation EDIFY_ID = modLoc("edify");
private static final ResourceLocation VILLAGER_LEVELING_ID = modLoc("villager_leveling");
private static final ResourceLocation VILLAGER_PROFESSION_ID = modLoc("villager_profession");
@ -39,6 +42,14 @@ public class HexEMIPlugin implements EmiPlugin {
new PatternRendererEMI(BRAINSWEEP_ID, 16, 16),
new EmiTexture(SIMPLIFIED_ICON_BRAINSWEEP, 0, 0, 16, 16, 16, 16, 16, 16));
public static final EmiRecipeCategory PHIAL = new EmiRecipeCategory(PHIAL_ID,
new PatternRendererEMI(PHIAL_ID, 12, 12).shift(2, 2),
new EmiTexture(SIMPLIFIED_ICON_BRAINSWEEP, 0, 0, 16, 16, 16, 16, 16, 16)); // temp
public static final EmiRecipeCategory EDIFY = new EmiRecipeCategory(EDIFY_ID,
new PatternRendererEMI(EDIFY_ID, 16, 16).strokeOrder(false),
new EmiTexture(SIMPLIFIED_ICON_BRAINSWEEP, 0, 0, 16, 16, 16, 16, 16, 16)); // temp
public static final EmiRecipeCategory VILLAGER_LEVELING = new EmiRecipeCategory(VILLAGER_LEVELING_ID,
EmiStack.of(Items.EMERALD),
new EmiTexture(SIMPLIFIED_ICON_LEVELING, 0, 0, 16, 16, 16, 16, 16, 16));
@ -50,9 +61,13 @@ public class HexEMIPlugin implements EmiPlugin {
@Override
public void register(EmiRegistry registry) {
registry.addCategory(BRAINSWEEP);
registry.addCategory(PHIAL);
registry.addCategory(EDIFY);
registry.addCategory(VILLAGER_LEVELING);
registry.addCategory(VILLAGER_PROFESSION);
registry.addWorkstation(BRAINSWEEP, EmiIngredient.of(HexItemTags.WANDS));
registry.addWorkstation(PHIAL, EmiIngredient.of(HexItemTags.WANDS));
registry.addWorkstation(EDIFY, EmiIngredient.of(HexItemTags.WANDS));
for (BrainsweepRecipe recipe : registry.getRecipeManager().getAllRecipesFor(HexRecipeSerializers.BRAINSWEEP_TYPE)) {
var inputs = EmiIngredient.of(recipe.blockIn().getDisplayedStacks().stream()
@ -62,6 +77,12 @@ public class HexEMIPlugin implements EmiPlugin {
registry.addRecipe(new EmiBrainsweepRecipe(inputs, villagerInput, output, recipe.getId()));
}
if (PhialRecipeStackBuilder.shouldAddRecipe()) {
registry.addRecipe(new EmiPhialRecipe());
}
registry.addRecipe(new EmiEdifyRecipe());
var basicVillager = new VillagerIngredient(null, null, 1);
for (VillagerProfession profession : Registry.VILLAGER_PROFESSION) {

View file

@ -19,7 +19,10 @@ public class PatternRendererEMI implements EmiRenderable {
private final int width;
private final int height;
private final boolean strokeOrder;
private int xOffset = 0;
private int yOffset = 0;
private boolean strokeOrder;
private final List<PatternEntry> patterns;
private final List<Vec2> pathfinderDots;
@ -34,11 +37,22 @@ public class PatternRendererEMI implements EmiRenderable {
this.height = h;
}
public PatternRendererEMI shift(int x, int y) {
xOffset += x;
yOffset += y;
return this;
}
public PatternRendererEMI strokeOrder(boolean order) {
strokeOrder = order;
return this;
}
@Override
public void render(PoseStack poseStack, int x, int y, float delta) {
long time = (System.currentTimeMillis() - startTime) / 50;
poseStack.pushPose();
poseStack.translate(x - 0.5f + width / 2f, y + 1 + height / 2f, 0);
poseStack.translate(xOffset + x - 0.5f + width / 2f, yOffset + y + 1 + height / 2f, 0);
poseStack.scale(width / 64f, height / 64f, 1f);
PatternDrawingUtil.drawPattern(poseStack, 0, 0, this.patterns, this.pathfinderDots, this.strokeOrder, time,
0xff_333030, 0xff_191818, 0xc8_0c0a0c, 0x80_666363);

View file

@ -20,6 +20,7 @@ import java.util.List;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class BrainsweepRecipeCategory implements DisplayCategory<BrainsweepRecipeDisplay> {
public static final ResourceLocation UID = modLoc("brainsweep");
private final ResourceLocation OVERLAY = modLoc("textures/gui/brainsweep.png");
private final Renderer icon;
@ -48,7 +49,7 @@ public class BrainsweepRecipeCategory implements DisplayCategory<BrainsweepRecip
widgets.add(Widgets.createDrawableWidget(((helper, matrices, mouseX, mouseY, delta) -> {
RenderSystem.enableBlend();
RenderSystem.setShaderTexture(0, OVERLAY);
GuiComponent.blit(matrices, bounds.getMinX(), bounds.getMinY(), 0, 0, 118, 85, 128, 128);
GuiComponent.blit(matrices, bounds.getMinX(), bounds.getMinY(), 0, 0, getDisplayWidth(display), getDisplayHeight(), 128, 128);
RenderSystem.disableBlend();
})));
widgets.add(new VillagerWidget(display.recipe.villagerIn(), bounds.getMinX(), bounds.getMinY()));

View file

@ -0,0 +1,76 @@
package at.petrak.hexcasting.fabric.interop.rei;
import com.mojang.blaze3d.systems.RenderSystem;
import me.shedaniel.math.Point;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.gui.Renderer;
import me.shedaniel.rei.api.client.gui.widgets.Widget;
import me.shedaniel.rei.api.client.gui.widgets.Widgets;
import me.shedaniel.rei.api.client.registry.display.DisplayCategory;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class EdifyRecipeCategory implements DisplayCategory<EdifyRecipeDisplay> {
public static final ResourceLocation UID = modLoc("edify");
private final ResourceLocation OVERLAY = modLoc("textures/gui/edify.png");
private final Renderer icon;
private final Component localizedName;
public EdifyRecipeCategory() {
localizedName = new TranslatableComponent("hexcasting.spell." + UID);
icon = new PatternRendererREI(UID, 16, 16).strokeOrder(false);
}
@Override
public Renderer getIcon() {
return icon;
}
@Override
public @NotNull Component getTitle() {
return localizedName;
}
@Override
public List<Widget> setupDisplay(EdifyRecipeDisplay display, Rectangle bounds) {
List<Widget> widgets = new ArrayList<>();
widgets.add(Widgets.createRecipeBase(bounds));
widgets.add(Widgets.createDrawableWidget(((helper, matrices, mouseX, mouseY, delta) -> {
RenderSystem.enableBlend();
RenderSystem.setShaderTexture(0, OVERLAY);
GuiComponent.blit(matrices, bounds.getMinX(), bounds.getMinY(), 0, 0, getDisplayWidth(display), getDisplayHeight(), 128, 128);
RenderSystem.disableBlend();
})));
widgets.add(Widgets.createSlot(new Point(bounds.getMinX() + 12, bounds.getMinY() + 22)).entries(display.getInputEntries().get(0)).disableBackground());
widgets.add(Widgets.createSlot(new Point(bounds.getMinX() + 51, bounds.getMinY() + 10)).entries(display.getOutputEntries().get(0)).disableBackground());
widgets.add(Widgets.createSlot(new Point(bounds.getMinX() + 51, bounds.getMinY() + 35)).entries(display.getOutputEntries().get(1)).disableBackground());
return widgets;
}
@Override
public CategoryIdentifier<? extends EdifyRecipeDisplay> getCategoryIdentifier() {
return HexREIPlugin.EDIFY;
}
@Override
public int getDisplayHeight() {
return 61;
}
@Override
public int getDisplayWidth(EdifyRecipeDisplay display) {
return 79;
}
}

View file

@ -0,0 +1,52 @@
package at.petrak.hexcasting.fabric.interop.rei;
import at.petrak.hexcasting.common.lib.HexBlocks;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.Display;
import me.shedaniel.rei.api.common.entry.EntryIngredient;
import me.shedaniel.rei.api.common.util.EntryIngredients;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.item.crafting.Ingredient;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.Optional;
public class EdifyRecipeDisplay implements Display {
protected EntryIngredient saplings;
protected EntryIngredient leaves;
protected EntryIngredient log;
public EdifyRecipeDisplay() {
this.saplings = EntryIngredients.ofIngredient(Ingredient.of(ItemTags.SAPLINGS));
this.leaves = EntryIngredients.ofItems(List.of(
HexBlocks.AKASHIC_LEAVES1,
HexBlocks.AKASHIC_LEAVES2,
HexBlocks.AKASHIC_LEAVES3
));
this.log = EntryIngredients.of(HexBlocks.AKASHIC_LOG);
}
@Override
public @Nonnull List<EntryIngredient> getInputEntries() {
return List.of(this.saplings);
}
@Override
public @Nonnull List<EntryIngredient> getOutputEntries() {
return List.of(this.leaves, this.log);
}
@Override
public @Nonnull Optional<ResourceLocation> getDisplayLocation() {
return Optional.of(EdifyRecipeCategory.UID);
}
@Override
public CategoryIdentifier<?> getCategoryIdentifier() {
return HexREIPlugin.EDIFY;
}
}

View file

@ -2,26 +2,25 @@ package at.petrak.hexcasting.fabric.interop.rei;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.recipe.BrainsweepRecipe;
import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder;
import com.google.common.collect.ImmutableSet;
import me.shedaniel.rei.api.client.plugins.REIClientPlugin;
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry;
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.util.EntryStacks;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.ItemLike;
import java.util.Set;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class HexREIPlugin implements REIClientPlugin {
public static final ResourceLocation UID = modLoc("brainsweep");
public static final CategoryIdentifier<BrainsweepRecipeDisplay> BRAINSWEEP = CategoryIdentifier.of(UID);
public static final CategoryIdentifier<BrainsweepRecipeDisplay> BRAINSWEEP = CategoryIdentifier.of(BrainsweepRecipeCategory.UID);
public static final CategoryIdentifier<PhialRecipeDisplay> PHIAL = CategoryIdentifier.of(PhialRecipeCategory.UID);
public static final CategoryIdentifier<EdifyRecipeDisplay> EDIFY = CategoryIdentifier.of(EdifyRecipeCategory.UID);
@Override
public void registerCategories(CategoryRegistry registry) {
registry.add(new BrainsweepRecipeCategory());
registry.add(new BrainsweepRecipeCategory(), new PhialRecipeCategory(), new EdifyRecipeCategory());
Set<ItemLike> wands = ImmutableSet.of(
HexItems.WAND_OAK,
HexItems.WAND_SPRUCE,
@ -34,13 +33,21 @@ public class HexREIPlugin implements REIClientPlugin {
HexItems.WAND_AKASHIC);
for (ItemLike wand : wands) {
registry.addWorkstations(BRAINSWEEP, EntryStacks.of(wand));
registry.addWorkstations(PHIAL, EntryStacks.of(wand));
registry.addWorkstations(EDIFY, EntryStacks.of(wand));
}
registry.removePlusButton(BRAINSWEEP);
registry.removePlusButton(PHIAL);
registry.removePlusButton(EDIFY);
}
@Override
public void registerDisplays(DisplayRegistry helper) {
helper.registerFiller(BrainsweepRecipe.class, BrainsweepRecipeDisplay::new);
if (PhialRecipeStackBuilder.shouldAddRecipe()) {
helper.add(new PhialRecipeDisplay());
}
helper.add(new EdifyRecipeDisplay());
}
}

View file

@ -22,11 +22,14 @@ public class PatternRendererREI implements Renderer {
private final int width;
private final int height;
private final boolean strokeOrder;
private boolean strokeOrder;
private final List<PatternEntry> patterns;
private final List<Vec2> pathfinderDots;
private int xOffset = 0;
private int yOffset = 0;
public PatternRendererREI(ResourceLocation pattern, int w, int h) {
var entry = PatternRegistry.lookupPattern(pattern);
this.strokeOrder = !entry.isPerWorld();
@ -37,6 +40,17 @@ public class PatternRendererREI implements Renderer {
this.height = h;
}
public PatternRendererREI shift(int x, int y) {
xOffset += x;
yOffset += y;
return this;
}
public PatternRendererREI strokeOrder(boolean order) {
strokeOrder = order;
return this;
}
@Environment(EnvType.CLIENT)
private int blitOffset;
@ -56,7 +70,7 @@ public class PatternRendererREI implements Renderer {
public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) {
long time = (System.currentTimeMillis() - startTime) / 50;
matrices.pushPose();
matrices.translate(bounds.getMinX() - 0.5f + width / 2f, bounds.getMinY() + height / 2f, blitOffset);
matrices.translate(bounds.getMinX() + xOffset - 0.5f + width / 2f, bounds.getMinY() + yOffset + height / 2f, blitOffset);
matrices.scale(width / 64f, height / 64f, 1f);
PatternDrawingUtil.drawPattern(matrices, 0, 0, this.patterns, this.pathfinderDots, this.strokeOrder, time,
0xff_333030, 0xff_191818, 0xc8_0c0a0c, 0x80_666363);

View file

@ -0,0 +1,76 @@
package at.petrak.hexcasting.fabric.interop.rei;
import com.mojang.blaze3d.systems.RenderSystem;
import me.shedaniel.math.Point;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.gui.Renderer;
import me.shedaniel.rei.api.client.gui.widgets.Widget;
import me.shedaniel.rei.api.client.gui.widgets.Widgets;
import me.shedaniel.rei.api.client.registry.display.DisplayCategory;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class PhialRecipeCategory implements DisplayCategory<PhialRecipeDisplay> {
public static final ResourceLocation UID = modLoc("craft/battery");
private final ResourceLocation OVERLAY = modLoc("textures/gui/phial.png");
private final Renderer icon;
private final Component localizedName;
public PhialRecipeCategory() {
localizedName = new TranslatableComponent("hexcasting.spell." + UID);
icon = new PatternRendererREI(UID, 12, 12).shift(2, 2);
}
@Override
public Renderer getIcon() {
return icon;
}
@Override
public @NotNull Component getTitle() {
return localizedName;
}
@Override
public List<Widget> setupDisplay(PhialRecipeDisplay display, Rectangle bounds) {
List<Widget> widgets = new ArrayList<>();
widgets.add(Widgets.createRecipeBase(bounds));
widgets.add(Widgets.createDrawableWidget(((helper, matrices, mouseX, mouseY, delta) -> {
RenderSystem.enableBlend();
RenderSystem.setShaderTexture(0, OVERLAY);
GuiComponent.blit(matrices, bounds.getMinX(), bounds.getMinY(), 0, 0, getDisplayWidth(display), getDisplayHeight(), 128, 128);
RenderSystem.disableBlend();
})));
widgets.add(Widgets.createSlot(new Point(bounds.getMinX() + 12, bounds.getMinY() + 12)).entries(display.getInputEntries().get(0)).disableBackground());
widgets.add(Widgets.createSlot(new Point(bounds.getMinX() + 47, bounds.getMinY() + 12)).entries(display.getInputEntries().get(1)).disableBackground());
widgets.add(Widgets.createSlot(new Point(bounds.getMinX() + 85, bounds.getMinY() + 12)).entries(display.getOutputEntries().get(0)).disableBackground());
return widgets;
}
@Override
public CategoryIdentifier<? extends PhialRecipeDisplay> getCategoryIdentifier() {
return HexREIPlugin.PHIAL;
}
@Override
public int getDisplayHeight() {
return 40;
}
@Override
public int getDisplayWidth(PhialRecipeDisplay display) {
return 113;
}
}

View file

@ -0,0 +1,49 @@
package at.petrak.hexcasting.fabric.interop.rei;
import at.petrak.hexcasting.api.mod.HexItemTags;
import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.Display;
import me.shedaniel.rei.api.common.entry.EntryIngredient;
import me.shedaniel.rei.api.common.util.EntryIngredients;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Ingredient;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class PhialRecipeDisplay implements Display {
protected EntryIngredient inputs;
protected EntryIngredient bottle;
protected EntryIngredient outputs;
public PhialRecipeDisplay() {
var stacks = PhialRecipeStackBuilder.createStacks();
this.inputs = EntryIngredients.ofItemStacks(stacks.getFirst());
this.bottle = EntryIngredients.ofIngredient(Ingredient.of(HexItemTags.PHIAL_BASE));
this.outputs = EntryIngredients.ofItemStacks(stacks.getSecond());
}
@Override
public @Nonnull List<EntryIngredient> getInputEntries() {
return List.of(this.inputs, this.bottle);
}
@Override
public @Nonnull List<EntryIngredient> getOutputEntries() {
return Collections.singletonList(this.outputs);
}
@Override
public @Nonnull Optional<ResourceLocation> getDisplayLocation() {
return Optional.of(PhialRecipeCategory.UID);
}
@Override
public CategoryIdentifier<?> getCategoryIdentifier() {
return HexREIPlugin.PHIAL;
}
}

View file

@ -0,0 +1,87 @@
package at.petrak.hexcasting.forge.interop.jei;
import at.petrak.hexcasting.common.casting.operators.spells.OpEdifySapling;
import at.petrak.hexcasting.common.lib.HexBlocks;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.drawable.IDrawableStatic;
import mezz.jei.api.helpers.IGuiHelper;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class EdifyRecipeCategory implements IRecipeCategory<OpEdifySapling> {
public static final ResourceLocation UID = modLoc("edify_tree");
private final IDrawableStatic background;
private final IDrawable icon;
private final Component localizedName;
public EdifyRecipeCategory(IGuiHelper guiHelper) {
ResourceLocation location = modLoc("textures/gui/edify_jei.png");
background = guiHelper.drawableBuilder(location, 0, 0, 79, 61).setTextureSize(128, 128).build();
var edify = modLoc("edify");
localizedName = new TranslatableComponent("hexcasting.spell." + edify);
icon = new PatternDrawable(edify, 16, 16).strokeOrder(false);
}
@Override
@OnlyIn(Dist.CLIENT)
public @NotNull Component getTitle() {
return localizedName;
}
@Override
public @NotNull IDrawable getBackground() {
return background;
}
@Override
public @NotNull IDrawable getIcon() {
return icon;
}
@Override
public void setRecipe(@NotNull IRecipeLayoutBuilder builder, @NotNull OpEdifySapling recipe,
@NotNull IFocusGroup focuses) {
builder.addSlot(RecipeIngredientRole.INPUT, 12, 22)
.addIngredients(Ingredient.of(ItemTags.SAPLINGS));
builder.addSlot(RecipeIngredientRole.OUTPUT, 51, 10)
.addItemStack(new ItemStack(HexBlocks.AKASHIC_LEAVES1))
.addItemStack(new ItemStack(HexBlocks.AKASHIC_LEAVES2))
.addItemStack(new ItemStack(HexBlocks.AKASHIC_LEAVES3));
builder.addSlot(RecipeIngredientRole.OUTPUT, 51, 35)
.addItemStack(new ItemStack(HexBlocks.AKASHIC_LOG));
}
@Override
public @NotNull RecipeType<OpEdifySapling> getRecipeType() {
return HexJEIPlugin.EDIFY;
}
@Override
@SuppressWarnings("removal")
public @NotNull ResourceLocation getUid() {
return UID;
}
@Override
@SuppressWarnings("removal")
public @NotNull Class<? extends OpEdifySapling> getRecipeClass() {
return OpEdifySapling.class;
}
}

View file

@ -1,23 +1,26 @@
package at.petrak.hexcasting.forge.interop.jei;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.common.casting.operators.spells.OpEdifySapling;
import at.petrak.hexcasting.common.casting.operators.spells.OpMakeBattery;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.recipe.BrainsweepRecipe;
import at.petrak.hexcasting.common.recipe.HexRecipeSerializers;
import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter;
import mezz.jei.api.recipe.RecipeType;
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.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
@JeiPlugin
@ -27,25 +30,25 @@ public class HexJEIPlugin implements IModPlugin {
public static final RecipeType<BrainsweepRecipe> BRAINSWEEPING =
RecipeType.create(HexAPI.MOD_ID, "brainsweeping", BrainsweepRecipe.class);
// Only one entry, might as well use the op class
public static final RecipeType<OpMakeBattery> PHIAL =
RecipeType.create(HexAPI.MOD_ID, "craft_phial", OpMakeBattery.class);
public static final RecipeType<OpEdifySapling> EDIFY =
RecipeType.create(HexAPI.MOD_ID, "edify_tree", OpEdifySapling.class);
@NotNull
@Override
public ResourceLocation getPluginUid() {
return UID;
}
@Override
public void registerItemSubtypes(@NotNull ISubtypeRegistration registration) {
registration.registerSubtypeInterpreter(HexItems.BATTERY, (itemStack, ctx) -> {
if (!itemStack.hasTag()) {
return IIngredientSubtypeInterpreter.NONE;
}
return String.valueOf(HexItems.BATTERY.getMaxMana(itemStack));
});
}
@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
registration.addRecipeCategories(new BrainsweepRecipeCategory(registration.getJeiHelpers().getGuiHelper()));
var guiHelper = registration.getJeiHelpers().getGuiHelper();
registration.addRecipeCategories(
new BrainsweepRecipeCategory(guiHelper),
new PhialRecipeCategory(guiHelper),
new EdifyRecipeCategory(guiHelper));
}
@Override
@ -55,18 +58,24 @@ public class HexJEIPlugin implements IModPlugin {
registration.addRecipes(BRAINSWEEPING,
level.getRecipeManager().getAllRecipesFor(HexRecipeSerializers.BRAINSWEEP_TYPE));
}
if (PhialRecipeStackBuilder.shouldAddRecipe()) {
registration.addRecipes(PHIAL, List.of(OpMakeBattery.INSTANCE));
}
registration.addRecipes(EDIFY, List.of(OpEdifySapling.INSTANCE));
}
@Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_OAK), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_SPRUCE), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_BIRCH), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_JUNGLE), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_ACACIA), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_DARK_OAK), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_CRIMSON), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_WARPED), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_AKASHIC), BRAINSWEEPING);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_OAK), BRAINSWEEPING, PHIAL, EDIFY);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_SPRUCE), BRAINSWEEPING, PHIAL, EDIFY);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_BIRCH), BRAINSWEEPING, PHIAL, EDIFY);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_JUNGLE), BRAINSWEEPING, PHIAL, EDIFY);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_ACACIA), BRAINSWEEPING, PHIAL, EDIFY);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_DARK_OAK), BRAINSWEEPING, PHIAL, EDIFY);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_CRIMSON), BRAINSWEEPING, PHIAL, EDIFY);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_WARPED), BRAINSWEEPING, PHIAL, EDIFY);
registration.addRecipeCatalyst(new ItemStack(HexItems.WAND_AKASHIC), BRAINSWEEPING, PHIAL, EDIFY);
}
}

View file

@ -19,7 +19,7 @@ public class PatternDrawable implements IDrawable {
private final int width;
private final int height;
private final boolean strokeOrder;
private boolean strokeOrder;
private final List<PatternEntry> patterns;
private final List<Vec2> pathfinderDots;
@ -44,6 +44,11 @@ public class PatternDrawable implements IDrawable {
return height;
}
public PatternDrawable strokeOrder(boolean order) {
strokeOrder = order;
return this;
}
@Override
public void draw(PoseStack poseStack, int xOffset, int yOffset) {
long time = (System.currentTimeMillis() - startTime) / 50;

View file

@ -0,0 +1,87 @@
package at.petrak.hexcasting.forge.interop.jei;
import at.petrak.hexcasting.api.mod.HexItemTags;
import at.petrak.hexcasting.common.casting.operators.spells.OpMakeBattery;
import at.petrak.hexcasting.interop.utils.PhialRecipeStackBuilder;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.drawable.IDrawableStatic;
import mezz.jei.api.helpers.IGuiHelper;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class PhialRecipeCategory implements IRecipeCategory<OpMakeBattery> {
public static final ResourceLocation UID = modLoc("craft_phial");
private final IDrawableStatic background;
private final IDrawable icon;
private final Component localizedName;
public PhialRecipeCategory(IGuiHelper guiHelper) {
ResourceLocation location = modLoc("textures/gui/phial_jei.png");
background = guiHelper.drawableBuilder(location, 0, 0, 113, 40).setTextureSize(128, 128).build();
var craftPhial = modLoc("craft/battery");
localizedName = new TranslatableComponent("hexcasting.spell." + craftPhial);
icon = new PatternDrawable(craftPhial, 12, 12);
}
@Override
@OnlyIn(Dist.CLIENT)
public @NotNull Component getTitle() {
return localizedName;
}
@Override
public @NotNull IDrawable getBackground() {
return background;
}
@Override
public @NotNull IDrawable getIcon() {
return icon;
}
@Override
public void setRecipe(@NotNull IRecipeLayoutBuilder builder, @NotNull OpMakeBattery recipe,
@NotNull IFocusGroup focuses) {
var stacks = PhialRecipeStackBuilder.createStacks();
var inputSlot = builder.addSlot(RecipeIngredientRole.INPUT, 12, 12)
.addItemStacks(stacks.getFirst());
builder.addSlot(RecipeIngredientRole.INPUT, 47, 12)
.addIngredients(Ingredient.of(HexItemTags.PHIAL_BASE));
var outputSlot = builder.addSlot(RecipeIngredientRole.OUTPUT, 85, 12)
.addItemStacks(stacks.getSecond());
builder.createFocusLink(inputSlot, outputSlot);
}
@Override
public @NotNull RecipeType<OpMakeBattery> getRecipeType() {
return HexJEIPlugin.PHIAL;
}
@Override
@SuppressWarnings("removal")
public @NotNull ResourceLocation getUid() {
return UID;
}
@Override
@SuppressWarnings("removal")
public @NotNull Class<? extends OpMakeBattery> getRecipeClass() {
return OpMakeBattery.class;
}
}