diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java index f3b13455..8a1e0a05 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/trait/Trait.java @@ -114,9 +114,11 @@ public enum Trait implements CommandArgumentEnum { } public Text getName() { - return Text.translatable("gui.unicopia.trait.label", - Text.translatable("trait." + getId().getNamespace() + "." + getId().getPath() + ".name") - ).formatted(Formatting.YELLOW); + return Text.translatable("gui.unicopia.trait.label", getShortName()).formatted(Formatting.YELLOW); + } + + public Text getShortName() { + return Text.translatable("trait." + getId().getNamespace() + "." + getId().getPath() + ".name"); } public List getTooltipLines() { diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/ParagraphWrappingVisitor.java b/src/main/java/com/minelittlepony/unicopia/client/gui/ParagraphWrappingVisitor.java index 9051dbf5..0a947e9c 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/ParagraphWrappingVisitor.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/ParagraphWrappingVisitor.java @@ -66,13 +66,19 @@ public class ParagraphWrappingVisitor implements StyledVisitor { } // append the segment to the line that's being built - if (currentLineCollectedLength > 0) { + if (currentLineCollectedLength > 0 && s.startsWith(" ")) { currentLine.append(" "); currentLineCollectedLength += handler.getWidth(" "); } currentLine.append(fragment); currentLineCollectedLength += grabbedWidth; + // append the segment to the line that's being built + if (currentLineCollectedLength > 0 && s.endsWith(" ")) { + currentLine.append(" "); + currentLineCollectedLength += handler.getWidth(" "); + } + if (newline >= 0) { advance(); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/ClientChapters.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/ClientChapters.java index bf99250e..767afb43 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/ClientChapters.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/ClientChapters.java @@ -2,6 +2,8 @@ package com.minelittlepony.unicopia.client.gui.spellbook; import java.util.*; import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.*; +import com.minelittlepony.unicopia.client.gui.spellbook.element.DynamicContent; + import net.minecraft.network.PacketByteBuf; import net.minecraft.util.*; diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/IngredientTree.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/IngredientTree.java index 950410ad..831ea7ca 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/IngredientTree.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/IngredientTree.java @@ -23,7 +23,7 @@ import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; -class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder { +public class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder { private final List entries = new ArrayList<>(); private Optional result = Optional.empty(); diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/PageElement.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/PageElement.java deleted file mode 100644 index 040f0343..00000000 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/PageElement.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.minelittlepony.unicopia.client.gui.spellbook; - -import java.util.ArrayList; -import java.util.List; - -import com.minelittlepony.common.client.gui.IViewRoot; -import com.minelittlepony.common.client.gui.dimension.Bounds; -import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell; -import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe; -import com.minelittlepony.unicopia.client.gui.ParagraphWrappingVisitor; -import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Drawable; -import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow; -import com.minelittlepony.unicopia.entity.player.Pony; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import net.minecraft.util.*; - -interface PageElement extends Drawable { - @Override - default void draw(DrawContext context, int mouseX, int mouseY, IViewRoot container) { - - } - - Bounds bounds(); - - default Flow flow() { - return Flow.NONE; - } - - default boolean isInline() { - return flow() == Flow.NONE; - } - - default boolean isFloating() { - return !isInline(); - } - - default void compile(int y, IViewRoot Container) {} - - static PageElement read(DynamicContent.Page page, PacketByteBuf buffer) { - byte type = buffer.readByte(); - return (switch (type) { - case 0 -> new Image(buffer.readIdentifier(), boundsFromBuffer(buffer), buffer.readEnumConstant(Flow.class)); - case 1 -> new Recipe(page, buffer.readIdentifier(), Bounds.empty()); - case 2 -> new Stack(page, IngredientWithSpell.fromPacket(buffer), boundsFromBuffer(buffer)); - case 3 -> new TextBlock(page, buffer.readText()); - default -> throw new IllegalArgumentException("Unexpected value: " + type); - }); - } - - private static Bounds boundsFromBuffer(PacketByteBuf buffer) { - return new Bounds(buffer.readInt(), buffer.readInt(), buffer.readInt(), buffer.readInt()); - } - - record Image( - Identifier texture, - Bounds bounds, - Flow flow) implements PageElement { - @Override - public void draw(DrawContext context, int mouseX, int mouseY, IViewRoot container) { - context.drawTexture(texture, 0, 0, 0, 0, 0, bounds().width, bounds().height, bounds().width, bounds().height); - } - } - - class TextBlock implements PageElement { - private final DynamicContent.Page page; - - private final Text unwrappedText; - private final List wrappedText = new ArrayList<>(); - private final Bounds bounds = Bounds.empty(); - - public TextBlock(DynamicContent.Page page,Text text) { - this.page = page; - unwrappedText = text; - } - - @Override - public void compile(int y, IViewRoot container) { - wrappedText.clear(); - ParagraphWrappingVisitor visitor = new ParagraphWrappingVisitor( - yPosition -> page.getLineLimitAt(y + yPosition), - (line, yPosition) -> wrappedText.add(new Line(line, page.getLeftMarginAt(y + yPosition))) - ); - unwrappedText.visit(visitor, Style.EMPTY); - visitor.forceAdvance(); - bounds.height = MinecraftClient.getInstance().textRenderer.fontHeight * (wrappedText.size()); - } - - @Override - public void draw(DrawContext context, int mouseX, int mouseY, IViewRoot container) { - TextRenderer font = MinecraftClient.getInstance().textRenderer; - boolean needsMoreXp = page.getLevel() < 0 || Pony.of(MinecraftClient.getInstance().player).getLevel().get() < page.getLevel(); - MatrixStack matrices = context.getMatrices(); - matrices.push(); - wrappedText.forEach(line -> { - context.drawText(font, needsMoreXp ? line.text().copy().formatted(Formatting.OBFUSCATED) : line.text().copy(), line.x(), 0, 0, false); - matrices.translate(0, font.fontHeight, 0); - }); - matrices.pop(); - } - - @Override - public Bounds bounds() { - return bounds; - } - - @Override - public Flow flow() { - return Flow.NONE; - } - - private record Line(Text text, int x) { } - } - - record Recipe (DynamicContent.Page page, Identifier id, Bounds bounds) implements PageElement { - @Override - public void compile(int y, IViewRoot container) { - if (container instanceof SpellbookScreen book) { - bounds().left = book.getX(); - bounds().top = book.getY(); - } - MinecraftClient.getInstance().world.getRecipeManager().get(id).ifPresent(recipe -> { - if (recipe instanceof SpellbookRecipe spellRecipe) { - - boolean needsMoreXp = page.getLevel() < 0 || Pony.of(MinecraftClient.getInstance().player).getLevel().get() < page.getLevel(); - - IngredientTree tree = new IngredientTree( - bounds().left + page().getBounds().left, - bounds().top + page().getBounds().top + y + 10, - page().getBounds().width - 20 - ).obfuscateResult(needsMoreXp); - spellRecipe.buildCraftingTree(tree); - bounds.height = tree.build(container) - 10; - } - }); - } - } - - record Stack (DynamicContent.Page page, IngredientWithSpell ingredient, Bounds bounds) implements PageElement { - @Override - public void compile(int y, IViewRoot container) { - int xx = 0, yy = 0; - if (container instanceof SpellbookScreen book) { - xx = book.getX(); - yy = book.getY(); - } - IngredientTree tree = new IngredientTree( - bounds().left + xx + page().getBounds().left, - bounds().top + yy + page().getBounds().top + y + 10, - 30 - ); - tree.input(ingredient.getMatchingStacks()); - bounds.height = tree.build(container) - 10; - } - } -} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/DynamicContent.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/DynamicContent.java similarity index 97% rename from src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/DynamicContent.java rename to src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/DynamicContent.java index 3a5cc878..1f9ac36a 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/DynamicContent.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/DynamicContent.java @@ -1,10 +1,11 @@ -package com.minelittlepony.unicopia.client.gui.spellbook; +package com.minelittlepony.unicopia.client.gui.spellbook.element; import java.util.*; import com.minelittlepony.common.client.gui.IViewRoot; import com.minelittlepony.common.client.gui.dimension.Bounds; import com.minelittlepony.unicopia.client.gui.DrawableUtil; +import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen; import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Content; import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Drawable; import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow; diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Image.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Image.java new file mode 100644 index 00000000..090de1f7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Image.java @@ -0,0 +1,18 @@ +package com.minelittlepony.unicopia.client.gui.spellbook.element; + +import com.minelittlepony.common.client.gui.IViewRoot; +import com.minelittlepony.common.client.gui.dimension.Bounds; +import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow; + +import net.minecraft.client.gui.DrawContext; +import net.minecraft.util.Identifier; + +record Image( + Identifier texture, + Bounds bounds, + Flow flow) implements PageElement { + @Override + public void draw(DrawContext context, int mouseX, int mouseY, IViewRoot container) { + context.drawTexture(texture, 0, 0, 0, 0, 0, bounds().width, bounds().height, bounds().width, bounds().height); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/PageElement.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/PageElement.java new file mode 100644 index 00000000..6af9020d --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/PageElement.java @@ -0,0 +1,77 @@ +package com.minelittlepony.unicopia.client.gui.spellbook.element; + +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.google.common.base.Suppliers; +import com.minelittlepony.common.client.gui.IViewRoot; +import com.minelittlepony.common.client.gui.dimension.Bounds; +import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell; +import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; +import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; +import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Drawable; +import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.registry.Registries; +import net.minecraft.text.Text; + +public interface PageElement extends Drawable { + @Override + default void draw(DrawContext context, int mouseX, int mouseY, IViewRoot container) { + + } + + Bounds bounds(); + + default Flow flow() { + return Flow.NONE; + } + + default boolean isInline() { + return flow() == Flow.NONE; + } + + default boolean isFloating() { + return !isInline(); + } + + default void compile(int y, IViewRoot Container) {} + + static PageElement read(DynamicContent.Page page, PacketByteBuf buffer) { + byte type = buffer.readByte(); + return switch (type) { + case 0 -> new Image(buffer.readIdentifier(), boundsFromBuffer(buffer), buffer.readEnumConstant(Flow.class)); + case 1 -> new Recipe(page, buffer.readIdentifier(), Bounds.empty()); + case 2 -> new Stack(page, IngredientWithSpell.fromPacket(buffer), boundsFromBuffer(buffer)); + case 3 -> new TextBlock(page, List.of(Suppliers.ofInstance(buffer.readText()))); + case 4 -> new TextBlock(page, buffer.readList(b -> { + int count = b.readVarInt(); + byte t = b.readByte(); + return switch (t) { + case 1 -> formatLine(capture(b.readIdentifier(), id -> { + return Registries.ITEM.get(id).getDefaultStack().getName(); + }), "item", count); + case 2 -> formatLine(Trait.fromId(b.readIdentifier()).orElseThrow()::getShortName, "trait", count); + case 3 -> Suppliers.ofInstance(b.readText()); + case 4 -> formatLine(SpellType.getKey(b.readIdentifier())::getName, "spell", count); + default -> throw new IllegalArgumentException("Unexpected value: " + t); + }; + })); + default -> throw new IllegalArgumentException("Unexpected value: " + type); + }; + } + + private static Supplier capture(T t, Function func) { + return () -> func.apply(t); + } + + private static Supplier formatLine(Supplier line, String kind, int count) { + return () -> Text.translatable("gui.unicopia.spellbook.page.requirements.entry." + kind, count, line.get()); + } + + private static Bounds boundsFromBuffer(PacketByteBuf buffer) { + return new Bounds(buffer.readInt(), buffer.readInt(), buffer.readInt(), buffer.readInt()); + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Recipe.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Recipe.java new file mode 100644 index 00000000..79264fa3 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Recipe.java @@ -0,0 +1,35 @@ +package com.minelittlepony.unicopia.client.gui.spellbook.element; + +import com.minelittlepony.common.client.gui.IViewRoot; +import com.minelittlepony.common.client.gui.dimension.Bounds; +import com.minelittlepony.unicopia.ability.magic.spell.crafting.SpellbookRecipe; +import com.minelittlepony.unicopia.client.gui.spellbook.IngredientTree; +import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen; +import com.minelittlepony.unicopia.entity.player.Pony; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.Identifier; + +record Recipe (DynamicContent.Page page, Identifier id, Bounds bounds) implements PageElement { + @Override + public void compile(int y, IViewRoot container) { + if (container instanceof SpellbookScreen book) { + bounds().left = book.getX(); + bounds().top = book.getY(); + } + MinecraftClient.getInstance().world.getRecipeManager().get(id).ifPresent(recipe -> { + if (recipe instanceof SpellbookRecipe spellRecipe) { + + boolean needsMoreXp = page.getLevel() < 0 || Pony.of(MinecraftClient.getInstance().player).getLevel().get() < page.getLevel(); + + IngredientTree tree = new IngredientTree( + bounds().left + page().getBounds().left, + bounds().top + page().getBounds().top + y + 10, + page().getBounds().width - 20 + ).obfuscateResult(needsMoreXp); + spellRecipe.buildCraftingTree(tree); + bounds.height = tree.build(container) - 10; + } + }); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Stack.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Stack.java new file mode 100644 index 00000000..1113d668 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/Stack.java @@ -0,0 +1,25 @@ +package com.minelittlepony.unicopia.client.gui.spellbook.element; + +import com.minelittlepony.common.client.gui.IViewRoot; +import com.minelittlepony.common.client.gui.dimension.Bounds; +import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell; +import com.minelittlepony.unicopia.client.gui.spellbook.IngredientTree; +import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookScreen; + +record Stack (DynamicContent.Page page, IngredientWithSpell ingredient, Bounds bounds) implements PageElement { + @Override + public void compile(int y, IViewRoot container) { + int xx = 0, yy = 0; + if (container instanceof SpellbookScreen book) { + xx = book.getX(); + yy = book.getY(); + } + IngredientTree tree = new IngredientTree( + bounds().left + xx + page().getBounds().left, + bounds().top + yy + page().getBounds().top + y + 10, + 30 + ); + tree.input(ingredient.getMatchingStacks()); + bounds.height = tree.build(container) - 10; + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/TextBlock.java b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/TextBlock.java new file mode 100644 index 00000000..79867f24 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/spellbook/element/TextBlock.java @@ -0,0 +1,72 @@ +package com.minelittlepony.unicopia.client.gui.spellbook.element; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import com.minelittlepony.common.client.gui.IViewRoot; +import com.minelittlepony.common.client.gui.dimension.Bounds; +import com.minelittlepony.unicopia.client.gui.ParagraphWrappingVisitor; +import com.minelittlepony.unicopia.container.SpellbookChapterLoader.Flow; +import com.minelittlepony.unicopia.entity.player.Pony; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +class TextBlock implements PageElement { + private final DynamicContent.Page page; + + private final List wrappedText = new ArrayList<>(); + private final Bounds bounds = Bounds.empty(); + private final List> uncompiledLines; + + public TextBlock(DynamicContent.Page page, List> uncompiledLines) { + this.page = page; + this.uncompiledLines = uncompiledLines; + } + + @Override + public void compile(int y, IViewRoot container) { + wrappedText.clear(); + ParagraphWrappingVisitor visitor = new ParagraphWrappingVisitor( + yPosition -> page.getLineLimitAt(y + yPosition), + (line, yPosition) -> wrappedText.add(new Line(line, page.getLeftMarginAt(y + yPosition))) + ); + uncompiledLines.forEach(line -> { + line.get().visit(visitor, Style.EMPTY); + visitor.advance(); + }); + visitor.forceAdvance(); + bounds.height = MinecraftClient.getInstance().textRenderer.fontHeight * (wrappedText.size()); + } + + @Override + public void draw(DrawContext context, int mouseX, int mouseY, IViewRoot container) { + TextRenderer font = MinecraftClient.getInstance().textRenderer; + boolean needsMoreXp = page.getLevel() < 0 || Pony.of(MinecraftClient.getInstance().player).getLevel().get() < page.getLevel(); + MatrixStack matrices = context.getMatrices(); + matrices.push(); + wrappedText.forEach(line -> { + context.drawText(font, needsMoreXp ? line.text().copy().formatted(Formatting.OBFUSCATED) : line.text().copy(), line.x(), 0, 0, false); + matrices.translate(0, font.fontHeight, 0); + }); + matrices.pop(); + } + + @Override + public Bounds bounds() { + return bounds; + } + + @Override + public Flow flow() { + return Flow.NONE; + } + + private record Line(Text text, int x) { } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/container/SpellbookChapterLoader.java b/src/main/java/com/minelittlepony/unicopia/container/SpellbookChapterLoader.java index 20a928d6..b7911f05 100644 --- a/src/main/java/com/minelittlepony/unicopia/container/SpellbookChapterLoader.java +++ b/src/main/java/com/minelittlepony/unicopia/container/SpellbookChapterLoader.java @@ -12,6 +12,7 @@ import com.minelittlepony.common.client.gui.dimension.Bounds; import com.minelittlepony.unicopia.Debug; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.ability.magic.spell.crafting.IngredientWithSpell; +import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.*; import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.network.MsgServerResources; @@ -129,7 +130,7 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab this( Text.Serializer.fromJson(json.get("title")), JsonHelper.getInt(json, "level", 0), - new ArrayList() + new ArrayList<>() ); JsonHelper.getArray(json, "elements", new JsonArray()).forEach(element -> { elements.add(Element.read(element)); @@ -164,11 +165,19 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab } } - record Recipe (Identifier id) implements Element { + record Multi(int count, Element element) implements Element { @Override public void toBuffer(PacketByteBuf buffer) { - buffer.writeByte(1); - buffer.writeIdentifier(id); + buffer.writeVarInt(count); + element.toBuffer(buffer); + } + } + + record Id(byte id, Identifier value) implements Element { + @Override + public void toBuffer(PacketByteBuf buffer) { + buffer.writeByte(id); + buffer.writeIdentifier(value); } } @@ -189,6 +198,31 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab } } + record Ingredients(List entries) implements Element { + static Element loadIngredient(JsonObject json) { + int count = JsonHelper.getInt(json, "count", 1); + if (json.has("item")) { + return new Multi(count, new Id((byte)1, Identifier.tryParse(json.get("item").getAsString()))); + } + + if (json.has("trait")) { + return new Multi(count, new Id((byte)2, Trait.fromId(json.get("trait").getAsString()).orElseThrow().getId())); + } + + if (json.has("spell")) { + return new Multi(count, new Id((byte)4, Identifier.tryParse(json.get("spell").getAsString()))); + } + + return new Multi(count, new TextBlock(Text.Serializer.fromJson(json.get("text")))); + } + + @Override + public void toBuffer(PacketByteBuf buffer) { + buffer.writeByte(4); + buffer.writeCollection(entries, (b, c) -> c.toBuffer(b)); + } + } + static void write(PacketByteBuf buffer, Element element) { element.toBuffer(buffer); } @@ -204,13 +238,22 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab Flow.valueOf(JsonHelper.getString(el, "flow", "RIGHT")) ); } + if (el.has("recipe")) { - return new Recipe(new Identifier(JsonHelper.getString(el, "recipe"))); + return new Id((byte)1, new Identifier(JsonHelper.getString(el, "recipe"))); } if (el.has("item")) { return new Stack(IngredientWithSpell.fromJson(el.get("item")), boundsFromJson(el)); } + + if (el.has("ingredients")) { + return new Ingredients(JsonHelper.getArray(el, "ingredients").asList().stream() + .map(JsonElement::getAsJsonObject) + .map(Ingredients::loadIngredient) + .toList() + ); + } } return new TextBlock(Text.Serializer.fromJson(json)); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/SpellbookEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/SpellbookEntity.java index 1d40b374..28f8be8b 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/SpellbookEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/SpellbookEntity.java @@ -170,8 +170,6 @@ public class SpellbookEntity extends MobEntity { } }); - System.out.println(activeTicks); - boolean daytime = MeteorlogicalUtil.getSkyAngle(getWorld()) < 1; if (daytime != prevDaytime) { prevDaytime = daytime; diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index abd2fc6d..596ec0b3 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -461,6 +461,9 @@ "gui.unicopia.spellbook.page.recipes": "Recipes", "gui.unicopia.spellbook.page.recipes.empty": "0 Recipes Unlocked", "gui.unicopia.spellbook.page.mana": "Mana", + "gui.unicopia.spellbook.page.requirements.entry.item": "- %1$sx %2$s", + "gui.unicopia.spellbook.page.requirements.entry.trait": "- At least %1$sx %2$s trait", + "gui.unicopia.spellbook.page.requirements.entry.spell": "- %1$sx %2$s gem", "gui.unicopia.action.spells_cleared": "Removed all spells", "gui.unicopia.action.no_spells_cleared": "You have no active spells", diff --git a/src/main/resources/data/unicopia/spellbook/chapters/air_magic.json b/src/main/resources/data/unicopia/spellbook/chapters/air_magic.json index af132f48..9c416f4b 100644 --- a/src/main/resources/data/unicopia/spellbook/chapters/air_magic.json +++ b/src/main/resources/data/unicopia/spellbook/chapters/air_magic.json @@ -75,8 +75,14 @@ "elements": [ { "recipe": "unicopia:spells/catapult" }, "Requires:", - "- 1x flame gem\n- At least 9x focus trait\n- At least 9x air trait", - "* One can add apply force by the strength trait" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:flame" }, + { "count": 9, "trait": "unicopia:focus" }, + { "count": 9, "trait": "unicopia:air" } + ] + }, + "* One can add apply more force by adding the strength trait" ] }, { @@ -95,7 +101,13 @@ "elements": [ { "recipe": "unicopia:spells/bubble" }, "Requires:", - "- 1x catapult gem\n- At least 9x water trait\n- At least 9x air trait" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:catapult" }, + { "count": 9, "trait": "unicopia:water" }, + { "count": 9, "trait": "unicopia:air" } + ] + } ] }, { @@ -147,7 +159,15 @@ "elements": [ { "recipe": "unicopia:spells/feather_fall" }, "Requires:", - "- 1x protection gem\n- At least 20x knowlege trait\n- At least 10x life trait\n- At least 10x generosity trait\n- At least 4x chaos trait" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:shield" }, + { "count": 20, "trait": "unicopia:knowledge" }, + { "count": 10, "trait": "unicopia:life" }, + { "count": 10, "trait": "unicopia:generosity" }, + { "count": 4, "trait": "unicopia:chaos" } + ] + } ] }, { diff --git a/src/main/resources/data/unicopia/spellbook/chapters/crystal_heart.json b/src/main/resources/data/unicopia/spellbook/chapters/crystal_heart.json index 4625fa99..707f95b8 100644 --- a/src/main/resources/data/unicopia/spellbook/chapters/crystal_heart.json +++ b/src/main/resources/data/unicopia/spellbook/chapters/crystal_heart.json @@ -59,7 +59,13 @@ "text": "Aasa sasa fwefsd q43rgfd wqklmsdfl as, klasn.", "obfuscated": "true" }, "Building Materials:", - "- 2x end rod\n- 20x diamond block\n- 1x crystal heart" + { + "ingredients": [ + { "count": 2, "item": "minecraft:end_rod" }, + { "count": 20, "item": "minecraft:diamond_block" }, + { "count": 1, "item": "unicopia:crystal_heart" } + ] + } ] }, { diff --git a/src/main/resources/data/unicopia/spellbook/chapters/dark_magic.json b/src/main/resources/data/unicopia/spellbook/chapters/dark_magic.json index 03cda40e..1d888807 100644 --- a/src/main/resources/data/unicopia/spellbook/chapters/dark_magic.json +++ b/src/main/resources/data/unicopia/spellbook/chapters/dark_magic.json @@ -61,8 +61,20 @@ "elements": [ { "recipe": "unicopia:spells/vortex" }, "Requires:", - "- 1x protection gem\n- At least 10x strength trait\n- At least 8x knowledge trait\n- At least 9x air trait", - "+ 10x knowledge to narrow the effect's range to items\n+ add focus trait to increase duration\n+ add power trait to increase range" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:shield" }, + { "count": 10, "trait": "unicopia:strength" }, + { "count": 8, "trait": "unicopia:knowledge" }, + { "count": 9, "trait": "unicopia:air" } + ] + }, + { + "ingredients": [ + { "text": "+ 10x knowledge to narrow the effect's range to items" }, + { "text": "+ add focus trait to increase duration\n+ add power trait to increase range" } + ] + } ] }, { @@ -170,7 +182,13 @@ "elements": [ { "recipe": "unicopia:spells/transformation" }, "Requires:", - "- At least 18x knowledge trait\n- At least 10x life trait\n- At least 4x chaos trait" + { + "ingredients": [ + { "count": 18, "trait": "unicopia:knowledge" }, + { "count": 10, "trait": "unicopia:life" }, + { "count": 4, "trait": "unicopia:chaos" } + ] + } ] }, { @@ -189,7 +207,14 @@ "elements": [ { "recipe": "unicopia:spells/reveal" }, "Requires:", - "- A protection gem\n- At least 18x knowledge trait\n- At least 1x life trait\n- At least 4x harmony trait", + { + "ingredients": [ + { "count": 1, "spell": "unicopia:shield" }, + { "count": 18, "trait": "unicopia:knowledge" }, + { "count": 1, "trait": "unicopia:life" }, + { "count": 4, "trait": "unicopia:order" } + ] + }, "* Increase range by adding the power trait" ] }, @@ -258,7 +283,14 @@ "elements": [ { "recipe": "unicopia:spells/arcane_protection" }, "Requires:", - "- A protection gem\n- At least 10x strength trait\n- At least 18x knowledge trait\n- At least 1x darkness trait", + { + "ingredients": [ + { "count": 1, "spell": "unicopia:shield" }, + { "count": 10, "trait": "unicopia:strength" }, + { "count": 18, "trait": "unicopia:knowledge" }, + { "count": 1, "trait": "unicopia:darkness" } + ] + }, "* Increase range by adding the power trait" ] }, @@ -277,7 +309,13 @@ "elements": [ { "recipe": "unicopia:spells/displacement" }, "Requires:", - "- 1x gemstone\n- At least 18x knowledge trait\n- At least 10x chaos trait" + { + "ingredients": [ + { "count": 1, "item": "unicopia:gemstone" }, + { "count": 18, "trait": "unicopia:knowledge" }, + { "count": 10, "trait": "unicopia:chaos" } + ] + } ] }, { @@ -311,7 +349,14 @@ "elements": [ { "recipe": "unicopia:spells/mimic" }, "Requires:", - "- A transmutation gem\n- At least 19x knowledge trait\n- At least 10x life trait\n- At least 4x chaos trait", + { + "ingredients": [ + { "count": 1, "spell": "unicopia:transformation" }, + { "count": 19, "trait": "unicopia:knowledge" }, + { "count": 10, "trait": "unicopia:life" }, + { "count": 4, "trait": "unicopia:chaos" } + ] + }, "* Add the focus trait to increase the effect's duration" ] }, @@ -381,7 +426,14 @@ "elements": [ { "recipe": "unicopia:spells/dispel_evil" }, "Requires:", - "- An arcane protection gem\n- A displacement gem\n- At least 1x kindness trait\n- At least 1x power trait", + { + "ingredients": [ + { "count": 1, "spell": "unicopia:arcane_protection" }, + { "count": 1, "spell": "unicopia:displacement" }, + { "count": 1, "trait": "unicopia:kindness" }, + { "count": 1, "trait": "unicopia:power" } + ] + }, "* Add the power trait to increase the effect's range" ] } diff --git a/src/main/resources/data/unicopia/spellbook/chapters/fire_magic.json b/src/main/resources/data/unicopia/spellbook/chapters/fire_magic.json index a2652e75..d7014015 100644 --- a/src/main/resources/data/unicopia/spellbook/chapters/fire_magic.json +++ b/src/main/resources/data/unicopia/spellbook/chapters/fire_magic.json @@ -37,7 +37,11 @@ "elements": [ { "recipe": "unicopia:spells/scorch" }, "Requires:", - "- At least 10x fire trait" + { + "ingredients": [ + { "count": 10, "trait": "unicopia:fire" } + ] + } ] }, { @@ -56,7 +60,13 @@ "elements": [ { "recipe": "unicopia:spells/flame" }, "Requires:", - "- 1x gemstone\n- At least 15x fire trait\n- A gem with scorch" + { + "ingredients": [ + { "count": 1, "item": "unicopia:gemstone" }, + { "count": 1, "spell": "unicopia:scorch" }, + { "count": 15, "trait": "unicopia:fire" } + ] + } ] }, { @@ -123,7 +133,13 @@ "elements": [ { "recipe": "unicopia:spells/fire_bolt" }, "Requires:", - "- At least 9x focus for control and flight\n- 30x fire trait for energy\n- A gem with flame" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:flame" }, + { "count": 9, "trait": "unicopia:focus" }, + { "count": 30, "trait": "unicopia:fire" } + ] + } ] }, { @@ -234,8 +250,15 @@ "elements": [ { "recipe": "unicopia:spells/shield" }, "Requires:", - "- 1x gemstone\n- At least 10x strength trait\n- At least 6x focus trait\n- At least 10x power trait", - "\n+ add power trait to increase effect range" + { + "ingredients": [ + { "count": 1, "item": "unicopia:gemstone" }, + { "count": 6, "trait": "unicopia:focus" }, + { "count": 10, "trait": "unicopia:strength" }, + { "count": 10, "trait": "unicopia:power" } + ] + }, + "+ add power trait to increase effect range" ] }, { diff --git a/src/main/resources/data/unicopia/spellbook/chapters/ice_magic.json b/src/main/resources/data/unicopia/spellbook/chapters/ice_magic.json index 0378214a..1c05cb6b 100644 --- a/src/main/resources/data/unicopia/spellbook/chapters/ice_magic.json +++ b/src/main/resources/data/unicopia/spellbook/chapters/ice_magic.json @@ -37,7 +37,11 @@ "elements": [ { "recipe": "unicopia:spells/frost" }, "Requires:", - "- At least 15x ice trait" + { + "ingredients": [ + { "count": 15, "trait": "unicopia:ice" } + ] + } ] }, { @@ -56,7 +60,13 @@ "elements": [ { "recipe": "unicopia:spells/chilling_breath" }, "Requires:", - "- A frost gem\n- At least 5x ice trait\n- At least 10x knowledge trait" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:frost" }, + { "count": 5, "trait": "unicopia:ice" }, + { "count": 10, "trait": "unicopia:knowledge" } + ] + } ] }, { @@ -88,17 +98,21 @@ }, { "title": "", - "level": 6, + "level": -1, "elements": [] }, { "title": "", - "level": -1, + "level": 6, "elements": [ "Ice Spell II", "Creates a cooling affect up to a radius of 3 hooves from any surfaces it touches.", "Requires:", - "- At least 15x cold trait", + { + "ingredients": [ + { "count": 15, "trait": "unicopia:ice" } + ] + }, { "x": 115, "y": -20, "width": 32, "height": 32, "texture": "minecraft:textures/item/snowball.png" }, { "x": 115, "y": -20, "width": 16, "height": 16, "texture": "unicopia:textures/gui/trait/ice.png" } ] @@ -129,7 +143,14 @@ "elements": [ { "recipe": "unicopia:spells/light" }, "Requires:", - "- A fire bolt gem\n- At least 10x focus trait\n- At least 30x life trait\n- At least 30x ice trait", + { + "ingredients": [ + { "count": 1, "spell": "unicopia:fire_bolt" }, + { "count": 10, "trait": "unicopia:focus" }, + { "count": 30, "trait": "unicopia:life" }, + { "count": 30, "trait": "unicopia:ice" } + ] + }, "* By adding more focus you can extend the duration of the spell" ] }, @@ -272,9 +293,19 @@ "elements": [ { "recipe": "unicopia:spells/hydrophobic" }, "Requires:", - "- A gem with frost\n- A gem with protection\n- At least 6x focus trait", - "* By adding more focus you can extend the duration of the spell", - "* Add the generosity trait to tie this spell to a location rather than a user" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:frost" }, + { "count": 1, "spell": "unicopia:shield" }, + { "count": 6, "trait": "unicopia:focus" } + ] + }, + { + "ingredients": [ + { "text": "* By adding more focus you can extend the duration of the spell" }, + { "text": "* Add the generosity trait to tie this spell to a location rather than a user" } + ] + } ] } ] diff --git a/src/main/resources/data/unicopia/spellbook/chapters/the_otherworldly.json b/src/main/resources/data/unicopia/spellbook/chapters/the_otherworldly.json index dcca3438..aee0fb23 100644 --- a/src/main/resources/data/unicopia/spellbook/chapters/the_otherworldly.json +++ b/src/main/resources/data/unicopia/spellbook/chapters/the_otherworldly.json @@ -35,7 +35,13 @@ "elements": [ { "recipe": "unicopia:spells/siphoning" }, "Requires:", - "- 1x inferno gem\n- At least 10x poison trait\n- At least 8x blood trait" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:infernal" }, + { "count": 10, "trait": "unicopia:poison" }, + { "count": 8, "trait": "unicopia:blood" } + ] + } ] }, { @@ -59,7 +65,17 @@ "elements": [ { "recipe": "unicopia:spells/necromancy" }, "Requires:", - "- 1x life sapping gem\n- At least 10x strength trait\n- At least 8x knowledge trait\n- At least 8x chaos trait\n- At least 19x darkness trait\n- At least 9x poison trait\n- At least 10x blood trait" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:siphoning" }, + { "count": 10, "trait": "unicopia:strength" }, + { "count": 8, "trait": "unicopia:knowledge" }, + { "count": 8, "trait": "unicopia:chaos" }, + { "count": 19, "trait": "unicopia:darkness" }, + { "count": 9, "trait": "unicopia:poison" }, + { "count": 10, "trait": "unicopia:blood" } + ] + } ] }, { @@ -78,7 +94,15 @@ "elements": [ { "recipe": "unicopia:spells/dark_vortex" }, "Requires:", - "- 1x arcane attraction gem\n- At least 10x strength trait\n- At least 8x knowledge trait\n- At least 8x chaos trait\n- At least 9x darkness trait" + { + "ingredients": [ + { "count": 1, "spell": "unicopia:vortex" }, + { "count": 10, "trait": "unicopia:strength" }, + { "count": 8, "trait": "unicopia:knowledge" }, + { "count": 8, "trait": "unicopia:chaos" }, + { "count": 9, "trait": "unicopia:darkness" } + ] + } ] }, { @@ -97,7 +121,15 @@ "elements": [ { "recipe": "unicopia:spells/portal" }, "Requires:", - "- 1x gemstone\n- 1x displacement gem\n- 1x dark vortext gem\n- At least 18x knowledge trait\n- At least 20x chaos trait" + { + "ingredients": [ + { "count": 1, "item": "unicopia:gemstone" }, + { "count": 1, "spell": "unicopia:displacement" }, + { "count": 1, "spell": "unicopia:dark_vortex" }, + { "count": 18, "trait": "unicopia:knowledge" }, + { "count": 20, "trait": "unicopia:chaos" } + ] + } ] }, { @@ -116,7 +148,14 @@ "elements": [ { "recipe": "unicopia:spells/mind_swap" }, "Requires:", - "- A mimic gem\n- At least 19x knowledge trait\n- At least 10x life trait\n- At least 40x chaos trait", + { + "ingredients": [ + { "count": 1, "spell": "unicopia:mimic" }, + { "count": 19, "trait": "unicopia:knowledge" }, + { "count": 10, "trait": "unicopia:life" }, + { "count": 40, "trait": "unicopia:chaos" } + ] + }, "* Add the focus trait to increase the effect's duration" ] }