From 6b59198308bd63175085be4f05ff28e23bc347a4 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Wed, 27 May 2026 06:48:50 -0700 Subject: [PATCH 1/4] add SKIP_COMPLETION_COUNT --- src/main/java/betterquesting/api/properties/NativeProps.java | 1 + src/main/java/betterquesting/questing/QuestInstance.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/betterquesting/api/properties/NativeProps.java b/src/main/java/betterquesting/api/properties/NativeProps.java index df73341a5..5efd968fe 100644 --- a/src/main/java/betterquesting/api/properties/NativeProps.java +++ b/src/main/java/betterquesting/api/properties/NativeProps.java @@ -34,6 +34,7 @@ public class NativeProps { public static final IPropertyType LOCKED_PROGRESS = new PropertyTypeBoolean(new ResourceLocation(ModReference.MODID, "lockedProgress"), false); public static final IPropertyType SIMULTANEOUS = new PropertyTypeBoolean(new ResourceLocation(ModReference.MODID, "simultaneous"), false); public static final IPropertyType IGNORES_VIEW_MODE = new PropertyTypeBoolean(new ResourceLocation(ModReference.MODID, "ignoresView"), false); + public static final IPropertyType SKIP_COMPLETION_COUNT = new PropertyTypeBoolean(new ResourceLocation(ModReference.MODID, "skipCompletionCount"), false); public static final IPropertyType VISIBILITY = new PropertyTypeEnum<>(new ResourceLocation(ModReference.MODID, "visibility"), findVisibility()); public static final IPropertyType LOGIC_TASK = new PropertyTypeEnum<>(new ResourceLocation(ModReference.MODID, "taskLogic"), EnumLogic.AND); diff --git a/src/main/java/betterquesting/questing/QuestInstance.java b/src/main/java/betterquesting/questing/QuestInstance.java index e63a8825d..2dc0141d2 100644 --- a/src/main/java/betterquesting/questing/QuestInstance.java +++ b/src/main/java/betterquesting/questing/QuestInstance.java @@ -74,6 +74,7 @@ private void setupProps() { setupValue(NativeProps.GLOBAL_SHARE, false); setupValue(NativeProps.SIMULTANEOUS, false); setupValue(NativeProps.IGNORES_VIEW_MODE, false); + setupValue(NativeProps.SKIP_COMPLETION_COUNT, false); setupValue(NativeProps.VISIBILITY, NativeProps.VISIBILITY.getDefault()); } From 820ed8f53f23fd6aa869ca842bbe47a2ce5826f4 Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Wed, 27 May 2026 06:51:47 -0700 Subject: [PATCH 2/4] add total completed and percentage --- .../client/gui2/GuiQuestLines.java | 76 +++++++++++++++---- .../assets/betterquesting/lang/en_us.lang | 3 +- .../assets/betterquesting/lang/ja_jp.lang | 2 +- .../assets/betterquesting/lang/ru_ru.lang | 2 +- 4 files changed, 67 insertions(+), 16 deletions(-) diff --git a/src/main/java/betterquesting/client/gui2/GuiQuestLines.java b/src/main/java/betterquesting/client/gui2/GuiQuestLines.java index 71387fdd9..8cadf9e87 100644 --- a/src/main/java/betterquesting/client/gui2/GuiQuestLines.java +++ b/src/main/java/betterquesting/client/gui2/GuiQuestLines.java @@ -53,21 +53,24 @@ import betterquesting.network.handlers.NetQuestAction; import betterquesting.questing.QuestDatabase; import betterquesting.questing.QuestLineDatabase; +import it.unimi.dsi.fastutil.ints.IntArraySet; +import it.unimi.dsi.fastutil.ints.IntSet; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.Tuple; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.common.config.Configuration; import org.lwjgl.util.vector.Vector4f; import javax.annotation.Nonnull; +import java.text.DecimalFormat; import java.util.*; public class GuiQuestLines extends GuiScreenCanvas implements IPEventListener, INeedsRefresh { private static OpenTray openTray = OpenTray.NONE; + private static final DecimalFormat PERCENT_FORMAT = new DecimalFormat("0.##"); private final ScrollPosition scrollPosition; @@ -91,6 +94,7 @@ public class GuiQuestLines extends GuiScreenCanvas implements IPEventListener, I private PanelTextBox txTitle; private PanelTextBox txDesc; private PanelTextBox completionText; + private PanelTextBox globalCompletionText; private PanelButton claimAll; @@ -195,12 +199,16 @@ public void initPanel() { cvDescTray.setTrayState(false, 200); cvFrame.setTrayState(false, 200); buildChapterList(); - }); + }); cvBackground.addPanel(cvChapterTray); - cvLines = new CanvasScrolling(new GuiTransform(GuiAlign.FULL_BOX, new GuiPadding(8, 8, 16, 8), 0)); + cvLines = new CanvasScrolling(new GuiTransform(GuiAlign.FULL_BOX, new GuiPadding(8, 20, 16, 8), 0)); cvChapterTray.getCanvasOpen().addPanel(cvLines); + globalCompletionText = new PanelTextBox(new GuiTransform(new Vector4f(0F, 0F, 1F, 0F), new GuiPadding(24, 8, 16, -20), 0), ""); + globalCompletionText.setColor(PresetColor.TEXT_HEADER.getColor()); + cvChapterTray.getCanvasOpen().addPanel(globalCompletionText); + scLines = new PanelVScrollBar(new GuiTransform(GuiAlign.RIGHT_EDGE, new GuiPadding(-16, 8, 8, 8), 0)); cvLines.setScrollDriverY(scLines); cvChapterTray.getCanvasOpen().addPanel(scLines); @@ -513,10 +521,12 @@ private void refreshChapterVisibility() { } if (cvChapterTray.isTrayOpen()) buildChapterList(); + refreshGlobalCompletion(); } private boolean isQuestCompletedForQuestline(UUID playerID, @Nonnull IQuest q) { if (q.isComplete(playerID)) return true; // Completed quest + if (q.getProperty(NativeProps.SKIP_COMPLETION_COUNT)) return true; // Always counted as true if (q.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN) return true; // Always hidden quest if (q.getProperty(NativeProps.LOGIC_QUEST) == EnumLogic.XOR) { // Quest with choice int reqCount = 0; @@ -578,31 +588,71 @@ private void buildChapterList() { } private void refreshQuestCompletion() { - UUID playerUUID = QuestingAPI.getQuestingUUID(mc.player); + if (selectedLine == null) return; - if (selectedLine == null) { - return; - } + UUID playerUUID = QuestingAPI.getQuestingUUID(mc.player); - int questsCompleted = 0; - int totalQuests = 0; var database = Objects.requireNonNull(QuestingAPI.getAPI(ApiReference.QUEST_DB)); + int completed = 0; + int total = 0; for (DBEntry entry : selectedLine.getEntries()) { IQuest quest = database.getValue(entry.getID()); + if (quest.getProperty(NativeProps.SKIP_COMPLETION_COUNT)) continue; + if (quest.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN) continue; if (quest.getProperty(NativeProps.LOGIC_QUEST) == EnumLogic.XOR) { // Subtract the number of requirements - 1 to simulate only doing 1 task for XOR requirements - totalQuests = totalQuests - Math.max(0, quest.getRequirements().length - 1); + total = total - Math.max(0, quest.getRequirements().length - 1); } - totalQuests++; + total++; if (quest.isComplete(playerUUID)) { - questsCompleted++; + completed++; } } - completionText.setText(QuestTranslation.translate("betterquesting.title.completion", questsCompleted, totalQuests)); + completionText.setText(completionText("betterquesting.title.completion", completed, total)); + } + + private void refreshGlobalCompletion() { + if (globalCompletionText == null) return; + + UUID playerUUID = QuestingAPI.getQuestingUUID(mc.player); + var database = Objects.requireNonNull(QuestingAPI.getAPI(ApiReference.QUEST_DB)); + IntSet seen = new IntArraySet(); + int completed = 0; + int total = 0; + + for (var visChapter : visChapters) { + IQuestLine line = visChapter.getFirst().getValue(); + if (line.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN) continue; + for (var entry : line.getEntries()) { + int questId = entry.getID(); + if (!seen.add(questId)) continue; // already counted in another visible line + IQuest quest = database.getValue(questId); + + if (quest.getProperty(NativeProps.SKIP_COMPLETION_COUNT)) continue; + if (quest.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN) continue; + if (quest.getProperty(NativeProps.LOGIC_QUEST) == EnumLogic.XOR) { + // Subtract the number of requirements - 1 to simulate only doing 1 task for XOR requirements + total = total - Math.max(0, quest.getRequirements().length - 1); + } + + total++; + + if (quest.isComplete(playerUUID)) { + completed++; + } + } + } + + globalCompletionText.setText(completionText("betterquesting.title.completion_total", completed, total)); + } + + private static String completionText(String key, int completed, int total) { + String percent = total > 0 ? PERCENT_FORMAT.format(completed * 100.0 / total) : "0"; + return QuestTranslation.translate(key, completed, total, percent); } private void openQuestLine(DBEntry q) { diff --git a/src/main/resources/assets/betterquesting/lang/en_us.lang b/src/main/resources/assets/betterquesting/lang/en_us.lang index 3247df161..7a03357ae 100644 --- a/src/main/resources/assets/betterquesting/lang/en_us.lang +++ b/src/main/resources/assets/betterquesting/lang/en_us.lang @@ -19,7 +19,8 @@ betterquesting.title.party_invite=Invite Users betterquesting.title.select_theme=Select Theme betterquesting.title.importers=Importers betterquesting.title.submit_station=Submit Station -betterquesting.title.completion=Completion: %d/%d +betterquesting.title.completion=Completion: %d/%d (%s%%) +betterquesting.title.completion_total=Total: %d/%d (%s%%) betterquesting.btn.rewards=Rewards betterquesting.btn.tasks=Tasks diff --git a/src/main/resources/assets/betterquesting/lang/ja_jp.lang b/src/main/resources/assets/betterquesting/lang/ja_jp.lang index 77a40acaa..25baad766 100644 --- a/src/main/resources/assets/betterquesting/lang/ja_jp.lang +++ b/src/main/resources/assets/betterquesting/lang/ja_jp.lang @@ -18,7 +18,7 @@ betterquesting.title.party_invite=ユーザーを招待 betterquesting.title.select_theme=テーマを選択 betterquesting.title.importers=インポーター betterquesting.title.submit_station=提出ステーション -betterquesting.title.completion=%d/%d : 完了 +betterquesting.title.completion=%d/%d : 完了 (%s%%) betterquesting.btn.rewards=報酬 betterquesting.btn.tasks=タスク diff --git a/src/main/resources/assets/betterquesting/lang/ru_ru.lang b/src/main/resources/assets/betterquesting/lang/ru_ru.lang index 709c1843d..92d0f9904 100644 --- a/src/main/resources/assets/betterquesting/lang/ru_ru.lang +++ b/src/main/resources/assets/betterquesting/lang/ru_ru.lang @@ -18,7 +18,7 @@ betterquesting.title.party_invite=Пригласить игроков betterquesting.title.select_theme=Выбрать тему betterquesting.title.importers=Импортеры betterquesting.title.submit_station=Станция отправки -betterquesting.title.completion=Завершение: %d/%d +betterquesting.title.completion=Завершение: %d/%d (%s%%) betterquesting.btn.rewards=Награды betterquesting.btn.tasks=Задания From b639c5b9c49f936f1d7372d867c869f29f01ae6c Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Wed, 27 May 2026 06:52:29 -0700 Subject: [PATCH 3/4] use IGNORES_VIEW_MODE and add to questlines --- .../betterquesting/client/gui2/GuiQuestLines.java | 12 +++++++----- src/main/java/betterquesting/questing/QuestLine.java | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/betterquesting/client/gui2/GuiQuestLines.java b/src/main/java/betterquesting/client/gui2/GuiQuestLines.java index 8cadf9e87..cf40f0197 100644 --- a/src/main/java/betterquesting/client/gui2/GuiQuestLines.java +++ b/src/main/java/betterquesting/client/gui2/GuiQuestLines.java @@ -478,7 +478,9 @@ private void refreshChapterVisibility() { for (DBEntry dbEntry : lineList) { IQuestLine ql = dbEntry.getValue(); EnumQuestVisibility vis = ql.getProperty(NativeProps.VISIBILITY); - if (!canEdit && vis == EnumQuestVisibility.HIDDEN) continue; + + if (!canEdit && vis == EnumQuestVisibility.HIDDEN && (!viewMode || ql.getProperty(NativeProps.IGNORES_VIEW_MODE))) + continue; boolean show = false; boolean unlocked = false; @@ -527,7 +529,7 @@ private void refreshChapterVisibility() { private boolean isQuestCompletedForQuestline(UUID playerID, @Nonnull IQuest q) { if (q.isComplete(playerID)) return true; // Completed quest if (q.getProperty(NativeProps.SKIP_COMPLETION_COUNT)) return true; // Always counted as true - if (q.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN) return true; // Always hidden quest + if (q.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN && q.getProperty(NativeProps.IGNORES_VIEW_MODE)) return true; // Always hidden quest if (q.getProperty(NativeProps.LOGIC_QUEST) == EnumLogic.XOR) { // Quest with choice int reqCount = 0; for (int qRequirementId : q.getRequirements()) { @@ -600,7 +602,7 @@ private void refreshQuestCompletion() { IQuest quest = database.getValue(entry.getID()); if (quest.getProperty(NativeProps.SKIP_COMPLETION_COUNT)) continue; - if (quest.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN) continue; + if (quest.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN && quest.getProperty(NativeProps.IGNORES_VIEW_MODE)) continue; if (quest.getProperty(NativeProps.LOGIC_QUEST) == EnumLogic.XOR) { // Subtract the number of requirements - 1 to simulate only doing 1 task for XOR requirements total = total - Math.max(0, quest.getRequirements().length - 1); @@ -626,14 +628,14 @@ private void refreshGlobalCompletion() { for (var visChapter : visChapters) { IQuestLine line = visChapter.getFirst().getValue(); - if (line.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN) continue; + if (line.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN && line.getProperty(NativeProps.IGNORES_VIEW_MODE)) continue; for (var entry : line.getEntries()) { int questId = entry.getID(); if (!seen.add(questId)) continue; // already counted in another visible line IQuest quest = database.getValue(questId); if (quest.getProperty(NativeProps.SKIP_COMPLETION_COUNT)) continue; - if (quest.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN) continue; + if (quest.getProperty(NativeProps.VISIBILITY) == EnumQuestVisibility.HIDDEN && quest.getProperty(NativeProps.IGNORES_VIEW_MODE)) continue; if (quest.getProperty(NativeProps.LOGIC_QUEST) == EnumLogic.XOR) { // Subtract the number of requirements - 1 to simulate only doing 1 task for XOR requirements total = total - Math.max(0, quest.getRequirements().length - 1); diff --git a/src/main/java/betterquesting/questing/QuestLine.java b/src/main/java/betterquesting/questing/QuestLine.java index 1a526e95c..07baa8dd7 100644 --- a/src/main/java/betterquesting/questing/QuestLine.java +++ b/src/main/java/betterquesting/questing/QuestLine.java @@ -27,6 +27,7 @@ private void setupProps() { this.setupValue(NativeProps.DESC, "No Description"); this.setupValue(NativeProps.ICON, new BigItemStack(Items.BOOK)); this.setupValue(NativeProps.VISIBILITY, NativeProps.VISIBILITY.getDefault()); + this.setupValue(NativeProps.IGNORES_VIEW_MODE, false); this.setupValue(NativeProps.BG_IMAGE); this.setupValue(NativeProps.BG_SIZE); } From f11f735fb2570608339ff446512505b25377e21e Mon Sep 17 00:00:00 2001 From: Waiting Idly <25394029+WaitingIdly@users.noreply.github.com> Date: Wed, 27 May 2026 06:54:41 -0700 Subject: [PATCH 4/4] fix whitespace --- src/main/java/betterquesting/client/gui2/GuiQuestLines.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/betterquesting/client/gui2/GuiQuestLines.java b/src/main/java/betterquesting/client/gui2/GuiQuestLines.java index cf40f0197..fd00e48a1 100644 --- a/src/main/java/betterquesting/client/gui2/GuiQuestLines.java +++ b/src/main/java/betterquesting/client/gui2/GuiQuestLines.java @@ -199,7 +199,7 @@ public void initPanel() { cvDescTray.setTrayState(false, 200); cvFrame.setTrayState(false, 200); buildChapterList(); - }); + }); cvBackground.addPanel(cvChapterTray); cvLines = new CanvasScrolling(new GuiTransform(GuiAlign.FULL_BOX, new GuiPadding(8, 20, 16, 8), 0)); @@ -759,7 +759,7 @@ enum OpenTray { NONE, CHAPTER, DESCRIPTION } - public static class ScrollPosition{ + public static class ScrollPosition { public ScrollPosition(int chapterScrollY) { this.chapterScrollY = chapterScrollY; }