From 8aea7d326f4af76b39df14cfe53785632fa4210d Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 11 Nov 2021 20:06:28 +0200 Subject: [PATCH] Implement crafting using traits, and trait discovery, AND show known traits in item tooltips --- .../magic/spell/crafting/SpellbookRecipe.java | 26 ++++ .../crafting/TraitRequirementRecipe.java | 105 ++++++++++++++++ .../magic/spell/effect/AbstractSpell.java | 2 +- .../magic/spell/trait/SpellTraits.java | 104 +++++++++++++++- .../magic/spell/trait/TraitDiscovery.java | 115 ++++++++++++++++++ .../magic/spell/trait/TraitLoader.java | 2 +- .../container/SpellbookScreenHandler.java | 58 ++++++++- .../unicopia/entity/player/Pony.java | 10 ++ .../unicopia/item/URecipes.java | 26 ++-- .../unicopia/mixin/client/MixinItem.java | 5 + .../unicopia/util/InventoryUtil.java | 22 ++++ 11 files changed, 443 insertions(+), 32 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/SpellbookRecipe.java create mode 100644 src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/TraitRequirementRecipe.java create mode 100644 src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/TraitDiscovery.java create mode 100644 src/main/java/com/minelittlepony/unicopia/util/InventoryUtil.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/SpellbookRecipe.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/SpellbookRecipe.java new file mode 100644 index 00000000..5040d6e3 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/SpellbookRecipe.java @@ -0,0 +1,26 @@ +package com.minelittlepony.unicopia.ability.magic.spell.crafting; + +import com.minelittlepony.unicopia.container.SpellbookScreenHandler.SpellbookInventory; +import com.minelittlepony.unicopia.item.UItems; +import com.minelittlepony.unicopia.item.URecipes; + +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.RecipeType; + +public interface SpellbookRecipe extends Recipe { + @Override + default RecipeType getType() { + return URecipes.SPELLBOOK; + } + + @Override + default String getGroup() { + return "unicopia:spellbook"; + } + + @Override + default ItemStack createIcon() { + return new ItemStack(UItems.SPELLBOOK); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/TraitRequirementRecipe.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/TraitRequirementRecipe.java new file mode 100644 index 00000000..229eff9a --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/crafting/TraitRequirementRecipe.java @@ -0,0 +1,105 @@ +package com.minelittlepony.unicopia.ability.magic.spell.crafting; + +import com.google.gson.JsonObject; +import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; +import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits; +import com.minelittlepony.unicopia.container.SpellbookScreenHandler.SpellbookInventory; +import com.minelittlepony.unicopia.item.GemstoneItem; +import com.minelittlepony.unicopia.item.URecipes; + +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.RecipeSerializer; +import net.minecraft.recipe.ShapedRecipe; +import net.minecraft.util.Identifier; +import net.minecraft.util.JsonHelper; +import net.minecraft.world.World; + +public class TraitRequirementRecipe implements SpellbookRecipe { + + private final Identifier id; + private final Ingredient requirement; + private final SpellTraits requiredTraits; + private final ItemStack output; + + private TraitRequirementRecipe(Identifier id, Ingredient requirement, SpellTraits requiredTraits, ItemStack output) { + this.id = id; + this.requirement = requirement; + this.requiredTraits = requiredTraits; + this.output = output; + } + + @Override + public boolean matches(SpellbookInventory inventory, World world) { + return requirement.test(inventory.getItemToModify()) + && SpellTraits.of(inventory).includes(requiredTraits); + } + + @Override + public ItemStack craft(SpellbookInventory inventory) { + return SpellTraits.union( + SpellTraits.of(inventory.getItemToModify()), + SpellTraits.of(inventory), + SpellTraits.of(output) + ).applyTo(output); + } + + @Override + public boolean fits(int width, int height) { + return (width * height) > 0; + } + + @Override + public ItemStack getOutput() { + return output; + } + + @Override + public Identifier getId() { + return id; + } + + @Override + public RecipeSerializer getSerializer() { + return URecipes.TRAIT_REQUIREMENT; + } + + public static ItemStack outputFromJson(JsonObject json) { + ItemStack stack = ShapedRecipe.outputFromJson(json); + SpellTraits.fromJson(JsonHelper.getObject(json, "traits", new JsonObject())) + .map(traits -> traits.applyTo(stack)).orElse(stack); + + SpellType spell = SpellType.getKey(Identifier.tryParse(JsonHelper.getString(json, "spell", ""))); + if (spell != SpellType.EMPTY_KEY) { + return GemstoneItem.enchanted(stack, spell); + } + return stack; + } + + public static class Serializer implements RecipeSerializer { + @Override + public TraitRequirementRecipe read(Identifier id, JsonObject json) { + return new TraitRequirementRecipe(id, + Ingredient.fromJson(JsonHelper.getObject(json, "material")), + SpellTraits.fromJson(JsonHelper.getObject(json, "traits")).get(), + outputFromJson(JsonHelper.getObject(json, "result"))); + } + + @Override + public TraitRequirementRecipe read(Identifier id, PacketByteBuf buf) { + return new TraitRequirementRecipe(id, + Ingredient.fromPacket(buf), + SpellTraits.fromPacket(buf).get(), + buf.readItemStack() + ); + } + + @Override + public void write(PacketByteBuf buf, TraitRequirementRecipe recipe) { + recipe.requirement.write(buf); + recipe.requiredTraits.write(buf); + buf.writeItemStack(recipe.output); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java index 36c775a7..a1dc7b52 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java @@ -90,7 +90,7 @@ public abstract class AbstractSpell implements Spell { } isDead = compound.getBoolean("dead"); if (compound.contains("traits")) { - traits = SpellTraits.readNbt(compound.getCompound("traits")).orElse(SpellTraits.EMPTY); + traits = SpellTraits.fromNbt(compound.getCompound("traits")).orElse(SpellTraits.EMPTY); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java index e4fe6835..c8854841 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/SpellTraits.java @@ -1,7 +1,10 @@ package com.minelittlepony.unicopia.ability.magic.spell.trait; +import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -9,11 +12,18 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.google.gson.JsonObject; +import com.minelittlepony.unicopia.util.InventoryUtil; + import net.minecraft.block.Block; +import net.minecraft.inventory.Inventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; import net.minecraft.util.registry.Registry; public final class SpellTraits { @@ -29,6 +39,12 @@ public final class SpellTraits { return traits.isEmpty(); } + public boolean includes(SpellTraits other) { + return other.entries().stream().allMatch(pair -> { + return getAmount(pair.getKey()) >= pair.getValue(); + }); + } + public Set> entries() { return traits.entrySet(); } @@ -37,14 +53,46 @@ public final class SpellTraits { return traits.getOrDefault(trait, 0F); } + public void appendTooltip(List tooltip) { + if (isEmpty()) { + return; + } + tooltip.add(new LiteralText("Traits:")); + traits.forEach((trait, amount) -> { + tooltip.add(new LiteralText(trait.name().toLowerCase() + ": " + amount)); + }); + } + public NbtCompound toNbt() { NbtCompound nbt = new NbtCompound(); traits.forEach((key, value) -> nbt.putFloat(key.name(), value)); return nbt; } - public static Optional of(Collection stacks) { - return fromEntries(stacks.stream().flatMap(a -> of(a).entries().stream())); + public void write(PacketByteBuf buf) { + buf.writeInt(traits.size()); + traits.forEach((trait, value) -> { + buf.writeIdentifier(trait.getId()); + buf.writeFloat(value); + }); + } + + public static SpellTraits union(SpellTraits...many) { + Map traits = new HashMap<>(); + for (SpellTraits i : many) { + combine(traits, i.traits); + } + return traits.isEmpty() ? EMPTY : new SpellTraits(traits); + } + + public static SpellTraits of(Inventory inventory) { + List stacks = new ArrayList<>(); + InventoryUtil.iterate(inventory).forEach(stacks::add); + return of(stacks); + } + + public static SpellTraits of(Collection stacks) { + return fromEntries(stacks.stream().flatMap(a -> of(a).entries().stream())).orElse(SpellTraits.EMPTY); } public static SpellTraits of(ItemStack stack) { @@ -52,7 +100,7 @@ public final class SpellTraits { } public static SpellTraits of(Item item) { - return TraitLoader.INSTANCE.values.getOrDefault(Registry.ITEM.getId(item), null); + return TraitLoader.INSTANCE.values.getOrDefault(Registry.ITEM.getId(item), EMPTY); } public static SpellTraits of(Block block) { @@ -63,13 +111,43 @@ public final class SpellTraits { if (!(stack.hasTag() && stack.getTag().contains("spell_traits", NbtElement.COMPOUND_TYPE))) { return Optional.empty(); } - return readNbt(stack.getTag().getCompound("spell_traits")); + return fromNbt(stack.getTag().getCompound("spell_traits")); } - public static Optional readNbt(NbtCompound traits) { + public ItemStack applyTo(ItemStack stack) { + stack = stack.copy(); + stack.getOrCreateTag().put("spell_traits", toNbt()); + return stack; + } + + public static Optional fromNbt(NbtCompound traits) { return fromEntries(streamFromNbt(traits)); } + public static Optional fromJson(JsonObject traits) { + return fromEntries(streamFromJson(traits)); + } + + public static Optional fromPacket(PacketByteBuf buf) { + Map entries = new HashMap<>(); + int count = buf.readInt(); + if (count <= 0) { + return Optional.empty(); + } + + for (int i = 0; i < count; i++) { + Trait trait = Trait.REGISTRY.getOrDefault(buf.readIdentifier(), null); + float value = buf.readFloat(); + if (trait != null) { + entries.compute(trait, (k, v) -> v == null ? value : (v + value)); + } + } + if (entries.isEmpty()) { + return Optional.empty(); + } + return Optional.of(new SpellTraits(entries)); + } + public static Stream> streamFromNbt(NbtCompound traits) { return traits.getKeys().stream().map(key -> { Trait trait = Trait.REGISTRY.get(key.toUpperCase()); @@ -80,6 +158,16 @@ public final class SpellTraits { }); } + public static Stream> streamFromJson(JsonObject traits) { + return traits.entrySet().stream().map(entry -> { + Trait trait = Trait.REGISTRY.get(entry.getKey().toUpperCase()); + if (trait == null && !entry.getValue().isJsonPrimitive() && !entry.getValue().getAsJsonPrimitive().isNumber()) { + return null; + } + return Map.entry(trait, entry.getValue().getAsJsonPrimitive().getAsFloat()); + }); + } + public static Optional fromEntries(Stream> entries) { var result = collect(entries); @@ -89,6 +177,12 @@ public final class SpellTraits { return Optional.of(new SpellTraits(result)); } + static void combine(Map to, Map from) { + from.forEach((trait, value) -> { + to.compute(trait, (k, v) -> v == null ? value : (v + value)); + }); + } + static Map collect(Stream> entries) { return entries.filter(Objects::nonNull) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a + b, () -> new EnumMap<>(Trait.class))); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/TraitDiscovery.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/TraitDiscovery.java new file mode 100644 index 00000000..9bb82e3b --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/TraitDiscovery.java @@ -0,0 +1,115 @@ +package com.minelittlepony.unicopia.ability.magic.spell.trait; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.util.NbtSerialisable; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; + +public class TraitDiscovery implements NbtSerialisable { + private final Set unreadTraits = new HashSet<>(); + + private final Set traits = new HashSet<>(); + private final Map items = new HashMap<>(); + + private final Pony pony; + + public TraitDiscovery(Pony pony) { + this.pony = pony; + } + + public void clear() { + unreadTraits.clear(); + items.clear(); + traits.clear(); + pony.setDirty(); + } + + public void markRead() { + unreadTraits.clear(); + pony.setDirty(); + } + + public void unlock(Item item) { + if (item == Items.AIR) { + return; + } + SpellTraits traits = SpellTraits.of(item); + items.put(Registry.ITEM.getId(item), traits); + traits.entries().forEach(e -> { + if (this.traits.add(e.getKey().getId())) { + unreadTraits.add(e.getKey().getId()); + } + }); + pony.setDirty(); + } + + public SpellTraits getKnownTraits(Item item) { + return items.getOrDefault(Registry.ITEM.getId(item), SpellTraits.EMPTY); + } + + public void appendTooltip(ItemStack stack, @Nullable World world, List tooltip) { + getKnownTraits(stack.getItem()).appendTooltip(tooltip); + } + + @Override + public void toNBT(NbtCompound compound) { + NbtCompound disco = new NbtCompound(); + items.forEach((key, val) -> { + disco.put(key.toString(), val.toNbt()); + }); + compound.put("items", disco); + + NbtList a = new NbtList(); + this.traits.forEach(id -> a.add(NbtString.of(id.toString()))); + compound.put("traits", a); + + NbtList b = new NbtList(); + unreadTraits.forEach(id -> b.add(NbtString.of(id.toString()))); + compound.put("unreadTraits", b); + } + + @Override + public void fromNBT(NbtCompound compound) { + clear(); + NbtCompound disco = compound.getCompound("items"); + disco.getKeys().forEach(key -> { + Optional.ofNullable(Identifier.tryParse(key)).ifPresent(id -> { + SpellTraits.fromNbt(disco.getCompound(key)).ifPresent(val -> { + items.put(id, val); + }); + }); + }); + compound.getList("traits", NbtElement.STRING_TYPE).forEach(el -> { + Optional.ofNullable(Identifier.tryParse(el.asString())).ifPresent(this.traits::add); + }); + compound.getList("unreadTraits", NbtElement.STRING_TYPE).forEach(el -> { + Optional.ofNullable(Identifier.tryParse(el.asString())).ifPresent(this.unreadTraits::add); + }); + } + + public void copyFrom(TraitDiscovery old) { + clear(); + unreadTraits.addAll(old.unreadTraits); + traits.addAll(old.traits); + items.putAll(old.items); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/TraitLoader.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/TraitLoader.java index d9cbda2b..ee0c84c9 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/TraitLoader.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/TraitLoader.java @@ -42,7 +42,7 @@ public class TraitLoader extends SinglePreparationResourceReloader result.shouldCraftRecipe(world, (ServerPlayerEntity)this.inventory.player, recipe)) .map(recipe -> recipe.craft(input)) .ifPresentOrElse(gemSlot::setCrafted, gemSlot::setUncrafted); } @@ -202,6 +207,17 @@ public class SpellbookScreenHandler extends ScreenHandler { public interface SpellbookSlot {} + public class SpellbookInventory extends CraftingInventory { + + public SpellbookInventory(ScreenHandler handler, int width, int height) { + super(handler, width, height); + } + + public ItemStack getItemToModify() { + return gemSlot.getStack(); + } + } + public class InputSlot extends Slot implements SpellbookSlot { public InputSlot(Inventory inventory, int index, int xPosition, int yPosition) { super(inventory, index, xPosition, yPosition); @@ -217,8 +233,11 @@ public class SpellbookScreenHandler extends ScreenHandler { private Optional uncrafted = Optional.empty(); - public OutputSlot(PlayerEntity player, CraftingInventory input, Inventory inventory, int index, int x, int y) { + private final SpellbookInventory input; + + public OutputSlot(PlayerEntity player, SpellbookInventory input, Inventory inventory, int index, int x, int y) { super(player, input, inventory, index, x, y); + this.input = input; } public void setCrafted(ItemStack crafted) { @@ -247,7 +266,34 @@ public class SpellbookScreenHandler extends ScreenHandler { public void onTakeItem(PlayerEntity player, ItemStack stack) { if (uncrafted.isPresent()) { uncrafted = Optional.empty(); - super.onTakeItem(player, stack); + onCrafted(stack); + + Pony pony = Pony.of(player); + InventoryUtil.iterate(input).forEach(s -> { + pony.getDiscoveries().unlock(s.getItem()); + }); + + DefaultedList defaultedList = player.world.getRecipeManager().getRemainingStacks(URecipes.SPELLBOOK, input, player.world); + + for (int i = 0; i < defaultedList.size(); ++i) { + ItemStack itemStack = input.getStack(i); + ItemStack itemStack2 = defaultedList.get(i); + if (!itemStack.isEmpty()) { + input.removeStack(i, 1); + itemStack = input.getStack(i); + } + + if (!itemStack2.isEmpty()) { + if (itemStack.isEmpty()) { + input.setStack(i, itemStack2); + } else if (ItemStack.areItemsEqualIgnoreDamage(itemStack, itemStack2) && ItemStack.areTagsEqual(itemStack, itemStack2)) { + itemStack2.increment(itemStack.getCount()); + input.setStack(i, itemStack2); + } else if (!player.getInventory().insertStack(itemStack2)) { + player.dropItem(itemStack2, false); + } + } + } } } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index f5e4a29d..8cfc8cac 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -18,6 +18,7 @@ import com.minelittlepony.unicopia.ability.EarthPonyStompAbility; import com.minelittlepony.unicopia.ability.magic.Affine; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; +import com.minelittlepony.unicopia.ability.magic.spell.trait.TraitDiscovery; import com.minelittlepony.unicopia.advancement.UCriteria; import com.minelittlepony.unicopia.entity.PonyContainer; import com.minelittlepony.unicopia.entity.Living; @@ -77,6 +78,8 @@ public class Pony extends Living implements Transmittable, Copieab private final PlayerCharmTracker charms = new PlayerCharmTracker(this); private final PlayerAttributes attributes = new PlayerAttributes(this); private final PlayerCamera camera = new PlayerCamera(this); + private final TraitDiscovery discoveries = new TraitDiscovery(this); + private final ManaContainer mana; private final PlayerLevelStore levels; @@ -137,6 +140,10 @@ public class Pony extends Living implements Transmittable, Copieab UCriteria.PLAYER_CHANGE_RACE.trigger(entity); } + public TraitDiscovery getDiscoveries() { + return discoveries; + } + public MagicReserves getMagicalReserves() { return mana; } @@ -469,6 +476,7 @@ public class Pony extends Living implements Transmittable, Copieab compound.put("powers", powers.toNBT()); compound.put("gravity", gravity.toNBT()); compound.put("charms", charms.toNBT()); + compound.put("discoveries", discoveries.toNBT()); getSpellSlot().get(true).ifPresent(effect ->{ compound.put("effect", SpellType.toNBT(effect)); @@ -484,6 +492,7 @@ public class Pony extends Living implements Transmittable, Copieab powers.fromNBT(compound.getCompound("powers")); gravity.fromNBT(compound.getCompound("gravity")); charms.fromNBT(compound.getCompound("charms")); + discoveries.fromNBT(compound.getCompound("discoveries")); magicExhaustion = compound.getFloat("magicExhaustion"); @@ -500,6 +509,7 @@ public class Pony extends Living implements Transmittable, Copieab } oldPlayer.setSpell(null); setSpecies(oldPlayer.getSpecies()); + getDiscoveries().copyFrom(oldPlayer.getDiscoveries()); setDirty(); } diff --git a/src/main/java/com/minelittlepony/unicopia/item/URecipes.java b/src/main/java/com/minelittlepony/unicopia/item/URecipes.java index 5f9c4ce5..48ccf9a9 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/URecipes.java +++ b/src/main/java/com/minelittlepony/unicopia/item/URecipes.java @@ -1,39 +1,27 @@ package com.minelittlepony.unicopia.item; import com.google.gson.JsonArray; +import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe; +import com.minelittlepony.unicopia.ability.magic.spell.crafting.TraitRequirementRecipe; import net.fabricmc.fabric.api.loot.v1.FabricLootSupplier; import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback; import net.minecraft.loot.LootTable; import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.Recipe; import net.minecraft.recipe.RecipeSerializer; import net.minecraft.recipe.RecipeType; import net.minecraft.recipe.ShapelessRecipe; import net.minecraft.recipe.SpecialRecipeSerializer; import net.minecraft.util.Identifier; import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.registry.Registry; public interface URecipes { + RecipeType SPELLBOOK = RecipeType.register("unicopia:spellbook"); - RecipeSerializer ZAP_APPLE_SERIALIZER = register("crafting_zap_apple", new ZapAppleRecipe.Serializer()); - RecipeSerializer GLOWING_SERIALIZER = register("crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new)); - RecipeSerializer JAR_INSERT_SERIALIZER = register("jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new)); - - static > RecipeType register(final String id) { - return Registry.register(Registry.RECIPE_TYPE, new Identifier("unicopia", id), new RecipeType() { - @Override - public String toString() { - return id; - } - }); - } - - static , T extends Recipe> S register(String id, S serializer) { - return Registry.register(Registry.RECIPE_SERIALIZER, new Identifier("unicopia", id), serializer); - } - + RecipeSerializer ZAP_APPLE_SERIALIZER = RecipeSerializer.register("unicopia:crafting_zap_apple", new ZapAppleRecipe.Serializer()); + RecipeSerializer GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new)); + RecipeSerializer JAR_INSERT_SERIALIZER = RecipeSerializer.register("unicopia:jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new)); + RecipeSerializer TRAIT_REQUIREMENT = RecipeSerializer.register("unicopia:spellbook/crafting", new TraitRequirementRecipe.Serializer()); static DefaultedList getIngredients(JsonArray json) { DefaultedList defaultedList = DefaultedList.of(); diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinItem.java b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinItem.java index 54cb373c..58b12909 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinItem.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinItem.java @@ -7,6 +7,8 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.item.toxin.ToxicHolder; import net.minecraft.client.MinecraftClient; @@ -21,5 +23,8 @@ abstract class MixinItem implements ToxicHolder { @Inject(method = "appendTooltip", at = @At("RETURN")) private void onAppendTooltip(ItemStack stack, @Nullable World world, List tooltip, TooltipContext context, CallbackInfo into) { getToxic().ifPresent(t -> t.getAilmentFor(MinecraftClient.getInstance().player).appendTooltip(tooltip, context)); + if (MinecraftClient.getInstance().player != null) { + Pony.of(MinecraftClient.getInstance().player).getDiscoveries().appendTooltip(stack, world, tooltip); + } } } diff --git a/src/main/java/com/minelittlepony/unicopia/util/InventoryUtil.java b/src/main/java/com/minelittlepony/unicopia/util/InventoryUtil.java new file mode 100644 index 00000000..7969f9f5 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/util/InventoryUtil.java @@ -0,0 +1,22 @@ +package com.minelittlepony.unicopia.util; + +import com.google.common.collect.AbstractIterator; + +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; + +public interface InventoryUtil { + static Iterable iterate(Inventory inventory) { + return () -> new AbstractIterator<>() { + private int slot = 0; + + @Override + protected ItemStack computeNext() { + if (slot >= inventory.size()) { + return endOfData(); + } + return inventory.getStack(slot++); + } + }; + } +}