mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 13:37:58 +01:00
Added EMI support
This commit is contained in:
parent
45d6e2c1f8
commit
188530c3ef
16 changed files with 607 additions and 34 deletions
|
@ -63,6 +63,9 @@ dependencies {
|
|||
|
||||
modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}"
|
||||
modCompileOnly "dev.emi:trinkets:${project.trinkets_version}"
|
||||
|
||||
//modCompileOnly "dev.emi:emi:${project.emi_version}:api"
|
||||
modCompileOnly "dev.emi:emi:${project.emi_version}"
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
|
|
@ -26,3 +26,4 @@ org.gradle.daemon=false
|
|||
kirin_version=1.13.2
|
||||
reach_attributes_version=2.3.1
|
||||
trinkets_version=3.5.0
|
||||
emi_version=0.7.3+1.19.3
|
||||
|
|
|
@ -24,9 +24,13 @@ public class SpellEnhancingRecipe implements SpellbookRecipe {
|
|||
this.material = material;
|
||||
}
|
||||
|
||||
public IngredientWithSpell getBaseMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildCraftingTree(CraftingTreeBuilder builder) {
|
||||
|
||||
builder.input(material.getMatchingStacks());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,11 +32,15 @@ public interface SpellbookRecipe extends Recipe<SpellbookInventory> {
|
|||
int getPriority();
|
||||
|
||||
interface CraftingTreeBuilder {
|
||||
void input(ItemStack...stack);
|
||||
void input(ItemStack...stacks);
|
||||
|
||||
void input(Trait...traits);
|
||||
|
||||
void input(Trait trait, float value);
|
||||
|
||||
void mystery(ItemStack...stacks);
|
||||
default void mystery(ItemStack...stacks) {
|
||||
input(stacks);
|
||||
}
|
||||
|
||||
void result(ItemStack...stack);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.trait;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
|
@ -39,9 +40,21 @@ public final class SpellTraits implements Iterable<Map.Entry<Trait, Float>> {
|
|||
public static final SpellTraits EMPTY = new SpellTraits(Map.of());
|
||||
|
||||
private static Map<Identifier, SpellTraits> REGISTRY = new HashMap<>();
|
||||
static final Map<Trait, List<Item>> ITEMS = new HashMap<>();
|
||||
|
||||
public static void load(Map<Identifier, SpellTraits> newRegistry) {
|
||||
REGISTRY = new HashMap<>(newRegistry);
|
||||
ITEMS.clear();
|
||||
REGISTRY.forEach((itemId, traits) -> {
|
||||
Registries.ITEM.getOrEmpty(itemId).ifPresent(item -> {
|
||||
traits.forEach(entry -> {
|
||||
List<Item> items = ITEMS.computeIfAbsent(entry.getKey(), k -> new ArrayList<>());
|
||||
if (!items.contains(item)) {
|
||||
items.add(item);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static Map<Identifier, SpellTraits> all() {
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.stream.Stream;
|
|||
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
|
@ -63,6 +64,7 @@ public enum Trait {
|
|||
|
||||
private final Text tooltip;
|
||||
private final Text obfuscatedTooltip;
|
||||
private final List<Text> tooltipLines;
|
||||
|
||||
Trait(TraitGroup group) {
|
||||
this.id = Unicopia.id(name().toLowerCase(Locale.ROOT));
|
||||
|
@ -75,14 +77,17 @@ public enum Trait {
|
|||
? Formatting.RED
|
||||
: Formatting.WHITE;
|
||||
|
||||
MutableText tooltipText = Text.translatable("gui.unicopia.trait.label",
|
||||
Text.translatable("trait." + getId().getNamespace() + "." + getId().getPath() + ".name")
|
||||
).formatted(Formatting.YELLOW)
|
||||
.append(Text.translatable("gui.unicopia.trait.group", getGroup().name().toLowerCase(Locale.ROOT)).formatted(Formatting.ITALIC, Formatting.GRAY))
|
||||
.append(Text.literal("\n\n").formatted(Formatting.WHITE)
|
||||
.append(Text.translatable("trait." + getId().getNamespace() + "." + getId().getPath() + ".description").formatted(Formatting.GRAY))
|
||||
.append("\n")
|
||||
.append(Text.translatable("gui.unicopia.trait.corruption", ItemStack.MODIFIER_FORMAT.format(getGroup().getCorruption())).formatted(Formatting.ITALIC, corruptionColor)));
|
||||
tooltipLines = List.of(
|
||||
Text.translatable("gui.unicopia.trait.group", getGroup().name().toLowerCase(Locale.ROOT)).formatted(Formatting.ITALIC, Formatting.GRAY),
|
||||
Text.empty(),
|
||||
Text.empty(),
|
||||
Text.translatable("trait." + getId().getNamespace() + "." + getId().getPath() + ".description").formatted(Formatting.GRAY),
|
||||
Text.empty(),
|
||||
Text.translatable("gui.unicopia.trait.corruption", ItemStack.MODIFIER_FORMAT.format(getGroup().getCorruption())).formatted(Formatting.ITALIC, corruptionColor)
|
||||
);
|
||||
|
||||
MutableText tooltipText = getName().copy();
|
||||
tooltipLines.forEach(line -> tooltipText.append(line).append("\n"));
|
||||
this.tooltip = tooltipText;
|
||||
this.obfuscatedTooltip = tooltipText.copy().formatted(Formatting.OBFUSCATED);
|
||||
|
||||
|
@ -100,6 +105,16 @@ public enum Trait {
|
|||
return sprite;
|
||||
}
|
||||
|
||||
public Text getName() {
|
||||
return Text.translatable("gui.unicopia.trait.label",
|
||||
Text.translatable("trait." + getId().getNamespace() + "." + getId().getPath() + ".name")
|
||||
).formatted(Formatting.YELLOW);
|
||||
}
|
||||
|
||||
public List<Text> getTooltipLines() {
|
||||
return tooltipLines;
|
||||
}
|
||||
|
||||
public Text getTooltip() {
|
||||
return tooltip;
|
||||
}
|
||||
|
@ -108,6 +123,10 @@ public enum Trait {
|
|||
return obfuscatedTooltip;
|
||||
}
|
||||
|
||||
public List<Item> getItems() {
|
||||
return SpellTraits.ITEMS.getOrDefault(this, List.of());
|
||||
}
|
||||
|
||||
public static Collection<Trait> all() {
|
||||
return IDS.values();
|
||||
}
|
||||
|
|
|
@ -82,10 +82,10 @@ public class ItemTraitsTooltipRenderer implements Text, OrderedText, TooltipComp
|
|||
}
|
||||
|
||||
public static void renderStackTraits(ItemStack stack, MatrixStack matrices, float x, float y, float weight, float delta, int seed) {
|
||||
renderStackTraits(SpellTraits.of(stack), matrices, x, y, weight, delta, seed);
|
||||
renderStackTraits(SpellTraits.of(stack), matrices, x, y, weight, delta, seed, false);
|
||||
}
|
||||
|
||||
public static void renderStackTraits(SpellTraits traits, MatrixStack matrices, float x, float y, float weight, float delta, int seed) {
|
||||
public static void renderStackTraits(SpellTraits traits, MatrixStack matrices, 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;
|
||||
|
@ -93,10 +93,11 @@ public class ItemTraitsTooltipRenderer implements Text, OrderedText, TooltipComp
|
|||
float r = 9 + 2 * MathHelper.sin(delta / 20F);
|
||||
|
||||
for (var entry : traits) {
|
||||
if (isKnown(entry.getKey())) {
|
||||
if (revealAll || isKnown(entry.getKey())) {
|
||||
ItemTraitsTooltipRenderer.renderTraitIcon(entry.getKey(), entry.getValue() * weight, matrices,
|
||||
x + r * MathHelper.sin(angle),
|
||||
y + r * MathHelper.cos(angle)
|
||||
y + r * MathHelper.cos(angle),
|
||||
revealAll || isKnown(entry.getKey())
|
||||
);
|
||||
angle += angleIncrement;
|
||||
}
|
||||
|
@ -109,12 +110,16 @@ public class ItemTraitsTooltipRenderer implements Text, OrderedText, TooltipComp
|
|||
}
|
||||
|
||||
public static void renderTraitIcon(Trait trait, float value, MatrixStack matrices, float xx, float yy) {
|
||||
renderTraitIcon(trait, value, matrices, xx, yy, isKnown(trait));
|
||||
}
|
||||
|
||||
public static void renderTraitIcon(Trait trait, float value, MatrixStack matrices, float xx, float yy, boolean reveal) {
|
||||
TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
|
||||
ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
|
||||
|
||||
int size = 12;
|
||||
|
||||
RenderSystem.setShaderTexture(0, isKnown(trait) ? trait.getSprite() : UNKNOWN);
|
||||
RenderSystem.setShaderTexture(0, reveal ? trait.getSprite() : UNKNOWN);
|
||||
|
||||
matrices.push();
|
||||
matrices.translate(xx, yy, itemRenderer.zOffset + 300.0F);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.unicopia.client.gui.spellbook;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -54,7 +55,14 @@ class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder {
|
|||
@Override
|
||||
public void input(ItemStack... stacks) {
|
||||
if (stacks.length > 0) {
|
||||
entries.add(new Stacks(stacks));
|
||||
entries.add(Entry.of(stacks));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void input(Trait... traits) {
|
||||
if (traits.length > 0) {
|
||||
entries.add(Entry.of(1, traits));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,14 +76,14 @@ class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder {
|
|||
@Override
|
||||
public void mystery(ItemStack... stacks) {
|
||||
if (stacks.length > 0) {
|
||||
entries.add(new HiddenStacks(stacks));
|
||||
entries.add(Multiple.of(Arrays.stream(stacks).map(HiddenStacks::new).toArray(Entry[]::new)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void result(ItemStack...stacks) {
|
||||
if (stacks.length > 0) {
|
||||
result = Optional.of(new Stacks(stacks));
|
||||
result = Optional.of(Entry.of(stacks));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,6 +156,15 @@ class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder {
|
|||
}
|
||||
|
||||
interface Entry {
|
||||
|
||||
static Entry of(ItemStack... stacks) {
|
||||
return Multiple.of(Arrays.stream(stacks).map(Stacks::new).toArray(Entry[]::new));
|
||||
}
|
||||
|
||||
static Entry of(float value, Trait... traits) {
|
||||
return Multiple.of(Arrays.stream(traits).map(t -> new Traits(t, value)).toArray(Entry[]::new));
|
||||
}
|
||||
|
||||
void render(MatrixStack matrices, int mouseX, int mouseY, float tickDelta);
|
||||
|
||||
Tooltip getTooltip();
|
||||
|
@ -155,15 +172,37 @@ class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder {
|
|||
void onClick();
|
||||
}
|
||||
|
||||
static class Stacks implements IngredientTree.Entry {
|
||||
static class Multiple implements IngredientTree.Entry {
|
||||
private int ticker;
|
||||
protected int index;
|
||||
protected final ItemStack[] stacks;
|
||||
protected final IngredientTree.Entry[] entries;
|
||||
|
||||
protected final ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
|
||||
static final IngredientTree.Entry EMPTY = new IngredientTree.Entry() {
|
||||
|
||||
Stacks(ItemStack[] stacks) {
|
||||
this.stacks = stacks;
|
||||
@Override
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float tickDelta) {}
|
||||
|
||||
@Override
|
||||
public void onClick() { }
|
||||
|
||||
@Override
|
||||
public Tooltip getTooltip() {
|
||||
return List::of;
|
||||
}
|
||||
};
|
||||
|
||||
static IngredientTree.Entry of(IngredientTree.Entry... entries) {
|
||||
if (entries.length == 0) {
|
||||
return EMPTY;
|
||||
}
|
||||
if (entries.length == 1) {
|
||||
return entries[0];
|
||||
}
|
||||
return new Multiple(entries);
|
||||
}
|
||||
|
||||
Multiple(IngredientTree.Entry[] entries) {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -171,25 +210,53 @@ class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder {
|
|||
y -= 2;
|
||||
|
||||
if (ticker++ % 30 == 0) {
|
||||
index = (index + 1) % stacks.length;
|
||||
index = (index + 1) % entries.length;
|
||||
}
|
||||
|
||||
entries[index].render(matrices, x, y, tickDelta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tooltip getTooltip() {
|
||||
return () -> entries[index].getTooltip().getLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
entries[index].onClick();
|
||||
}
|
||||
}
|
||||
|
||||
static class Stacks implements IngredientTree.Entry {
|
||||
|
||||
protected final ItemStack stack;
|
||||
|
||||
protected final ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
|
||||
|
||||
Stacks(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, int x, int y, float tickDelta) {
|
||||
y -= 2;
|
||||
|
||||
Vector4f pos = new Vector4f(x, y, 0, 1);
|
||||
pos.mul(matrices.peek().getPositionMatrix());
|
||||
drawItem((int)pos.x, (int)pos.y);
|
||||
}
|
||||
|
||||
protected void drawItem(int x, int y) {
|
||||
itemRenderer.renderInGui(stacks[index], x, y);
|
||||
itemRenderer.renderInGui(stack, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tooltip getTooltip() {
|
||||
return () -> {
|
||||
if (stacks[index].isEmpty()) {
|
||||
if (stack.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
return stacks[index].getTooltip(MinecraftClient.getInstance().player, TooltipContext.Default.BASIC);
|
||||
return stack.getTooltip(MinecraftClient.getInstance().player, TooltipContext.Default.BASIC);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -204,13 +271,13 @@ class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder {
|
|||
parent.color(0, 0, 0, a);
|
||||
});
|
||||
|
||||
HiddenStacks(ItemStack[] stacks) {
|
||||
super(stacks);
|
||||
HiddenStacks(ItemStack stack) {
|
||||
super(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawItem(int x, int y) {
|
||||
var model = itemRenderer.getModel(stacks[index], null, null, 0);
|
||||
var model = itemRenderer.getModel(stack, null, null, 0);
|
||||
|
||||
MinecraftClient.getInstance().getTextureManager().getTexture(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE).setFilter(false, false);
|
||||
RenderSystem.setShaderTexture(0, PlayerScreenHandler.BLOCK_ATLAS_TEXTURE);
|
||||
|
@ -231,7 +298,7 @@ class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder {
|
|||
}
|
||||
RenderSystem.disableDepthTest();
|
||||
try {
|
||||
itemRenderer.renderItem(stacks[index], ModelTransformation.Mode.GUI, false, new MatrixStack(), layer -> PassThroughVertexConsumer.of(immediate.getBuffer(layer), FIXTURE), 0, OverlayTexture.DEFAULT_UV, model);
|
||||
itemRenderer.renderItem(stack, ModelTransformation.Mode.GUI, false, new MatrixStack(), layer -> PassThroughVertexConsumer.of(immediate.getBuffer(layer), FIXTURE), 0, OverlayTexture.DEFAULT_UV, model);
|
||||
immediate.draw();
|
||||
} catch (Exception e) {
|
||||
// Sodium
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
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.Ingredient;
|
||||
import net.minecraft.recipe.ShapedRecipe;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class MagicalShapedEmiRecipe extends EmiCraftingRecipe {
|
||||
public MagicalShapedEmiRecipe(ShapedRecipe recipe, CustomisedSpellType<?> spellEffect, ItemStack output) {
|
||||
super(padIngredients(recipe, spellEffect), EmiStack.of(output),
|
||||
new Identifier(recipe.getId().getNamespace(), recipe.getId().getPath() + "/" + spellEffect.type().getId().getPath()), false);
|
||||
EmiShapedRecipe.setRemainders(input, recipe);
|
||||
}
|
||||
|
||||
private static List<EmiIngredient> padIngredients(ShapedRecipe recipe, CustomisedSpellType<?> spellEffect) {
|
||||
List<EmiIngredient> list = recipe.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 e) {
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package com.minelittlepony.unicopia.compat.emi;
|
||||
|
||||
import java.util.Arrays;
|
||||
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.item.EnchantableItem;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.item.URecipes;
|
||||
import com.minelittlepony.unicopia.item.group.MultiItem;
|
||||
|
||||
import dev.emi.emi.api.EmiPlugin;
|
||||
import dev.emi.emi.api.EmiRegistry;
|
||||
import dev.emi.emi.api.recipe.EmiRecipeCategory;
|
||||
import dev.emi.emi.api.stack.Comparison;
|
||||
import dev.emi.emi.api.stack.EmiStack;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class Main implements EmiPlugin {
|
||||
static final EmiStack SPELL_BOOK_STATION = EmiStack.of(UItems.SPELLBOOK);
|
||||
static final EmiRecipeCategory SPELL_BOOK_CATEGORY = new EmiRecipeCategory(Unicopia.id("spellbook"), SPELL_BOOK_STATION, SPELL_BOOK_STATION);
|
||||
static final Comparison COMPARING_BOTH = Comparison.builder().nbt(true).build();
|
||||
|
||||
@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 instanceof SpellDuplicatingRecipe) {
|
||||
registry.addRecipe(new SpellDuplicatingEmiRecipe(recipe));
|
||||
} else if (recipe instanceof SpellEnhancingRecipe enhancingRecipe) {
|
||||
Trait.all().forEach(trait -> {
|
||||
registry.addRecipe(new SpellDuplicatingEmiRecipe(recipe) {
|
||||
private final Identifier id;
|
||||
|
||||
{
|
||||
id = recipe.getId().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.builder().nbt(false).build()))
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return id;
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
registry.addRecipe(new SpellbookEmiRecipe(recipe));
|
||||
}
|
||||
});
|
||||
|
||||
Stream.of(UItems.GEMSTONE, UItems.BOTCHED_GEM, UItems.MAGIC_STAFF, UItems.FILLED_JAR).forEach(item -> {
|
||||
registry.setDefaultComparison(item, comparison -> COMPARING_BOTH);
|
||||
});
|
||||
|
||||
registry.getRecipeManager().listAllOfType(RecipeType.CRAFTING).stream()
|
||||
.filter(recipe -> recipe instanceof SpellShapedCraftingRecipe)
|
||||
.map(SpellShapedCraftingRecipe.class::cast).forEach(recipe -> {
|
||||
ItemStack output = recipe.getOutput();
|
||||
if (output.getItem() instanceof MultiItem multiItem && output.getItem() instanceof EnchantableItem enchantable) {
|
||||
multiItem.getDefaultStacks().forEach(outputVariation -> {
|
||||
var spellEffect = enchantable.getSpellEffect(outputVariation);
|
||||
if (!spellEffect.isEmpty()) {
|
||||
registry.addRecipe(new MagicalShapedEmiRecipe(recipe, spellEffect, outputVariation));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
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 net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class SpellDuplicatingEmiRecipe extends SpellbookEmiRecipe {
|
||||
|
||||
public SpellDuplicatingEmiRecipe(SpellbookRecipe 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<? extends EmiIngredient> ingredients;
|
||||
private final int maxCount;
|
||||
|
||||
public CyclingRecipeIngredient(List<? extends EmiIngredient> ingredients, long amount) {
|
||||
super(ingredients, amount);
|
||||
this.ingredients = ingredients;
|
||||
this.maxCount = ingredients.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, int x, int y, float delta, int flags) {
|
||||
|
||||
if (maxCount < 2 || MinecraftClient.getInstance().player == null) {
|
||||
super.render(matrices, 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(matrices, x, y, EmiPort.literal(count));
|
||||
}
|
||||
ingredients.get(tick).render(matrices, x, y, delta, flags & ~RENDER_AMOUNT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
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.render.EmiTexture;
|
||||
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.util.math.MatrixStack;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
class SpellbookEmiRecipe implements EmiRecipe, SpellbookRecipe.CraftingTreeBuilder {
|
||||
|
||||
private final SpellbookRecipe recipe;
|
||||
|
||||
private final List<EmiIngredient> inputs = new ArrayList<>();
|
||||
private final List<EmiStack> outputs = new ArrayList<>();
|
||||
|
||||
public SpellbookEmiRecipe(SpellbookRecipe recipe) {
|
||||
this.recipe = recipe;
|
||||
recipe.buildCraftingTree(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmiRecipeCategory getCategory() {
|
||||
return Main.SPELL_BOOK_CATEGORY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return recipe.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmiIngredient> getInputs() {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmiStack> getOutputs() {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDisplayWidth() {
|
||||
return 220;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDisplayHeight() {
|
||||
return 145;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addWidgets(WidgetHolder widgets) {
|
||||
widgets.addTexture(SpellbookScreen.TEXTURE, 0, 0, getDisplayWidth(), getDisplayHeight(), 50, 50, 128, 128, 512, 256);
|
||||
widgets.addTexture(EmiTexture.EMPTY_ARROW, 160, 65);
|
||||
|
||||
List<HexagonalCraftingGrid.Slot> grid = new ArrayList<>();
|
||||
List<HexagonalCraftingGrid.Slot> gem = new ArrayList<>();
|
||||
HexagonalCraftingGrid.create(4, 35, 3, grid, gem);
|
||||
|
||||
int currentInput = 1;
|
||||
|
||||
for (int i = 0; i < grid.size(); i++) {
|
||||
widgets.add(new SlotTexture(grid.get(i)));
|
||||
|
||||
if (currentInput < inputs.size() && grid.get(i).weight() == 1) {
|
||||
widgets.addSlot(inputs.get(currentInput++), grid.get(i).left(), grid.get(i).top()).drawBack(false);
|
||||
} else {
|
||||
widgets.addSlot(grid.get(i).left(), grid.get(i).top()).drawBack(false);
|
||||
}
|
||||
}
|
||||
widgets.addSlot(inputs.get(0), gem.get(0).left(), gem.get(0).top()).drawBack(false);
|
||||
widgets.addSlot(getOutput(), 190, 60).output(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(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
RenderSystem.enableBlend();
|
||||
super.render(matrices, mouseX, mouseY, delta);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package com.minelittlepony.unicopia.compat.emi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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.tooltip.TooltipComponent;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
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;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public NbtCompound getNbt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getKey() {
|
||||
return trait;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId() {
|
||||
return trait.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Text> getTooltipText() {
|
||||
return trait.getTooltipLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TooltipComponent> getTooltip() {
|
||||
List<TooltipComponent> 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(MatrixStack matrices, int x, int y, float delta, int flags) {
|
||||
if ((flags & RENDER_ICON) != 0) {
|
||||
List<Item> knownItems = trait.getItems();
|
||||
if (knownItems.isEmpty() || MinecraftClient.getInstance().player == null) {
|
||||
ItemTraitsTooltipRenderer.renderTraitIcon(trait, amount, matrices, x, y, true);
|
||||
} else {
|
||||
int tick = (MinecraftClient.getInstance().player.age / 12) % knownItems.size();
|
||||
ItemStack stack = knownItems.get(tick).getDefaultStack();
|
||||
EmiStack.of(stack).render(matrices, x, y, delta, flags);
|
||||
ItemTraitsTooltipRenderer.renderStackTraits(traits, matrices, x, y, 1, delta, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & RENDER_REMAINDER) != 0) {
|
||||
EmiRender.renderRemainderIcon(this, matrices, 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);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.item;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -81,7 +82,10 @@ public class EnchantedStaffItem extends StaffItem implements EnchantableItem, Ch
|
|||
|
||||
@Override
|
||||
public List<ItemStack> getDefaultStacks() {
|
||||
return ENTITY_TYPE_TO_SPELL.values().stream().distinct().map(type -> EnchantableItem.enchant(getDefaultStack(), type)).toList();
|
||||
return Stream.concat(
|
||||
Stream.of(getDefaultStack()),
|
||||
ENTITY_TYPE_TO_SPELL.values().stream().distinct().map(type -> EnchantableItem.enchant(getDefaultStack(), type))
|
||||
).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
"item.unicopia.friendship_bracelet.glowing": "Glowing",
|
||||
|
||||
"item.unicopia.spellbook": "Spellbook",
|
||||
"emi.category.unicopia.spellbook": "Spellbook",
|
||||
|
||||
"item.unicopia.butterfly_spawn_egg": "Butterfly Spawn Egg",
|
||||
"item.unicopia.butterfly": "Butterfly",
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"accessWidener": "unicopia.aw",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"main": [
|
||||
"com.minelittlepony.unicopia.Unicopia"
|
||||
],
|
||||
"client": [
|
||||
|
@ -26,6 +26,9 @@
|
|||
"modmenu": [
|
||||
"com.minelittlepony.unicopia.modmenu.UMenuFactory"
|
||||
],
|
||||
"emi": [
|
||||
"com.minelittlepony.unicopia.compat.emi.Main"
|
||||
],
|
||||
"minelittlepony": [
|
||||
"com.minelittlepony.unicopia.client.minelittlepony.Main"
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue