From 37148fad51f25b4e93574be0aaf431d151ab9bde Mon Sep 17 00:00:00 2001 From: Sollace Date: Fri, 2 Sep 2022 12:53:14 +0200 Subject: [PATCH] Fix some more text wrapping issues and catch exceptions whilst loading chapters --- .../unicopia/container/DynamicContent.java | 36 +++++++++++++------ .../unicopia/container/PageElement.java | 23 +++++++----- .../container/ParagraphWrappingVisitor.java | 18 +++++++--- .../container/SpellbookChapterLoader.java | 33 +++++++++-------- .../SpellbookProfilePageContent.java | 5 +-- 5 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/container/DynamicContent.java b/src/main/java/com/minelittlepony/unicopia/container/DynamicContent.java index 2bf6a6e6..34257995 100644 --- a/src/main/java/com/minelittlepony/unicopia/container/DynamicContent.java +++ b/src/main/java/com/minelittlepony/unicopia/container/DynamicContent.java @@ -2,8 +2,7 @@ package com.minelittlepony.unicopia.container; import java.util.*; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import com.google.gson.*; import com.minelittlepony.common.client.gui.IViewRoot; import com.minelittlepony.common.client.gui.dimension.Bounds; import com.minelittlepony.unicopia.client.gui.DrawableUtil; @@ -25,8 +24,8 @@ public class DynamicContent implements Content { private Bounds bounds = Bounds.empty(); - public DynamicContent(JsonArray pages) { - pages.forEach(page -> this.pages.add(new Page(page.getAsJsonObject()))); + public DynamicContent(JsonArray json) { + json.forEach(element -> pages.add(new Page(element.getAsJsonObject()))); } @Override @@ -36,8 +35,10 @@ public class DynamicContent implements Content { getPage(pageIndex).ifPresent(page -> page.draw(matrices, mouseX, mouseY, container)); matrices.push(); - matrices.translate(bounds.width / 2 + 20, 0, 0); - getPage(pageIndex + 1).ifPresent(page -> page.draw(matrices, mouseX, mouseY, container)); + getPage(pageIndex + 1).ifPresent(page -> { + page.bounds.left = bounds.left + bounds.width / 2 + 20; + page.draw(matrices, mouseX, mouseY, container); + }); matrices.pop(); } @@ -45,7 +46,7 @@ public class DynamicContent implements Content { public void copyStateFrom(Content old) { if (old instanceof DynamicContent o) { offset = o.offset; - bounds = o.bounds; + setBounds(o.bounds); } } @@ -56,10 +57,18 @@ public class DynamicContent implements Content { return Optional.of(pages.get(index)); } + private void setBounds(Bounds bounds) { + this.bounds = bounds; + pages.forEach(page -> { + page.reset(); + page.bounds.copy(bounds); + page.bounds.width /= 2; + }); + } + @Override public void init(SpellbookScreen screen) { - bounds = screen.getFrameBounds(); - pages.forEach(Page::reset); + setBounds(screen.getFrameBounds()); screen.addPageButtons(187, 30, 350, incr -> { offset = MathHelper.clamp(offset + incr, 0, (int)Math.ceil(pages.size() / 2F) - 1); }); @@ -73,6 +82,8 @@ public class DynamicContent implements Content { private boolean compiled; + private Bounds bounds = Bounds.empty(); + public Page(JsonObject json) { title = Text.Serializer.fromJson(json.get("title")); level = JsonHelper.getInt(json, "level", 0); @@ -82,7 +93,7 @@ public class DynamicContent implements Content { } protected int getLineLimitAt(int yPosition) { - return (bounds.width / 2 - 10) - elements.stream() + return (bounds.width - 10) - elements.stream() .filter(PageElement::isFloating) .map(PageElement::bounds) .filter(b -> b.contains(b.left + b.width / 2, yPosition)) @@ -113,6 +124,11 @@ public class DynamicContent implements Content { @Override public void draw(MatrixStack matrices, int mouseX, int mouseY, IViewRoot container) { + + if (elements.isEmpty()) { + return; + } + if (!compiled) { compiled = true; int relativeY = 0; diff --git a/src/main/java/com/minelittlepony/unicopia/container/PageElement.java b/src/main/java/com/minelittlepony/unicopia/container/PageElement.java index 2d23666c..b168ad37 100644 --- a/src/main/java/com/minelittlepony/unicopia/container/PageElement.java +++ b/src/main/java/com/minelittlepony/unicopia/container/PageElement.java @@ -54,7 +54,7 @@ interface PageElement extends Drawable { ); } if (el.has("recipe")) { - return new Recipe(page, new Identifier(JsonHelper.getString(el, "texture")), new Bounds(0, 0, 0, 30)); + return new Recipe(page, new Identifier(JsonHelper.getString(el, "recipe")), new Bounds(0, 0, 0, 0)); } return new TextBlock(page, Text.Serializer.fromJson(element)); } @@ -86,11 +86,10 @@ interface PageElement extends Drawable { @Override public void compile(int y, IViewRoot container) { wrappedText.clear(); - ParagraphWrappingVisitor visitor = new ParagraphWrappingVisitor(yPosition -> { - return page.getLineLimitAt(y + yPosition); - }, (line, yPosition) -> { - wrappedText.add(new Line(line, page.getLeftMarginAt(y + yPosition))); - }); + 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()); @@ -128,12 +127,18 @@ interface PageElement extends Drawable { } @Override - public void compile(int y, IViewRoot Container) { + 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) { - IngredientTree tree = new IngredientTree(page.getBounds().left, y, page().getBounds().width / 2 - 20, 20); + IngredientTree tree = new IngredientTree( + bounds().left + page().getBounds().left, + bounds().top + page().getBounds().top + y + 10, page().getBounds().width - 20, 20); spellRecipe.buildCraftingTree(tree); - bounds.height = tree.build(Container); + bounds.height = tree.build(container) - 10; } }); } diff --git a/src/main/java/com/minelittlepony/unicopia/container/ParagraphWrappingVisitor.java b/src/main/java/com/minelittlepony/unicopia/container/ParagraphWrappingVisitor.java index 22c5c317..27414a37 100644 --- a/src/main/java/com/minelittlepony/unicopia/container/ParagraphWrappingVisitor.java +++ b/src/main/java/com/minelittlepony/unicopia/container/ParagraphWrappingVisitor.java @@ -40,7 +40,7 @@ class ParagraphWrappingVisitor implements StyledVisitor { int newline = s.indexOf('\n'); if (newline >= 0 && newline < trimmedLength) { - trimmedLength = newline; + trimmedLength = newline + 1; } else { newline = -1; } @@ -49,17 +49,23 @@ class ParagraphWrappingVisitor implements StyledVisitor { trimmedLength = s.length(); } - String wrappedFragment = s.substring(0, trimmedLength); - int lastSpace = wrappedFragment.lastIndexOf(' '); - trimmedLength = lastSpace > 0 ? Math.min(lastSpace, trimmedLength) : trimmedLength; + // avoid breaking in the middle of a word + if (trimmedLength < s.length() - 1 && trimmedLength > 0 + && (!Character.isWhitespace(s.charAt(trimmedLength + 1)) || !Character.isWhitespace(s.charAt(trimmedLength - 1)))) { + String wrappedFragment = s.substring(0, trimmedLength); + int lastSpace = wrappedFragment.lastIndexOf(' '); + trimmedLength = lastSpace > 0 ? Math.min(lastSpace, trimmedLength) : trimmedLength; + } Text fragment = Text.literal(s.substring(0, trimmedLength).trim()).setStyle(style); float grabbedWidth = handler.getWidth(fragment); + // advance if appending the next segment would cause an overflow if (currentLineCollectedLength + grabbedWidth > pageWidth) { advance(); } + // append the segment to the line that's being built if (currentLineCollectedLength > 0) { currentLine.append(" "); currentLineCollectedLength += handler.getWidth(" "); @@ -67,6 +73,10 @@ class ParagraphWrappingVisitor implements StyledVisitor { currentLine.append(fragment); currentLineCollectedLength += grabbedWidth; + if (newline >= 0) { + advance(); + } + if (trimmedLength <= s.length()) { s = s.substring(trimmedLength, s.length()); } diff --git a/src/main/java/com/minelittlepony/unicopia/container/SpellbookChapterLoader.java b/src/main/java/com/minelittlepony/unicopia/container/SpellbookChapterLoader.java index 04c04602..d0ded9e5 100644 --- a/src/main/java/com/minelittlepony/unicopia/container/SpellbookChapterLoader.java +++ b/src/main/java/com/minelittlepony/unicopia/container/SpellbookChapterLoader.java @@ -4,10 +4,13 @@ import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; +import org.slf4j.Logger; + import com.google.gson.*; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.container.SpellbookChapterList.*; import com.minelittlepony.unicopia.util.Resources; +import com.mojang.logging.LogUtils; import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; import net.minecraft.client.MinecraftClient; @@ -17,10 +20,10 @@ import net.minecraft.util.*; import net.minecraft.util.profiler.Profiler; public class SpellbookChapterLoader extends JsonDataLoader implements IdentifiableResourceReloadListener { - - public static boolean DEBUG = true; - + private static final Logger LOGGER = LogUtils.getLogger(); private static final Identifier ID = Unicopia.id("spellbook/chapters"); + private static final Executor EXECUTOR = CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS); + public static boolean DEBUG = true; public static final SpellbookChapterLoader INSTANCE = new SpellbookChapterLoader(); @@ -39,20 +42,22 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab return new HashSet<>(chapters.values()); } - private static final Executor EXECUTOR = CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS); - @Override protected void apply(Map data, ResourceManager manager, Profiler profiler) { - chapters = data.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> { - JsonObject json = JsonHelper.asObject(entry.getValue(), "root"); + try { + chapters = data.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> { + JsonObject json = JsonHelper.asObject(entry.getValue(), "root"); - return new Chapter(entry.getKey(), - TabSide.valueOf(JsonHelper.getString(json, "side")), - JsonHelper.getInt(json, "y_position"), - JsonHelper.getInt(json, "color", 0), - loadContent(JsonHelper.getObject(json, "content", new JsonObject())) - ); - })); + return new Chapter(entry.getKey(), + TabSide.valueOf(JsonHelper.getString(json, "side")), + JsonHelper.getInt(json, "y_position"), + JsonHelper.getInt(json, "color", 0), + loadContent(JsonHelper.getObject(json, "content", new JsonObject())) + ); + })); + } catch (IllegalStateException | JsonParseException e) { + LOGGER.error("Could not load spellbook chapters due to exception", e); + } if (DEBUG) { CompletableFuture.runAsync(() -> { diff --git a/src/main/java/com/minelittlepony/unicopia/container/SpellbookProfilePageContent.java b/src/main/java/com/minelittlepony/unicopia/container/SpellbookProfilePageContent.java index d1e924b2..79919755 100644 --- a/src/main/java/com/minelittlepony/unicopia/container/SpellbookProfilePageContent.java +++ b/src/main/java/com/minelittlepony/unicopia/container/SpellbookProfilePageContent.java @@ -64,13 +64,14 @@ public class SpellbookProfilePageContent extends DrawableHelper implements Spell float alphaF = (MathHelper.sin(delta / 9F) + 1) / 2F; int alpha = (int)(alphaF * 0x10) & 0xFF; int color = 0x10404000 | alpha; - int xpColor = 0xAA0040FF | ((int)(xpPercentage * 0xFF) & 0xFF) << 16; + int xpColor = 0xAA0040FF | ((int)((0.3F + 0.7F * xpPercentage) * 0xFF) & 0xFF) << 16; + int manaColor = 0xFF00F040 | (int)((0.3F + 0.7F * alphaF) * 0x40) << 16; DrawableUtil.drawArc(matrices, 0, radius + 24, 0, DrawableUtil.TAU, color, false); DrawableUtil.drawArc(matrices, radius / 3, radius + 6, 0, DrawableUtil.TAU, color, false); DrawableUtil.drawArc(matrices, radius / 3, radius + 6, 0, xpPercentage * DrawableUtil.TAU, xpColor, false); radius += 8; - DrawableUtil.drawArc(matrices, radius, radius + 6 + growth, 0, manaPercentage * DrawableUtil.TAU, 0xFF40F040, false); + DrawableUtil.drawArc(matrices, radius, radius + 6 + growth, 0, manaPercentage * DrawableUtil.TAU, manaColor, false); String manaString = (int)reserves.getMana().get() + "/" + (int)reserves.getMana().getMax();