From eaac65c47fb7784ea7b596fd66a256bbc5128088 Mon Sep 17 00:00:00 2001 From: "yrsegal@gmail.com" Date: Sun, 1 May 2022 13:38:58 -0400 Subject: [PATCH] spellbook/focus recipes are now in JEI --- .../hexcasting/api/item/DataHolderItem.java | 10 ++ .../petrak/hexcasting/api/spell/SpellDatum.kt | 17 +++- .../client/RegisterClientStuff.java | 31 +++--- .../common/items/ItemSpellbook.java | 36 ++++++- .../common/recipe/HexRecipeSerializers.java | 5 + .../common/recipe/SealFocusRecipe.java | 68 +++++-------- .../common/recipe/SealSpellbookRecipe.java | 66 +++++-------- .../recipe/ingredient/UnsealedIngredient.java | 97 +++++++++++++++++++ .../assets/hexcasting/lang/en_us.json | 1 + 9 files changed, 224 insertions(+), 107 deletions(-) create mode 100644 src/main/java/at/petrak/hexcasting/common/recipe/ingredient/UnsealedIngredient.java diff --git a/src/main/java/at/petrak/hexcasting/api/item/DataHolderItem.java b/src/main/java/at/petrak/hexcasting/api/item/DataHolderItem.java index dee9e52f..628babc3 100644 --- a/src/main/java/at/petrak/hexcasting/api/item/DataHolderItem.java +++ b/src/main/java/at/petrak/hexcasting/api/item/DataHolderItem.java @@ -1,8 +1,10 @@ package at.petrak.hexcasting.api.item; import at.petrak.hexcasting.api.spell.SpellDatum; +import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.server.level.ServerLevel; @@ -13,6 +15,8 @@ import org.jetbrains.annotations.Nullable; import java.util.List; public interface DataHolderItem { + String TAG_OVERRIDE_VISUALLY = "VisualOverride"; + @Nullable CompoundTag readDatumTag(ItemStack stack); @Nullable @@ -49,6 +53,12 @@ public interface DataHolderItem { if (pIsAdvanced.isAdvanced()) { pTooltipComponents.add(NbtUtils.toPrettyComponent(datumTag)); } + } else if (pStack.hasTag()) { + var tag = pStack.getTag(); + if (tag != null && tag.contains(DataHolderItem.TAG_OVERRIDE_VISUALLY, Tag.TAG_STRING)) { + pTooltipComponents.add(new TranslatableComponent("hexcasting.spelldata.onitem", + new TranslatableComponent("hexcasting.spelldata.anything").withStyle(ChatFormatting.LIGHT_PURPLE))); + } } } } diff --git a/src/main/java/at/petrak/hexcasting/api/spell/SpellDatum.kt b/src/main/java/at/petrak/hexcasting/api/spell/SpellDatum.kt index a7949bba..0058c9d0 100644 --- a/src/main/java/at/petrak/hexcasting/api/spell/SpellDatum.kt +++ b/src/main/java/at/petrak/hexcasting/api/spell/SpellDatum.kt @@ -1,10 +1,10 @@ package at.petrak.hexcasting.api.spell +import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.math.HexPattern +import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidSpellDatumType import at.petrak.hexcasting.api.utils.HexUtils import at.petrak.hexcasting.api.utils.HexUtils.serializeToNBT -import at.petrak.hexcasting.api.spell.casting.CastingContext -import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidSpellDatumType import net.minecraft.ChatFormatting import net.minecraft.nbt.* import net.minecraft.network.chat.Component @@ -259,6 +259,19 @@ class SpellDatum private constructor(val payload: T) { ValidTypes.any { clazz -> clazz.isAssignableFrom(checkee.javaClass) } } + @JvmStatic + fun GetTagName(datumType: DatumType): String { + return when (datumType) { + DatumType.ENTITY -> TAG_ENTITY + DatumType.WIDGET -> TAG_WIDGET + DatumType.LIST -> TAG_LIST + DatumType.PATTERN -> TAG_PATTERN + DatumType.DOUBLE -> TAG_DOUBLE + DatumType.VEC -> TAG_VEC3 + DatumType.OTHER, DatumType.EMPTY -> "" + } + } + } } diff --git a/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java b/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java index 61a4131e..0f47ffc2 100644 --- a/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java +++ b/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java @@ -29,6 +29,8 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRenderers; import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Style; import net.minecraft.network.chat.TextColor; import net.minecraft.network.chat.TextComponent; @@ -251,19 +253,26 @@ public class RegisterClientStuff { ItemProperties.register((Item) item, ItemFocus.DATATYPE_PRED, (stack, level, holder, holderID) -> { var datum = item.readDatumTag(stack); + String typename = null; if (datum != null) { - var typename = datum.getAllKeys().iterator().next(); - return switch (typename) { - case SpellDatum.TAG_ENTITY -> 1f; - case SpellDatum.TAG_DOUBLE -> 2f; - case SpellDatum.TAG_VEC3 -> 3f; - case SpellDatum.TAG_WIDGET -> 4f; - case SpellDatum.TAG_LIST -> 5f; - case SpellDatum.TAG_PATTERN -> 6f; - default -> 0f; // uh oh - }; + typename = datum.getAllKeys().iterator().next(); + + } else if (stack.hasTag()) { + CompoundTag tag = stack.getTag(); + if (tag != null && tag.contains(DataHolderItem.TAG_OVERRIDE_VISUALLY, Tag.TAG_STRING)) { + typename = tag.getString(DataHolderItem.TAG_OVERRIDE_VISUALLY); + } } - return 0f; + + return typename == null ? 0f : switch (typename) { + case SpellDatum.TAG_ENTITY -> 1f; + case SpellDatum.TAG_DOUBLE -> 2f; + case SpellDatum.TAG_VEC3 -> 3f; + case SpellDatum.TAG_WIDGET -> 4f; + case SpellDatum.TAG_LIST -> 5f; + case SpellDatum.TAG_PATTERN -> 6f; + default -> 0f; // uh oh + }; }); ItemProperties.register((Item) item, ItemFocus.SEALED_PRED, (stack, level, holder, holderID) -> item.canWrite(stack, SpellDatum.make(Widget.NULL)) ? 0f : 1f); diff --git a/src/main/java/at/petrak/hexcasting/common/items/ItemSpellbook.java b/src/main/java/at/petrak/hexcasting/common/items/ItemSpellbook.java index 7a64fb2b..47518284 100644 --- a/src/main/java/at/petrak/hexcasting/common/items/ItemSpellbook.java +++ b/src/main/java/at/petrak/hexcasting/common/items/ItemSpellbook.java @@ -58,11 +58,16 @@ public class ItemSpellbook extends Item implements DataHolderItem { new TextComponent(String.valueOf(highest)).withStyle(ChatFormatting.WHITE)) .withStyle(ChatFormatting.GRAY)); } else { - if (sealed) - tooltip.add(new TranslatableComponent("hexcasting.tooltip.spellbook.empty.sealed", - new TranslatableComponent("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD)) - .withStyle(ChatFormatting.GRAY)); - else + boolean overridden = tag.contains(DataHolderItem.TAG_OVERRIDE_VISUALLY, Tag.TAG_STRING); + if (sealed) { + if (overridden) { + tooltip.add(new TranslatableComponent("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD)); + } else { + tooltip.add(new TranslatableComponent("hexcasting.tooltip.spellbook.empty.sealed", + new TranslatableComponent("hexcasting.tooltip.spellbook.sealed").withStyle(ChatFormatting.GOLD)) + .withStyle(ChatFormatting.GRAY)); + } + } else if (!overridden) tooltip.add(new TranslatableComponent("hexcasting.tooltip.spellbook.empty").withStyle(ChatFormatting.GRAY)); } } else { @@ -208,6 +213,27 @@ public class ItemSpellbook extends Item implements DataHolderItem { } + public static boolean HasDatum(ItemStack stack) { + if (!stack.hasTag()) { + return false; + } + var tag = stack.getTag(); + + int idx; + if (tag.contains(TAG_SELECTED_PAGE, Tag.TAG_ANY_NUMERIC)) { + idx = tag.getInt(TAG_SELECTED_PAGE); + } else { + idx = 0; + } + var key = String.valueOf(idx); + if (tag.contains(TAG_PAGES, Tag.TAG_COMPOUND)) { + var pagesTag = tag.getCompound(TAG_PAGES); + return pagesTag.contains(key); + } else { + return false; + } + } + public static boolean IsSealed(ItemStack stack) { if (!stack.hasTag()) return false; diff --git a/src/main/java/at/petrak/hexcasting/common/recipe/HexRecipeSerializers.java b/src/main/java/at/petrak/hexcasting/common/recipe/HexRecipeSerializers.java index dde9660c..484dde13 100644 --- a/src/main/java/at/petrak/hexcasting/common/recipe/HexRecipeSerializers.java +++ b/src/main/java/at/petrak/hexcasting/common/recipe/HexRecipeSerializers.java @@ -1,9 +1,12 @@ package at.petrak.hexcasting.common.recipe; import at.petrak.hexcasting.HexMod; +import at.petrak.hexcasting.common.recipe.ingredient.UnsealedIngredient; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; +import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.registries.DeferredRegister; @@ -22,5 +25,7 @@ public class HexRecipeSerializers { @SubscribeEvent public static void registerTypes(RegistryEvent.Register evt) { BRAINSWEEP_TYPE = RecipeType.register(HexMod.MOD_ID + ":brainsweep"); + + CraftingHelper.register(new ResourceLocation(HexMod.MOD_ID, "unsealed"), UnsealedIngredient.Serializer.INSTANCE); } } diff --git a/src/main/java/at/petrak/hexcasting/common/recipe/SealFocusRecipe.java b/src/main/java/at/petrak/hexcasting/common/recipe/SealFocusRecipe.java index 150c4248..d7ff9776 100644 --- a/src/main/java/at/petrak/hexcasting/common/recipe/SealFocusRecipe.java +++ b/src/main/java/at/petrak/hexcasting/common/recipe/SealFocusRecipe.java @@ -2,60 +2,41 @@ package at.petrak.hexcasting.common.recipe; import at.petrak.hexcasting.common.items.HexItems; import at.petrak.hexcasting.common.items.ItemFocus; +import at.petrak.hexcasting.common.recipe.ingredient.UnsealedIngredient; +import net.minecraft.core.NonNullList; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.CustomRecipe; +import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.ShapelessRecipe; import net.minecraft.world.item.crafting.SimpleRecipeSerializer; -import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; -public class SealFocusRecipe extends CustomRecipe { +public class SealFocusRecipe extends ShapelessRecipe { public static final SimpleRecipeSerializer SERIALIZER = new SimpleRecipeSerializer<>(SealFocusRecipe::new); + private static ItemStack getSealedStack() { + ItemStack output = new ItemStack(HexItems.FOCUS::get); + output.getOrCreateTag().putBoolean(ItemFocus.TAG_SEALED, true); + return output; + } + + private static NonNullList createIngredients() { + NonNullList ingredients = NonNullList.createWithCapacity(2); + ingredients.add(UnsealedIngredient.of(new ItemStack(HexItems.FOCUS::get))); + ingredients.add(Ingredient.of(Items.HONEYCOMB)); + return ingredients; + } + public SealFocusRecipe(ResourceLocation id) { - super(id); + super(id, "", getSealedStack(), createIngredients()); } @Override - public boolean matches(CraftingContainer inv, Level world) { - var foundWax = false; - var foundOkFocus = false; - - for (int i = 0; i < inv.getContainerSize(); i++) { - var stack = inv.getItem(i); - if (!stack.isEmpty()) { - if (stack.is(HexItems.FOCUS.get())) { - if (foundOkFocus) { - return false; - } - - if (stack.hasTag() - && stack.getTag().contains(ItemFocus.TAG_DATA) - && (!stack.getTag().contains(ItemFocus.TAG_SEALED) - || !stack.getTag().getBoolean(ItemFocus.TAG_SEALED))) { - foundOkFocus = true; - } else { - return false; - } - } else if (stack.is(Items.HONEYCOMB)) { - if (foundWax) { - return false; - } - foundWax = true; - } else { - return false; - } - } - } - - return foundWax && foundOkFocus; - } - - @Override - public ItemStack assemble(CraftingContainer inv) { + public @NotNull ItemStack assemble(CraftingContainer inv) { ItemStack out = ItemStack.EMPTY; for (int i = 0; i < inv.getContainerSize(); i++) { @@ -75,12 +56,7 @@ public class SealFocusRecipe extends CustomRecipe { } @Override - public boolean canCraftInDimensions(int width, int height) { - return width * height >= 2; - } - - @Override - public RecipeSerializer getSerializer() { + public @NotNull RecipeSerializer getSerializer() { return SERIALIZER; } } diff --git a/src/main/java/at/petrak/hexcasting/common/recipe/SealSpellbookRecipe.java b/src/main/java/at/petrak/hexcasting/common/recipe/SealSpellbookRecipe.java index f256cd93..5136d1da 100644 --- a/src/main/java/at/petrak/hexcasting/common/recipe/SealSpellbookRecipe.java +++ b/src/main/java/at/petrak/hexcasting/common/recipe/SealSpellbookRecipe.java @@ -2,57 +2,41 @@ package at.petrak.hexcasting.common.recipe; import at.petrak.hexcasting.common.items.HexItems; import at.petrak.hexcasting.common.items.ItemSpellbook; +import at.petrak.hexcasting.common.recipe.ingredient.UnsealedIngredient; +import net.minecraft.core.NonNullList; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.CustomRecipe; +import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.ShapelessRecipe; import net.minecraft.world.item.crafting.SimpleRecipeSerializer; -import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; -public class SealSpellbookRecipe extends CustomRecipe { +public class SealSpellbookRecipe extends ShapelessRecipe { public static final SimpleRecipeSerializer SERIALIZER = new SimpleRecipeSerializer<>(SealSpellbookRecipe::new); + private static ItemStack getSealedStack() { + ItemStack output = new ItemStack(HexItems.SPELLBOOK::get); + ItemSpellbook.SetSealed(output, true); + return output; + } + + private static NonNullList createIngredients() { + NonNullList ingredients = NonNullList.createWithCapacity(2); + ingredients.add(UnsealedIngredient.of(new ItemStack(HexItems.SPELLBOOK::get))); + ingredients.add(Ingredient.of(Items.HONEYCOMB)); + return ingredients; + } + public SealSpellbookRecipe(ResourceLocation id) { - super(id); + super(id, "", getSealedStack(), createIngredients()); } @Override - public boolean matches(CraftingContainer inv, Level world) { - var foundWax = false; - var foundOkSpellbook = false; - - for (int i = 0; i < inv.getContainerSize(); i++) { - var stack = inv.getItem(i); - if (!stack.isEmpty()) { - if (stack.is(HexItems.SPELLBOOK.get())) { - if (foundOkSpellbook) { - return false; - } - - if (!ItemSpellbook.IsSealed(stack)) { - foundOkSpellbook = true; - } else { - return false; - } - } else if (stack.is(Items.HONEYCOMB)) { - if (foundWax) { - return false; - } - foundWax = true; - } else { - return false; - } - } - } - - return foundWax && foundOkSpellbook; - } - - @Override - public ItemStack assemble(CraftingContainer inv) { + public @NotNull ItemStack assemble(CraftingContainer inv) { ItemStack out = ItemStack.EMPTY; for (int i = 0; i < inv.getContainerSize(); i++) { @@ -67,16 +51,12 @@ public class SealSpellbookRecipe extends CustomRecipe { ItemSpellbook.SetSealed(out, true); out.setCount(1); } + return out; } @Override - public boolean canCraftInDimensions(int width, int height) { - return width * height >= 2; - } - - @Override - public RecipeSerializer getSerializer() { + public @NotNull RecipeSerializer getSerializer() { return SERIALIZER; } } diff --git a/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/UnsealedIngredient.java b/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/UnsealedIngredient.java new file mode 100644 index 00000000..0f343a38 --- /dev/null +++ b/src/main/java/at/petrak/hexcasting/common/recipe/ingredient/UnsealedIngredient.java @@ -0,0 +1,97 @@ +package at.petrak.hexcasting.common.recipe.ingredient; + +import at.petrak.hexcasting.api.cap.DataHolder; +import at.petrak.hexcasting.api.cap.HexCapabilities; +import at.petrak.hexcasting.api.item.DataHolderItem; +import at.petrak.hexcasting.api.spell.DatumType; +import at.petrak.hexcasting.api.spell.SpellDatum; +import at.petrak.hexcasting.api.spell.Widget; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraftforge.common.crafting.AbstractIngredient; +import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraftforge.common.crafting.IIngredientSerializer; +import net.minecraftforge.common.crafting.NBTIngredient; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Objects; +import java.util.Optional; + +public class UnsealedIngredient extends AbstractIngredient { + private final ItemStack stack; + + protected UnsealedIngredient(ItemStack stack) { + super(Arrays.stream(DatumType.values()) + .filter((it) -> it != DatumType.EMPTY && it != DatumType.OTHER) + .map((type) -> { + ItemStack newStack = stack.copy(); + newStack.getOrCreateTag().putString(DataHolderItem.TAG_OVERRIDE_VISUALLY, SpellDatum.GetTagName(type)); + return new Ingredient.ItemValue(newStack); + })); + this.stack = stack; + } + + /** + * Creates a new ingredient matching the given stack + */ + public static UnsealedIngredient of(ItemStack stack) { + return new UnsealedIngredient(stack); + } + + @Override + public boolean test(@Nullable ItemStack input) { + if (input == null) + return false; + if(this.stack.getItem() == input.getItem() && this.stack.getDamageValue() == input.getDamageValue()) { + Optional holder = HexCapabilities.getCapability(input, HexCapabilities.DATUM); + if (holder.isPresent()) { + return holder.get().readRawDatum() != null && holder.get().writeDatum(SpellDatum.make(Widget.NULL), true); + } + } + + return false; + } + + @Override + public boolean isSimple() { + return false; + } + + @Override + public @NotNull IIngredientSerializer getSerializer() { + return UnsealedIngredient.Serializer.INSTANCE; + } + + @Override + public @NotNull JsonElement toJson() { + JsonObject json = new JsonObject(); + json.addProperty("type", Objects.toString(CraftingHelper.getID(NBTIngredient.Serializer.INSTANCE))); + json.addProperty("item", Objects.toString(stack.getItem().getRegistryName())); + return json; + } + + + public static class Serializer implements IIngredientSerializer { + public static final UnsealedIngredient.Serializer INSTANCE = new UnsealedIngredient.Serializer(); + + @Override + public @NotNull UnsealedIngredient parse(FriendlyByteBuf buffer) { + return new UnsealedIngredient(buffer.readItem()); + } + + @Override + public @NotNull UnsealedIngredient parse(@NotNull JsonObject json) { + return new UnsealedIngredient(CraftingHelper.getItemStack(json, true)); + } + + @Override + public void write(FriendlyByteBuf buffer, UnsealedIngredient ingredient) { + buffer.writeItem(ingredient.stack); + } + } +} diff --git a/src/main/resources/assets/hexcasting/lang/en_us.json b/src/main/resources/assets/hexcasting/lang/en_us.json index cf3deaba..15bacaa0 100644 --- a/src/main/resources/assets/hexcasting/lang/en_us.json +++ b/src/main/resources/assets/hexcasting/lang/en_us.json @@ -120,6 +120,7 @@ "hexcasting.tooltip.brainsweep.biome.any": "Any Biome", "hexcasting.tooltip.brainsweep.min_level": "Level %d or higher", "hexcasting.spelldata.onitem": "Contains: %s", + "hexcasting.spelldata.anything": "Anything", "hexcasting.spelldata.entity.whoknows": "An Entity (this should only show up if this was stored before the 0.5.0 update, use Scribe's Reflection, Scribe's Gambit to fix)", "hexcasting.spelldata.akashic.nopos": "The owning record does not know of any iota here (this is a bug)",