From 3b1fab888f31f811563dfa25469eaec9f91308be Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 00:52:40 +0100 Subject: [PATCH] Migrate to TLA. Closes #263 --- .../client/gui/ItemTraitsTooltipRenderer.java | 13 ++ .../compat/emi/MagicalShapedEmiRecipe.java | 49 ----- .../unicopia/compat/emi/Main.java | 149 ------------- .../compat/emi/SpellDuplicatingEmiRecipe.java | 64 ------ .../compat/emi/SpellbookEmiRecipe.java | 131 ------------ .../emi/StructureInteractionEmiRecipe.java | 144 ------------- .../unicopia/compat/emi/TraitEmiStack.java | 120 ----------- .../compat/tla/CloudShapingTlaRecipe.java | 65 ++++++ .../unicopia/compat/tla/Main.java | 16 ++ .../unicopia/compat/tla/RecipeCategory.java | 75 +++++++ .../compat/tla/SpellDuplicatingTlaRecipe.java | 17 ++ .../compat/tla/SpellbookTlaRecipe.java | 162 ++++++++++++++ .../tla/StructureInteractionTlaRecipe.java | 198 ++++++++++++++++++ .../compat/tla/TraitedTlaIngredient.java | 66 ++++++ .../resources/assets/unicopia/lang/en_us.json | 8 +- src/main/resources/fabric.mod.json | 4 +- 16 files changed, 618 insertions(+), 663 deletions(-) delete mode 100644 src/main/java/com/minelittlepony/unicopia/compat/emi/MagicalShapedEmiRecipe.java delete mode 100644 src/main/java/com/minelittlepony/unicopia/compat/emi/Main.java delete mode 100644 src/main/java/com/minelittlepony/unicopia/compat/emi/SpellDuplicatingEmiRecipe.java delete mode 100644 src/main/java/com/minelittlepony/unicopia/compat/emi/SpellbookEmiRecipe.java delete mode 100644 src/main/java/com/minelittlepony/unicopia/compat/emi/StructureInteractionEmiRecipe.java delete mode 100644 src/main/java/com/minelittlepony/unicopia/compat/emi/TraitEmiStack.java create mode 100644 src/main/java/com/minelittlepony/unicopia/compat/tla/CloudShapingTlaRecipe.java create mode 100644 src/main/java/com/minelittlepony/unicopia/compat/tla/Main.java create mode 100644 src/main/java/com/minelittlepony/unicopia/compat/tla/RecipeCategory.java create mode 100644 src/main/java/com/minelittlepony/unicopia/compat/tla/SpellDuplicatingTlaRecipe.java create mode 100644 src/main/java/com/minelittlepony/unicopia/compat/tla/SpellbookTlaRecipe.java create mode 100644 src/main/java/com/minelittlepony/unicopia/compat/tla/StructureInteractionTlaRecipe.java create mode 100644 src/main/java/com/minelittlepony/unicopia/compat/tla/TraitedTlaIngredient.java diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/ItemTraitsTooltipRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/gui/ItemTraitsTooltipRenderer.java index 55a68e70..94a41acb 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/ItemTraitsTooltipRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/ItemTraitsTooltipRenderer.java @@ -102,6 +102,19 @@ public class ItemTraitsTooltipRenderer implements Text, OrderedText, TooltipComp } } + public static void renderStackSingleTrait(Trait trait, float amount, DrawContext context, float x, float y, float weight, float delta, int seed, boolean revealAll) { + float time = MathHelper.cos((MinecraftClient.getInstance().player.age + delta + seed) / 2F) * 0.7F; + + float angle = 0.7F + (time / 30F) % MathHelper.TAU; + float r = 9 + 2 * MathHelper.sin(delta / 20F); + + ItemTraitsTooltipRenderer.renderTraitIcon(trait, amount * weight, context, + x + r * MathHelper.sin(angle), + y + r * MathHelper.cos(angle), + revealAll || isKnown(trait) + ); + } + public static boolean isKnown(Trait trait) { return MinecraftClient.getInstance().player == null || Pony.of(MinecraftClient.getInstance().player).getDiscoveries().isKnown(trait); diff --git a/src/main/java/com/minelittlepony/unicopia/compat/emi/MagicalShapedEmiRecipe.java b/src/main/java/com/minelittlepony/unicopia/compat/emi/MagicalShapedEmiRecipe.java deleted file mode 100644 index 6feb1d68..00000000 --- a/src/main/java/com/minelittlepony/unicopia/compat/emi/MagicalShapedEmiRecipe.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.minelittlepony.unicopia.compat.emi; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; -import com.minelittlepony.unicopia.item.EnchantableItem; - -import dev.emi.emi.api.recipe.EmiCraftingRecipe; -import dev.emi.emi.api.stack.EmiIngredient; -import dev.emi.emi.api.stack.EmiStack; -import dev.emi.emi.recipe.EmiShapedRecipe; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.CraftingRecipe; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.RecipeEntry; - -public class MagicalShapedEmiRecipe extends EmiCraftingRecipe { - public MagicalShapedEmiRecipe(RecipeEntry recipe, CustomisedSpellType spellEffect, ItemStack output) { - super(padIngredients(recipe, spellEffect), EmiStack.of(output), - recipe.id().withPath(p -> p + "/" + spellEffect.type().getId().getPath()), false); - EmiShapedRecipe.setRemainders(input, recipe.value()); - } - - private static List padIngredients(RecipeEntry recipe, CustomisedSpellType spellEffect) { - List list = recipe.value().getIngredients().stream() - .map(ingredient -> remapIngredient(ingredient, spellEffect)) - .collect(Collectors.toList()); - while (list.size() < 9) { - list.add(EmiStack.EMPTY); - } - return list; - } - - private static EmiIngredient remapIngredient(Ingredient ingredient, CustomisedSpellType spellEffect) { - ItemStack[] stacks = ingredient.getMatchingStacks(); - - for (int i = 0; i < stacks.length; i++) { - if (stacks[i].getItem() instanceof EnchantableItem) { - stacks = Arrays.copyOf(stacks, stacks.length); - stacks[i] = EnchantableItem.enchant(stacks[i].copy(), spellEffect.type()); - return EmiIngredient.of(Arrays.stream(stacks).map(EmiStack::of).toList()); - } - } - - return EmiIngredient.of(ingredient); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/emi/Main.java b/src/main/java/com/minelittlepony/unicopia/compat/emi/Main.java deleted file mode 100644 index 165d0080..00000000 --- a/src/main/java/com/minelittlepony/unicopia/compat/emi/Main.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.minelittlepony.unicopia.compat.emi; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Stream; - -import org.jetbrains.annotations.Nullable; - -import com.minelittlepony.unicopia.Unicopia; -import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellDuplicatingRecipe; -import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellEnhancingRecipe; -import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellShapedCraftingRecipe; -import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; -import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; -import com.minelittlepony.unicopia.block.UBlocks; -import com.minelittlepony.unicopia.block.state.Schematic; -import com.minelittlepony.unicopia.item.EnchantableItem; -import com.minelittlepony.unicopia.item.UItems; -import com.minelittlepony.unicopia.item.group.MultiItem; -import com.minelittlepony.unicopia.recipe.TransformCropsRecipe; -import com.minelittlepony.unicopia.recipe.URecipes; - -import dev.emi.emi.api.EmiPlugin; -import dev.emi.emi.api.EmiRegistry; -import dev.emi.emi.api.recipe.EmiRecipeCategory; -import dev.emi.emi.api.render.EmiTexture; -import dev.emi.emi.api.stack.Comparison; -import dev.emi.emi.api.stack.EmiStack; -import dev.emi.emi.recipe.EmiStonecuttingRecipe; -import net.minecraft.block.Blocks; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.recipe.RecipeType; -import net.minecraft.registry.DynamicRegistryManager; -import net.minecraft.registry.Registries; -import net.minecraft.util.Identifier; - -public class Main implements EmiPlugin { - static final EmiStack SPELL_BOOK_STATION = EmiStack.of(UItems.SPELLBOOK); - static final EmiStack CLOUD_SHAPING_STATION = EmiStack.of(UBlocks.SHAPING_BENCH); - static final EmiStack GROWING_STATION = EmiStack.of(Blocks.FARMLAND); - static final EmiStack ALTAR_STATION = EmiStack.of(Blocks.CRYING_OBSIDIAN); - static final EmiRecipeCategory SPELL_BOOK_CATEGORY = new EmiRecipeCategory(Unicopia.id("spellbook"), SPELL_BOOK_STATION, SPELL_BOOK_STATION); - static final EmiRecipeCategory CLOUD_SHAPING_CATEGORY = new EmiRecipeCategory(Unicopia.id("cloud_shaping"), CLOUD_SHAPING_STATION, CLOUD_SHAPING_STATION); - static final EmiRecipeCategory GROWING_CATEGORY = new EmiRecipeCategory(Unicopia.id("growing"), GROWING_STATION, GROWING_STATION); - static final EmiRecipeCategory ALTAR_CATEGORY = new EmiRecipeCategory(Unicopia.id("altar"), ALTAR_STATION, ALTAR_STATION); - - static final Identifier WIDGETS = Unicopia.id("textures/gui/widgets.png"); - static final EmiTexture EMPTY_ARROW = new EmiTexture(WIDGETS, 44, 0, 24, 17); - - @Override - public void register(EmiRegistry registry) { - registry.addCategory(SPELL_BOOK_CATEGORY); - registry.addWorkstation(SPELL_BOOK_CATEGORY, SPELL_BOOK_STATION); - registry.getRecipeManager().listAllOfType(URecipes.SPELLBOOK).forEach(recipe -> { - - if (recipe.value() instanceof SpellDuplicatingRecipe) { - registry.addRecipe(new SpellDuplicatingEmiRecipe(recipe)); - } else if (recipe.value() instanceof SpellEnhancingRecipe enhancingRecipe) { - Trait.all().forEach(trait -> { - registry.addRecipe(new SpellDuplicatingEmiRecipe(recipe) { - private final Identifier id; - - { - id = recipe.id().withPath(p -> p + "/" + trait.getId().getPath()); - input(trait); - this.getOutputs().addAll( - Arrays.stream(enhancingRecipe.getBaseMaterial().getMatchingStacks()) - .map(stack -> EmiStack.of(SpellTraits.of(stack).add(new SpellTraits.Builder().with(trait, 1).build()).applyTo(stack)).comparison(c -> Comparison.DEFAULT_COMPARISON)) - .toList() - ); - } - - @Nullable - @Override - public Identifier getId() { - return id; - } - }); - }); - } else { - registry.addRecipe(new SpellbookEmiRecipe(recipe)); - } - }); - - registry.addCategory(CLOUD_SHAPING_CATEGORY); - registry.addWorkstation(CLOUD_SHAPING_CATEGORY, CLOUD_SHAPING_STATION); - registry.getRecipeManager().listAllOfType(URecipes.CLOUD_SHAPING).forEach(recipe -> { - registry.addRecipe(new EmiStonecuttingRecipe(recipe.value()) { - @Override - public EmiRecipeCategory getCategory() { - return CLOUD_SHAPING_CATEGORY; - } - }); - }); - - Stream.of(UItems.GEMSTONE, UItems.BOTCHED_GEM, UItems.MAGIC_STAFF, UItems.FILLED_JAR).forEach(item -> { - registry.setDefaultComparison(item, comparison -> Comparison.compareComponents()); - }); - - DynamicRegistryManager registries = DynamicRegistryManager.of(Registries.REGISTRIES); - registry.getRecipeManager().listAllOfType(RecipeType.CRAFTING).stream() - .filter(recipe -> recipe.value() instanceof SpellShapedCraftingRecipe) - .forEach(recipe -> { - ItemStack output = recipe.value().getResult(registries); - if (output.getItem() instanceof MultiItem multiItem) { - multiItem.getDefaultStacks().forEach(outputVariation -> { - if (EnchantableItem.isEnchanted(outputVariation)) { - registry.addRecipe(new MagicalShapedEmiRecipe(recipe, EnchantableItem.getSpellEffect(outputVariation), outputVariation)); - } - }); - } - }); - - registry.addCategory(GROWING_CATEGORY); - registry.addWorkstation(GROWING_CATEGORY, GROWING_STATION); - registry.getRecipeManager().listAllOfType(URecipes.GROWING).forEach(recipe -> { - registry.addRecipe(new StructureInteractionEmiRecipe( - GROWING_CATEGORY, - recipe.id(), - new Schematic.Builder() - .fill(0, 0, 0, 6, 0, 6, recipe.value().getCatalystState()) - .set(3, 0, 3, Blocks.FARMLAND.getDefaultState()) - .set(3, 1, 3, recipe.value().getTargetState()) - .build(), - List.of(EmiStack.of(recipe.value().getTarget()), EmiStack.of(recipe.value().getCatalyst(), TransformCropsRecipe.AREA)), - EmiStack.of(recipe.value().getOutput()), - Unicopia.id("textures/gui/ability/grow.png") - )); - }); - - registry.addCategory(ALTAR_CATEGORY); - registry.addWorkstation(ALTAR_CATEGORY, ALTAR_STATION); - registry.addRecipe(new StructureInteractionEmiRecipe( - ALTAR_CATEGORY, - Unicopia.id("altar/spectral_clock"), - Schematic.ALTAR, - List.of( - EmiStack.of(Items.CLOCK), - EmiStack.of(UItems.SPELLBOOK), - EmiStack.of(Blocks.SOUL_SAND), - EmiStack.of(Blocks.LODESTONE), - EmiStack.of(Blocks.OBSIDIAN, 8 * 4 + 8) - ), - EmiStack.of(UItems.SPECTRAL_CLOCK), - Unicopia.id("textures/gui/race/alicorn.png") - )); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/emi/SpellDuplicatingEmiRecipe.java b/src/main/java/com/minelittlepony/unicopia/compat/emi/SpellDuplicatingEmiRecipe.java deleted file mode 100644 index 9e11a431..00000000 --- a/src/main/java/com/minelittlepony/unicopia/compat/emi/SpellDuplicatingEmiRecipe.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.minelittlepony.unicopia.compat.emi; - -import java.util.Arrays; -import java.util.List; - -import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe; - -import dev.emi.emi.EmiPort; -import dev.emi.emi.EmiRenderHelper; -import dev.emi.emi.api.stack.EmiIngredient; -import dev.emi.emi.api.stack.EmiStack; -import dev.emi.emi.api.stack.ListEmiIngredient; -import dev.emi.emi.runtime.EmiDrawContext; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.RecipeEntry; - -public class SpellDuplicatingEmiRecipe extends SpellbookEmiRecipe { - - public SpellDuplicatingEmiRecipe(RecipeEntry recipe) { - super(recipe); - } - - @Override - public void input(ItemStack... stacks) { - getInputs().add(new CyclingRecipeIngredient(Arrays.stream(stacks).map(EmiStack::of).toList(), 1)); - } - - @Override - protected EmiIngredient getOutput() { - return new CyclingRecipeIngredient(getOutputs(), 2); - } - - static class CyclingRecipeIngredient extends ListEmiIngredient { - - private final List ingredients; - private final int maxCount; - - public CyclingRecipeIngredient(List ingredients, long amount) { - super(ingredients, amount); - this.ingredients = ingredients; - this.maxCount = ingredients.size(); - } - - @Override - public void render(DrawContext context, int x, int y, float delta, int flags) { - - if (maxCount < 2 || MinecraftClient.getInstance().player == null) { - super.render(context, x, y, delta, flags); - } else { - int tick = (MinecraftClient.getInstance().player.age / 12) % maxCount; - if ((flags & RENDER_AMOUNT) != 0) { - String count = ""; - if (getAmount() != 1) { - count += getAmount(); - } - EmiRenderHelper.renderAmount(EmiDrawContext.wrap(context), x, y, EmiPort.literal(count)); - } - ingredients.get(tick).render(context, x, y, delta, flags & ~RENDER_AMOUNT); - } - } - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/emi/SpellbookEmiRecipe.java b/src/main/java/com/minelittlepony/unicopia/compat/emi/SpellbookEmiRecipe.java deleted file mode 100644 index 5e6743fd..00000000 --- a/src/main/java/com/minelittlepony/unicopia/compat/emi/SpellbookEmiRecipe.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.minelittlepony.unicopia.compat.emi; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.jetbrains.annotations.Nullable; - -import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe; -import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; -import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen; -import com.minelittlepony.unicopia.container.inventory.HexagonalCraftingGrid; -import com.mojang.blaze3d.systems.RenderSystem; - -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.TextureWidget; -import dev.emi.emi.api.widget.WidgetHolder; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.RecipeEntry; -import net.minecraft.util.Identifier; - -class SpellbookEmiRecipe implements EmiRecipe, SpellbookRecipe.CraftingTreeBuilder { - - private final RecipeEntry recipe; - - private final List inputs = new ArrayList<>(); - private final List outputs = new ArrayList<>(); - - public SpellbookEmiRecipe(RecipeEntry recipe) { - this.recipe = recipe; - recipe.value().buildCraftingTree(this); - } - - @Override - public EmiRecipeCategory getCategory() { - return Main.SPELL_BOOK_CATEGORY; - } - - @Nullable - @Override - public Identifier getId() { - return recipe.id(); - } - - @Override - public List getInputs() { - return inputs; - } - - @Override - public List getOutputs() { - return outputs; - } - - @Override - public int getDisplayWidth() { - return 150; - } - - @Override - public int getDisplayHeight() { - return 75; - } - - @Override - public void addWidgets(WidgetHolder widgets) { - widgets.addTexture(SpellbookScreen.TEXTURE, 0, 0, getDisplayWidth(), getDisplayHeight(), 50, 50, 128, 128, 512, 256); - widgets.addTexture(Main.EMPTY_ARROW, 85, 30); - - List grid = new ArrayList<>(); - List gem = new ArrayList<>(); - HexagonalCraftingGrid.create(-34, -5, 3, grid, gem); - - int currentInput = 1; - - for (int i = 0; i < grid.size(); i++) { - var slot = grid.get(i); - - if (currentInput < inputs.size() && slot.weight() == 1) { - widgets.add(new SlotTexture(slot)); - widgets.addSlot(inputs.get(currentInput++), slot.left(), slot.top()).drawBack(false); - } else if (slot.weight() == 1) { - widgets.add(new SlotTexture(slot)); - widgets.addSlot(slot.left(), slot.top()).drawBack(false); - } - } - widgets.addSlot(inputs.get(0), gem.get(0).left(), gem.get(0).top()).drawBack(false); - widgets.addSlot(getOutput(), 120, 25).large(true).recipeContext(this); - } - - protected EmiIngredient getOutput() { - return EmiIngredient.of(outputs); - } - - @Override - public void input(ItemStack... stacks) { - inputs.add(EmiIngredient.of(Arrays.stream(stacks).map(EmiStack::of).toList())); - } - - @Override - public void input(Trait... traits) { - inputs.add(EmiIngredient.of(Arrays.stream(traits).map(trait -> new TraitEmiStack(trait, 1)).toList())); - } - - @Override - public void input(Trait trait, float value) { - inputs.add(new TraitEmiStack(trait, value)); - } - - @Override - public void result(ItemStack... stack) { - outputs.addAll(Arrays.stream(stack).map(EmiStack::of).toList()); - } - - static class SlotTexture extends TextureWidget { - - public SlotTexture(HexagonalCraftingGrid.Slot slot) { - super(SpellbookScreen.SLOT, slot.left() - 7, slot.top() - 7, 32, 32, 0, 0, 32, 32, 32, 32); - } - - @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - RenderSystem.enableBlend(); - context.drawTexture(texture, x, y, 0, u, v, width, height, textureWidth, textureHeight); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/compat/emi/StructureInteractionEmiRecipe.java b/src/main/java/com/minelittlepony/unicopia/compat/emi/StructureInteractionEmiRecipe.java deleted file mode 100644 index c131aa32..00000000 --- a/src/main/java/com/minelittlepony/unicopia/compat/emi/StructureInteractionEmiRecipe.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.minelittlepony.unicopia.compat.emi; - -import java.util.List; - -import com.minelittlepony.unicopia.block.state.Schematic; -import dev.emi.emi.api.recipe.EmiRecipe; -import dev.emi.emi.api.recipe.EmiRecipeCategory; -import dev.emi.emi.api.render.EmiTexture; -import dev.emi.emi.api.stack.EmiIngredient; -import dev.emi.emi.api.stack.EmiStack; -import dev.emi.emi.api.widget.WidgetHolder; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.DiffuseLighting; -import net.minecraft.client.render.LightmapTextureManager; -import net.minecraft.client.render.OverlayTexture; -import net.minecraft.client.render.VertexConsumerProvider.Immediate; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; -import net.minecraft.util.math.RotationAxis; - -public class StructureInteractionEmiRecipe implements EmiRecipe { - - private final EmiRecipeCategory category; - private final Identifier id; - private final Schematic schematic; - - private final List inputs; - private final List output; - - private final Identifier processIcon; - - private int age; - - public StructureInteractionEmiRecipe(EmiRecipeCategory category, Identifier id, Schematic schematic, List inputs, EmiStack output, Identifier processIcon) { - this.category = category; - this.id = id; - this.schematic = schematic; - this.inputs = inputs; - this.output = List.of(output); - this.processIcon = processIcon; - } - - @Override - public EmiRecipeCategory getCategory() { - return category; - } - - @Override - public Identifier getId() { - return id; - } - - @Override - public List getInputs() { - return inputs; - } - - @Override - public List getOutputs() { - return output; - } - - @Override - public int getDisplayWidth() { - return 130; - } - - @Override - public int getDisplayHeight() { - return schematic.dy() * 8 + 80 + 20 * (inputs.size() - 2); - } - - @Override - public void addWidgets(WidgetHolder widgets) { - int y = schematic.dy() * 8; - int row = 0; - age = 0; - widgets.addDrawable(10, y / 2, 100, 100, this::renderSchematic); - int x = 10; - for (int i = 0; i < inputs.size(); i++) { - if (i > 1) { - x -= 40; - row += 20; - } - if (i > 0) { - widgets.addTexture(EmiTexture.PLUS, x + 3, y + 53 + row); - x += 20; - } - widgets.addSlot(inputs.get(i), x, y + 50 + row).catalyst(i > 0); - x += 20; - } - widgets.addTexture(EmiTexture.EMPTY_ARROW, 73, y + 52); - widgets.addSlot(output.get(0), 100, y + 47).large(true).recipeContext(this); - widgets.addTexture(processIcon, 73, y + 45, 13, 13, 0, 0, 16, 16, 16, 16).tooltipText(List.of(Text.translatable( - Util.createTranslationKey("recipe", category.getId()) + "." + "instruction" - ))); - } - - private void renderSchematic(DrawContext context, int mouseX, int mouseY, float delta) { - if (schematic.volume() == 0) { - return; - } - MatrixStack matrices = context.getMatrices(); - Immediate immediate = context.getVertexConsumers(); - - MinecraftClient client = MinecraftClient.getInstance(); - - matrices.push(); - float minSize = (Math.max(schematic.dz(), Math.max(schematic.dx(), schematic.dy())) + 1) * 16; - float scale = 60 / minSize; - matrices.scale(scale, scale, 1); - matrices.translate(95, 40, 100); - matrices.scale(16, -16, 16); - - matrices.peek().getNormalMatrix().scale(1, -1, 1); - matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(20)); - matrices.peek().getPositionMatrix().rotate(RotationAxis.POSITIVE_Y.rotationDegrees(40)); - matrices.translate( - (-schematic.dx() - 1) / 2F, - (-schematic.dy() - 1) / 2F, - (-schematic.dz() - 1) / 2F - ); - DiffuseLighting.disableGuiDepthLighting(); - - age++; - - for (var entry : schematic.states()) { - int x = entry.x() - schematic.dx() / 2; - int z = entry.z() - schematic.dz() / 2; - int distance = x * x + z * z; - if (age >= distance * 2) { - matrices.push(); - matrices.translate(entry.x(), entry.y(), entry.z()); - client.getBlockRenderManager().renderBlockAsEntity(entry.state(), matrices, immediate, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV); - matrices.pop(); - } - } - - matrices.pop(); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/emi/TraitEmiStack.java b/src/main/java/com/minelittlepony/unicopia/compat/emi/TraitEmiStack.java deleted file mode 100644 index c554b54e..00000000 --- a/src/main/java/com/minelittlepony/unicopia/compat/emi/TraitEmiStack.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.minelittlepony.unicopia.compat.emi; - -import java.util.List; - -import org.apache.commons.compress.utils.Lists; -import com.minelittlepony.common.client.gui.Tooltip; -import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; -import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; -import com.minelittlepony.unicopia.client.gui.ItemTraitsTooltipRenderer; - -import dev.emi.emi.api.render.EmiRender; -import dev.emi.emi.api.stack.Comparison; -import dev.emi.emi.api.stack.EmiStack; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.tooltip.TooltipComponent; -import net.minecraft.component.ComponentChanges; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.MathHelper; - -public class TraitEmiStack extends EmiStack { - - private final Trait trait; - private final float amount; - private final SpellTraits traits; - - public TraitEmiStack(Trait trait, float amount) { - this.trait = trait; - this.amount = amount; - traits = new SpellTraits.Builder().with(trait, amount).build(); - } - - @Override - public boolean isEmpty() { - return amount == 0; - } - - @Override - public ComponentChanges getComponentChanges() { - return ComponentChanges.EMPTY; - } - - @Override - public Object getKey() { - return trait; - } - - @Override - public Identifier getId() { - return trait.getId(); - } - - @Override - public List getTooltipText() { - return trait.getTooltipLines(); - } - - @Override - public List getTooltip() { - List list = Lists.newArrayList(); - if (!isEmpty()) { - for (Text line : Tooltip.of(trait.getTooltip(), 200).getLines()) { - list.add(TooltipComponent.of(line.asOrderedText())); - } - list.addAll(super.getTooltip()); - } - return list; - } - - @Override - public Text getName() { - return trait.getName(); - } - - @Override - public void render(DrawContext context, int x, int y, float delta, int flags) { - if ((flags & RENDER_ICON) != 0) { - List knownItems = trait.getItems(); - if (knownItems.isEmpty() || MinecraftClient.getInstance().player == null) { - ItemTraitsTooltipRenderer.renderTraitIcon(trait, amount, context, x, y, true); - } else { - int tick = (MinecraftClient.getInstance().player.age / 12) % knownItems.size(); - ItemStack stack = knownItems.get(tick).getDefaultStack(); - EmiStack.of(stack).render(context, x, y, delta, flags); - ItemTraitsTooltipRenderer.renderStackTraits(traits, context, x, y, 1, delta, 0, true); - } - } - - if ((flags & RENDER_REMAINDER) != 0) { - EmiRender.renderRemainderIcon(this, context, x, y); - } - } - - @Override - public EmiStack copy() { - return new TraitEmiStack(trait, amount); - } - - @Override - public boolean isEqual(EmiStack stack) { - return super.isEqual(stack) && equalTo(stack); - } - - @Override - public boolean isEqual(EmiStack stack, Comparison comparison) { - return super.isEqual(stack, comparison) && equalTo(stack); - } - - @Override - public boolean equals(Object obj) { - return super.equals(obj) && obj instanceof EmiStack s && equalTo(s); - } - - private boolean equalTo(EmiStack stack) { - return stack instanceof TraitEmiStack t && t.trait == trait && MathHelper.approximatelyEquals(t.amount, amount); - } -} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/tla/CloudShapingTlaRecipe.java b/src/main/java/com/minelittlepony/unicopia/compat/tla/CloudShapingTlaRecipe.java new file mode 100644 index 00000000..4941ad94 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/compat/tla/CloudShapingTlaRecipe.java @@ -0,0 +1,65 @@ +package com.minelittlepony.unicopia.compat.tla; + +import java.util.List; + +import com.minelittlepony.unicopia.recipe.URecipes; + +import io.github.mattidragon.tlaapi.api.gui.GuiBuilder; +import io.github.mattidragon.tlaapi.api.plugin.PluginContext; +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 net.minecraft.client.MinecraftClient; +import net.minecraft.recipe.RecipeEntry; +import net.minecraft.recipe.StonecuttingRecipe; +import net.minecraft.util.Identifier; + +public class CloudShapingTlaRecipe implements TlaRecipe { + private final Identifier id; + private final RecipeCategory category; + private final TlaIngredient input; + private final TlaStack output; + + static void generate(RecipeCategory category, PluginContext context) { + context.addRecipeGenerator(URecipes.CLOUD_SHAPING, recipe -> new CloudShapingTlaRecipe(category, recipe)); + } + + public CloudShapingTlaRecipe(RecipeCategory category, RecipeEntry recipe) { + this.id = recipe.id(); + this.category = category; + input = TlaIngredient.ofIngredient(recipe.value().getIngredients().get(0)); + output = TlaStack.of(recipe.value().getResult(MinecraftClient.getInstance().world.getRegistryManager())); + } + + @Override + public RecipeCategory getCategory() { + return category; + } + + @Override + public Identifier getId() { + return id; + } + + @Override + public List getInputs() { + return List.of(input); + } + + @Override + public List getOutputs() { + return List.of(output); + } + + @Override + public List getCatalysts() { + return List.of(); + } + + @Override + public void buildGui(GuiBuilder builder) { + builder.addArrow(26, 1, false); + builder.addSlot(input, 0, 0).markInput(); + builder.addSlot(output, 58, 0).markOutput(); + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/compat/tla/Main.java b/src/main/java/com/minelittlepony/unicopia/compat/tla/Main.java new file mode 100644 index 00000000..ed638e3e --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/compat/tla/Main.java @@ -0,0 +1,16 @@ +package com.minelittlepony.unicopia.compat.tla; + +import com.minelittlepony.unicopia.item.UItems; +import io.github.mattidragon.tlaapi.api.plugin.PluginContext; +import io.github.mattidragon.tlaapi.api.plugin.TlaApiPlugin; +import io.github.mattidragon.tlaapi.api.recipe.TlaStackComparison; + +public class Main implements TlaApiPlugin { + @Override + public void register(PluginContext registry) { + RecipeCategory.bootstrap(registry); + registry.getItemComparisons().register(TlaStackComparison.compareComponents(), + UItems.GEMSTONE, UItems.BOTCHED_GEM, UItems.MAGIC_STAFF, UItems.FILLED_JAR + ); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/tla/RecipeCategory.java b/src/main/java/com/minelittlepony/unicopia/compat/tla/RecipeCategory.java new file mode 100644 index 00000000..f2d15876 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/compat/tla/RecipeCategory.java @@ -0,0 +1,75 @@ +package com.minelittlepony.unicopia.compat.tla; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.block.UBlocks; +import com.minelittlepony.unicopia.item.UItems; +import io.github.mattidragon.tlaapi.api.plugin.PluginContext; +import io.github.mattidragon.tlaapi.api.recipe.CategoryIcon; +import io.github.mattidragon.tlaapi.api.recipe.TlaCategory; +import io.github.mattidragon.tlaapi.api.recipe.TlaIngredient; +import io.github.mattidragon.tlaapi.api.recipe.TlaStack; +import net.minecraft.block.Blocks; +import net.minecraft.item.ItemConvertible; +import net.minecraft.util.Identifier; + +public record RecipeCategory(Identifier id, CategoryIcon icon, TlaIngredient stations, int width, int height) implements TlaCategory { + static final Map> REGISTRY = new HashMap<>(); + + static final RecipeCategory SPELL_BOOK = register("spellbook", UItems.SPELLBOOK, 150, 75, SpellbookTlaRecipe::generate); + static final RecipeCategory CLOUD_SHAPING = register("cloud_shaping", UBlocks.SHAPING_BENCH, 76, 18, CloudShapingTlaRecipe::generate); + static final RecipeCategory GROWING = register("growing", Blocks.FARMLAND, 130, 85, StructureInteractionTlaRecipe::generateFarmingRecipes); + static final RecipeCategory ALTAR = register("altar", Blocks.CRYING_OBSIDIAN, 130, 160, StructureInteractionTlaRecipe::generateAltarRecipes); + + static RecipeCategory register(String name, ItemConvertible item, int width, int height, @Nullable BiConsumer recipeConstructor) { + return register(new RecipeCategory(Unicopia.id(name), CategoryIcon.item(item), TlaStack.of(item).asIngredient(), width, height), recipeConstructor); + } + + static RecipeCategory register(RecipeCategory category, @Nullable BiConsumer recipeConstructor) { + REGISTRY.put(category, recipeConstructor); + return category; + } + + static void bootstrap(PluginContext registry) { + REGISTRY.forEach((category, recipeConstructor) -> { + registry.addCategory(category); + registry.addWorkstation(category, category.stations()); + try { + if (recipeConstructor != null) { + recipeConstructor.accept(category, registry); + } + } catch (Throwable t) { + Unicopia.LOGGER.fatal("Error occured whilst registering recipes for category " + category.getId(), t); + } + }); + } + + @Override + public Identifier getId() { + return id; + } + + @Override + public int getDisplayHeight() { + return height; + } + + @Override + public int getDisplayWidth() { + return width; + } + + @Override + public CategoryIcon getIcon() { + return icon; + } + + @Override + public CategoryIcon getSimpleIcon() { + return icon; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/tla/SpellDuplicatingTlaRecipe.java b/src/main/java/com/minelittlepony/unicopia/compat/tla/SpellDuplicatingTlaRecipe.java new file mode 100644 index 00000000..da005724 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/compat/tla/SpellDuplicatingTlaRecipe.java @@ -0,0 +1,17 @@ +package com.minelittlepony.unicopia.compat.tla; + +import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe; + +import io.github.mattidragon.tlaapi.api.recipe.TlaIngredient; +import net.minecraft.recipe.RecipeEntry; + +class SpellDuplicatingTlaRecipe extends SpellbookTlaRecipe { + public SpellDuplicatingTlaRecipe(RecipeEntry recipe) { + super(recipe); + } + + @Override + protected TlaIngredient getOutput() { + return super.getOutput().withAmount(2); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/tla/SpellbookTlaRecipe.java b/src/main/java/com/minelittlepony/unicopia/compat/tla/SpellbookTlaRecipe.java new file mode 100644 index 00000000..03445232 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/compat/tla/SpellbookTlaRecipe.java @@ -0,0 +1,162 @@ +package com.minelittlepony.unicopia.compat.tla; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.jetbrains.annotations.Nullable; + +import com.google.common.base.Suppliers; +import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellDuplicatingRecipe; +import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellEnhancingRecipe; +import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe; +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; +import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; +import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen; +import com.minelittlepony.unicopia.container.inventory.HexagonalCraftingGrid; +import com.minelittlepony.unicopia.recipe.URecipes; +import io.github.mattidragon.tlaapi.api.gui.GuiBuilder; +import io.github.mattidragon.tlaapi.api.gui.TextureConfig; +import io.github.mattidragon.tlaapi.api.gui.TlaBounds; +import io.github.mattidragon.tlaapi.api.plugin.PluginContext; +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 net.minecraft.item.ItemStack; +import net.minecraft.recipe.RecipeEntry; +import net.minecraft.util.Identifier; + +class SpellbookTlaRecipe implements TlaRecipe, SpellbookRecipe.CraftingTreeBuilder { + static final Identifier WIDGETS = Unicopia.id("textures/gui/widgets.png"); + static final TextureConfig EMPTY_ARROW = TextureConfig.builder().texture(WIDGETS).uv(44, 0).size(24, 17).build(); + + private final RecipeEntry recipe; + + protected final List inputs = new ArrayList<>(); + private final List outputs = new ArrayList<>(); + + private final Supplier> ingredients; + + static void generate(RecipeCategory category, PluginContext context) { + context.addGenerator(client -> client.world.getRecipeManager().listAllOfType(URecipes.SPELLBOOK).stream().flatMap(recipe -> { + if (recipe.value() instanceof SpellDuplicatingRecipe) { + return Stream.of(new SpellDuplicatingTlaRecipe(recipe)); + } + + if (recipe.value() instanceof SpellEnhancingRecipe enhancingRecipe) { + return Trait.all().stream().map(trait -> { + return new SpellDuplicatingTlaRecipe(recipe) { + private final Identifier id = recipe.id().withPath(p -> p + "/" + trait.getId().getPath()); + + { + input(trait); + getOutputs().addAll( + Arrays.stream(enhancingRecipe.getBaseMaterial().getMatchingStacks()) + .map(stack -> TlaStack.of(SpellTraits.of(stack).add(new SpellTraits.Builder().with(trait, 1).build()).applyTo(stack))) + .toList() + ); + } + + @Nullable + @Override + public Identifier getId() { + return id; + } + }; + }); + } + + return Stream.of((TlaRecipe)new SpellbookTlaRecipe(recipe)); + }).toList()); + } + + public SpellbookTlaRecipe(RecipeEntry recipe) { + this.recipe = recipe; + this.ingredients = Suppliers.memoize(() -> inputs.stream().map(TraitedTlaIngredient::ingredient).toList()); + recipe.value().buildCraftingTree(this); + } + + @Override + public RecipeCategory getCategory() { + return RecipeCategory.SPELL_BOOK; + } + + @Nullable + @Override + public Identifier getId() { + return recipe.id(); + } + + @Override + public List getInputs() { + return ingredients.get(); + } + + @Override + public List getOutputs() { + return outputs; + } + + @Override + public List getCatalysts() { + return List.of(); + } + + @Override + public void buildGui(GuiBuilder builder) { + TlaBounds bounds = builder.getBounds(); + builder.addTexture(TextureConfig.builder().texture(SpellbookScreen.TEXTURE) + .size(bounds.width(), bounds.height()) + .uv(50, 50) + .regionSize(128, 128) + .textureSize(512, 256) + .build(), 0, 0); + builder.addTexture(EMPTY_ARROW, 85, 30); + + List grid = new ArrayList<>(); + List gem = new ArrayList<>(); + HexagonalCraftingGrid.create(-34, -5, 3, grid, gem); + + int currentInput = 1; + + for (int i = 0; i < grid.size(); i++) { + var slot = grid.get(i); + + if (currentInput < inputs.size() && slot.weight() == 1) { + inputs.get(currentInput++).buildGui(slot, builder); + } else if (slot.weight() == 1) { + inputs.get(0).buildGui(TlaIngredient.EMPTY, slot, builder); + } + } + + inputs.get(0).buildGui(gem.get(0), builder); + builder.addSlot(getOutput(), 120, 25).makeLarge().markOutput(); + } + + protected TlaIngredient getOutput() { + return TlaIngredient.ofStacks(outputs); + } + + @Override + public void input(ItemStack... stacks) { + inputs.add(TraitedTlaIngredient.of(TlaIngredient.ofStacks(Arrays.stream(stacks).map(TlaStack::of).toList()))); + } + + @Override + public void input(Trait... traits) { + inputs.add(TraitedTlaIngredient.of(List.of(traits), 1)); + } + + @Override + public void input(Trait trait, float value) { + inputs.add(TraitedTlaIngredient.of(trait, value)); + } + + @Override + public void result(ItemStack... stack) { + outputs.addAll(Arrays.stream(stack).map(TlaStack::of).toList()); + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/compat/tla/StructureInteractionTlaRecipe.java b/src/main/java/com/minelittlepony/unicopia/compat/tla/StructureInteractionTlaRecipe.java new file mode 100644 index 00000000..634543a4 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/compat/tla/StructureInteractionTlaRecipe.java @@ -0,0 +1,198 @@ +package com.minelittlepony.unicopia.compat.tla; + +import java.util.List; + +import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.block.state.Schematic; +import com.minelittlepony.unicopia.item.UItems; +import com.minelittlepony.unicopia.recipe.TransformCropsRecipe; +import com.minelittlepony.unicopia.recipe.URecipes; + +import io.github.mattidragon.tlaapi.api.gui.GuiBuilder; +import io.github.mattidragon.tlaapi.api.gui.TextureConfig; +import io.github.mattidragon.tlaapi.api.plugin.PluginContext; +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 net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.DiffuseLighting; +import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.VertexConsumerProvider.Immediate; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.Items; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.Util; +import net.minecraft.util.math.RotationAxis; + +public class StructureInteractionTlaRecipe implements TlaRecipe { + static final TextureConfig PLUS = TextureConfig.builder().texture(Identifier.of("emi", "textures/gui/widgets.png")).size(13, 13).uv(82, 0).build(); + + private final RecipeCategory category; + private final Identifier id; + private final Schematic schematic; + + private final List allInputs; + private final List inputs; + private final List catalysts; + private final List output; + + private final TextureConfig processIcon; + + private int age; + + static void generateFarmingRecipes(RecipeCategory category, PluginContext context) { + context.addRecipeGenerator(URecipes.GROWING, recipe -> { + return new StructureInteractionTlaRecipe( + category, + recipe.id(), + new Schematic.Builder() + .fill(0, 0, 0, 6, 0, 6, recipe.value().getCatalystState()) + .set(3, 0, 3, Blocks.FARMLAND.getDefaultState()) + .set(3, 1, 3, recipe.value().getTargetState()) + .build(), + List.of( + TlaStack.of(recipe.value().getTarget()).asIngredient(), + TlaStack.of(ItemVariant.of(recipe.value().getCatalyst()), TransformCropsRecipe.AREA).asIngredient() + ), + TlaStack.of(recipe.value().getOutput()), + Unicopia.id("textures/gui/ability/grow.png") + ); + }); + } + + static void generateAltarRecipes(RecipeCategory category, PluginContext context) { + context.addGenerator(client -> List.of(new StructureInteractionTlaRecipe( + category, + Unicopia.id("altar/spectral_clock"), + Schematic.ALTAR, + List.of( + TlaStack.of(Items.CLOCK).asIngredient(), + TlaStack.of(UItems.SPELLBOOK).asIngredient(), + TlaStack.of(Blocks.SOUL_SAND).asIngredient(), + TlaStack.of(Blocks.LODESTONE).asIngredient(), + TlaStack.of(Blocks.OBSIDIAN, 8 * 4 + 8).asIngredient() + ), + TlaStack.of(UItems.SPECTRAL_CLOCK), + Unicopia.id("textures/gui/race/alicorn.png") + ))); + } + + public StructureInteractionTlaRecipe(RecipeCategory category, Identifier id, Schematic schematic, List inputs, TlaStack output, Identifier processIcon) { + this.category = category; + this.id = id; + this.schematic = schematic; + this.allInputs = inputs; + this.inputs = inputs.stream().limit(1).toList(); + this.catalysts = inputs.stream().skip(1).toList(); + this.output = List.of(output); + this.processIcon = TextureConfig.builder().texture(processIcon).size(13, 13).regionSize(16, 16).textureSize(16, 16).build(); + } + + @Override + public RecipeCategory getCategory() { + return category; + } + + @Override + public Identifier getId() { + return id; + } + + @Override + public List getInputs() { + return inputs; + } + + @Override + public List getOutputs() { + return output; + } + + + @Override + public List getCatalysts() { + return catalysts; + } + + /*@Override + public int getDisplayHeight() { + return schematic.dy() * 8 + 80 + 20 * (inputs.size() - 2); + }*/ + + @Override + public void buildGui(GuiBuilder widgets) { + int y = schematic.dy() * 8; + int row = 0; + age = 0; + widgets.addCustomWidget(10, y / 2, 100, 100, this::renderSchematic); + int x = 10; + for (int i = 0; i < allInputs.size(); i++) { + if (i > 1) { + x -= 40; + row += 20; + } + if (i > 0) { + widgets.addTexture(PLUS, x + 3, y + 53 + row); + x += 20; + } + var slot = widgets.addSlot(allInputs.get(i), x, y + 50 + row); + if (i > 0) { + slot.markCatalyst(); + } + x += 20; + } + widgets.addArrow(73, y + 52, false); + widgets.addSlot(output.get(0), 100, y + 47).makeLarge().markOutput(); + widgets.addTexture(processIcon, 73, y + 45).addTooltip(List.of(Text.translatable( + Util.createTranslationKey("recipe", category.getId()) + "." + "instruction" + ))); + } + + private void renderSchematic(DrawContext context, int mouseX, int mouseY, float delta) { + if (schematic.volume() == 0) { + return; + } + MatrixStack matrices = context.getMatrices(); + Immediate immediate = context.getVertexConsumers(); + + MinecraftClient client = MinecraftClient.getInstance(); + + matrices.push(); + float minSize = (Math.max(schematic.dz(), Math.max(schematic.dx(), schematic.dy())) + 1) * 16; + float scale = 60 / minSize; + matrices.scale(scale, scale, 1); + matrices.translate(95, 40, 100); + matrices.scale(16, -16, 16); + + matrices.peek().getNormalMatrix().scale(1, -1, 1); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(20)); + matrices.peek().getPositionMatrix().rotate(RotationAxis.POSITIVE_Y.rotationDegrees(40)); + matrices.translate( + (-schematic.dx() - 1) / 2F, + (-schematic.dy() - 1) / 2F, + (-schematic.dz() - 1) / 2F + ); + DiffuseLighting.disableGuiDepthLighting(); + + age++; + + for (var entry : schematic.states()) { + int x = entry.x() - schematic.dx() / 2; + int z = entry.z() - schematic.dz() / 2; + int distance = x * x + z * z; + if (age >= distance * 2) { + matrices.push(); + matrices.translate(entry.x(), entry.y(), entry.z()); + client.getBlockRenderManager().renderBlockAsEntity(entry.state(), matrices, immediate, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV); + matrices.pop(); + } + } + + matrices.pop(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/compat/tla/TraitedTlaIngredient.java b/src/main/java/com/minelittlepony/unicopia/compat/tla/TraitedTlaIngredient.java new file mode 100644 index 00000000..e44eb9d8 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/compat/tla/TraitedTlaIngredient.java @@ -0,0 +1,66 @@ +package com.minelittlepony.unicopia.compat.tla; + +import java.util.List; +import java.util.Optional; + +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; +import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; +import com.minelittlepony.unicopia.client.gui.ItemTraitsTooltipRenderer; +import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen; +import com.minelittlepony.unicopia.container.inventory.HexagonalCraftingGrid; +import com.mojang.blaze3d.systems.RenderSystem; + +import io.github.mattidragon.tlaapi.api.gui.GuiBuilder; +import io.github.mattidragon.tlaapi.api.gui.TlaBounds; +import io.github.mattidragon.tlaapi.api.recipe.TlaIngredient; +import io.github.mattidragon.tlaapi.impl.SimpleCustomTlaWidget; +import net.minecraft.client.MinecraftClient; + +public record TraitedTlaIngredient(Optional trait, TlaIngredient ingredient) { + + public static TraitedTlaIngredient of(Trait trait, float amount) { + return of(List.of(trait), amount); + } + + public static TraitedTlaIngredient of(List traits, float amount) { + return new TraitedTlaIngredient(Optional.of(new TraitEntry(traits, amount)), + TlaIngredient.ofItems(traits.stream().flatMap(SpellTraits::getItems).distinct().toList()) + ); + } + + public static TraitedTlaIngredient of(TlaIngredient ingredient) { + return new TraitedTlaIngredient(Optional.empty(), ingredient); + } + + public void buildGui(HexagonalCraftingGrid.Slot slot, GuiBuilder builder) { + buildGui(ingredient(), slot, builder); + } + + public void buildGui(TlaIngredient ingredientOverride, HexagonalCraftingGrid.Slot slot, GuiBuilder builder) { + builder.addCustomWidget(new SlotTexture(slot)); + builder.addSlot(ingredientOverride, slot.left(), slot.top()).disableBackground(); + trait.ifPresent(traitEntry -> { + builder.addCustomWidget(slot.left(), slot.top(), 16, 16, (context, mouseX, mouseY, delta) -> { + int tick = (MinecraftClient.getInstance().player.age / 12) % traitEntry.traits().size(); + Trait currentDisplayedTrait = traitEntry.traits().get(tick); + if (currentDisplayedTrait.getItems().isEmpty() || MinecraftClient.getInstance().player == null) { + ItemTraitsTooltipRenderer.renderTraitIcon(currentDisplayedTrait, traitEntry.amount(), context, 0, 0, true); + } else { + ItemTraitsTooltipRenderer.renderStackSingleTrait(currentDisplayedTrait, traitEntry.amount(), context, 0, 0, 1, delta, 0, true); + } + }); + }); + } + + record TraitEntry(List traits, float amount) { } + + static class SlotTexture extends SimpleCustomTlaWidget { + public SlotTexture(HexagonalCraftingGrid.Slot slot) { + super((context, mouseX, mouseY, delta) -> { + RenderSystem.enableBlend(); + context.drawTexture(SpellbookScreen.SLOT, 0, 0, 0, 0, 0, 32, 32, 32, 32); + RenderSystem.disableBlend(); + }, new TlaBounds(slot.left() - 7, slot.top() - 7, 32, 32)); + } + } +} diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index dfd7f4cf..ba03cdd8 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -46,10 +46,10 @@ "item.unicopia.spellbook": "Spellbook", "item.unicopia.spectral_clock": "Spectral Clock", - "emi.category.unicopia.spellbook": "Spellbook", - "emi.category.unicopia.cloud_shaping": "Shaping", - "emi.category.unicopia.growing": "Growing", - "emi.category.unicopia.altar": "Dark Ritual", + "tla.category.unicopia.spellbook": "Spellbook", + "tla.category.unicopia.cloud_shaping": "Shaping", + "tla.category.unicopia.growing": "Growing", + "tla.category.unicopia.altar": "Dark Ritual", "recipe.unicopia.altar.instruction": "Cast item into flames", "recipe.unicopia.growing.instruction": "Focus Earth Pony Magic", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index a372fd58..b02647ce 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -30,8 +30,8 @@ "modmenu": [ "com.minelittlepony.unicopia.modmenu.UMenuFactory" ], - "emi": [ - "com.minelittlepony.unicopia.compat.emi.Main" + "tla-api": [ + "com.minelittlepony.unicopia.compat.tla.Main" ], "minelittlepony": [ "com.minelittlepony.unicopia.client.minelittlepony.Main"