From e34a2191b7865e33296c6d0dac0e70cef91c56b9 Mon Sep 17 00:00:00 2001 From: "Katatsumuri.pan" Date: Tue, 5 Mar 2024 19:13:43 +0900 Subject: [PATCH] Make quest gui cool --- .../gui/panels/content/PanelTaskOverlay.java | 210 ++++++++++++++++++ .../betterquesting/client/gui2/GuiQuest.java | 38 +++- .../client/gui2/editors/GuiTaskEditor.java | 109 +++++++-- .../gui2/tasks/PanelTaskAdvancement.java | 9 +- .../gui2/tasks/PanelTaskBlockBreak.java | 23 +- .../client/gui2/tasks/PanelTaskCrafting.java | 23 +- .../client/gui2/tasks/PanelTaskFluid.java | 144 ++++++++++-- .../client/gui2/tasks/PanelTaskRetrieval.java | 142 +++++++++--- .../questing/tasks/TaskFluid.java | 132 +++++++---- .../questing/tasks/TaskRetrieval.java | 56 +++-- .../assets/betterquesting/lang/en_us.lang | 1 + 11 files changed, 744 insertions(+), 143 deletions(-) create mode 100644 src/main/java/betterquesting/api2/client/gui/panels/content/PanelTaskOverlay.java diff --git a/src/main/java/betterquesting/api2/client/gui/panels/content/PanelTaskOverlay.java b/src/main/java/betterquesting/api2/client/gui/panels/content/PanelTaskOverlay.java new file mode 100644 index 000000000..d6a2aad6d --- /dev/null +++ b/src/main/java/betterquesting/api2/client/gui/panels/content/PanelTaskOverlay.java @@ -0,0 +1,210 @@ +package betterquesting.api2.client.gui.panels.content; + +import java.util.List; + +import org.lwjgl.opengl.GL11; + +import betterquesting.api.utils.RenderUtils; +import betterquesting.api2.client.gui.misc.IGuiRect; +import betterquesting.api2.client.gui.panels.IGuiPanel; +import betterquesting.api2.client.gui.resources.colors.GuiColorStatic; +import betterquesting.api2.client.gui.themes.presets.PresetIcon; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; + +/** + * Displays task info over the panel. + */ +public class PanelTaskOverlay implements IGuiPanel { + + public static final float FRAME_WIDTH = 2; + + private final IGuiPanel delegate; + private State state; + private boolean consume; + private String text; // Long text will be scaled. + + public PanelTaskOverlay(IGuiPanel delegate) { this.delegate = delegate; } + + public PanelTaskOverlay setState(State state) { + this.state = state; + return this; + } + + public PanelTaskOverlay setConsume(boolean consume) { + this.consume = consume; + return this; + } + + public PanelTaskOverlay setText(String text) { + this.text = text; + return this; + } + + @Override + public void drawPanel(int mx, int my, float partialTick) { + delegate.drawPanel(mx, my, partialTick); + switch (state) { + case INCOMPLETE -> { + renderIncomplete(); + if (consume) + renderConsumeIcon(mx, my); + } + case COMPLETE -> { + renderComplete(mx, my); + } + case IN_PROGRESS -> { + renderInProgress(); + if (consume) + renderConsumeIcon(mx, my); + } + } + renderText(mx, my); + } + + // delegates + + @Override + public IGuiRect getTransform() { return delegate.getTransform(); } + + @Override + public void initPanel() { + delegate.initPanel(); + } + + @Override + public void setEnabled(boolean state) { + delegate.setEnabled(state); + } + + @Override + public boolean isEnabled() { return delegate.isEnabled(); } + + @Override + public boolean onMouseClick(int mx, int my, int button) { + return delegate.onMouseClick(mx, my, button); + } + + @Override + public boolean onMouseRelease(int mx, int my, int button) { + return delegate.onMouseRelease(mx, my, button); + } + + @Override + public boolean onMouseScroll(int mx, int my, int scroll) { + return delegate.onMouseScroll(mx, my, scroll); + } + + @Override + public boolean onKeyTyped(char c, int keycode) { + return delegate.onKeyTyped(c, keycode); + } + + @Override + public List getTooltip(int mx, int my) { + return delegate.getTooltip(mx, my); + } + + private void renderIncomplete() { + renderFrame(0.2f * RenderUtils.sineWave(2, 0) + 0.3f, 0, 0, 1); + } + + private void renderComplete(int mx, int my) { + renderFrame(0.2f, 1, 0, 1); + int size = 12; + IGuiRect rect = getTransform(); + int x = rect.getX() + rect.getWidth() - size + 2; + int y = rect.getY() - 2; + int a = getTransform().contains(mx, my) ? 100 : 255; + PresetIcon.ICON_CHECK.getTexture().drawTexture(x, y, size, size, 0, 0, new GuiColorStatic(0, 255, 0, a)); + } + + private void renderInProgress() { + float r = 0.3f * RenderUtils.sineWave(2, 0) + 0.3f; + float g = r; + renderFrame(r, g, 0, 1); + } + + private void renderFrame(float red, float green, float blue, float alpha) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder vertexbuffer = tessellator.getBuffer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, + GlStateManager.SourceFactor.ONE, + GlStateManager.DestFactor.ZERO); + GlStateManager.color(red, green, blue, alpha); + + vertexbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); + IGuiRect rect = getTransform(); + double w = FRAME_WIDTH / 2; + vertexbuffer.pos((double) rect.getX() - w, (double) rect.getY() + w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + rect.getWidth() + w, (double) rect.getY() + w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + rect.getWidth() + w, (double) rect.getY() - w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() - w, (double) rect.getY() - w, 0.0D).endVertex(); + + vertexbuffer.pos((double) rect.getX() - w, (double) rect.getY() + rect.getHeight() + w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + rect.getWidth() + w, (double) rect.getY() + rect.getHeight() + w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + rect.getWidth() + w, (double) rect.getY() + rect.getHeight() - w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() - w, (double) rect.getY() + rect.getHeight() - w, 0.0D).endVertex(); + + vertexbuffer.pos((double) rect.getX() - w, (double) rect.getY() + rect.getHeight() + w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + w, (double) rect.getY() + rect.getHeight() + w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + w, (double) rect.getY() - w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() - w, (double) rect.getY() - w, 0.0D).endVertex(); + + vertexbuffer.pos((double) rect.getX() + rect.getWidth() - w, (double) rect.getY() + rect.getHeight() + w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + rect.getWidth() + w, (double) rect.getY() + rect.getHeight() + w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + rect.getWidth() + w, (double) rect.getY() - w, 0.0D).endVertex(); + vertexbuffer.pos((double) rect.getX() + rect.getWidth() - w, (double) rect.getY() - w, 0.0D).endVertex(); + + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + + private void renderText(int mx, int my) { + GlStateManager.enableBlend(); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + IGuiRect rect = getTransform(); + int width = fontRenderer.getStringWidth(text); + int x = rect.getX() + rect.getWidth() - width; + int y = rect.getY() + rect.getHeight() - fontRenderer.FONT_HEIGHT + 1; + int a = getTransform().contains(mx, my) ? 100 : 255; + if (x < rect.getX() + FRAME_WIDTH / 2) { + //scale to fit + float s = (rect.getWidth() - FRAME_WIDTH) / width; + float new_x = rect.getX() + FRAME_WIDTH / 2; + float new_y = y + fontRenderer.FONT_HEIGHT * (1 - s) - FRAME_WIDTH / 2; + GlStateManager.pushMatrix(); + GlStateManager.translate(new_x, new_y, 0); + GlStateManager.scale(s, s, s); + fontRenderer.drawStringWithShadow(text, 0, 0, 0xFFFFFF | (a << 24)); + GlStateManager.popMatrix(); + } else { + fontRenderer.drawStringWithShadow(text, x, y, 0xFFFFFF | (a << 24)); + } + } + + private void renderConsumeIcon(int mx, int my) { + GlStateManager.enableBlend(); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + IGuiRect rect = getTransform(); + int x = rect.getX() + rect.getWidth() - fontRenderer.getStringWidth("C"); + int y = rect.getY() + 1; + int a = getTransform().contains(mx, my) ? 100 : 255; + fontRenderer.drawStringWithShadow("C", x, y, 0xFFFF00 | (a << 24)); + } + + public enum State { + INCOMPLETE, + COMPLETE, + IN_PROGRESS, + } + +} diff --git a/src/main/java/betterquesting/client/gui2/GuiQuest.java b/src/main/java/betterquesting/client/gui2/GuiQuest.java index 801942cc5..7c9767751 100644 --- a/src/main/java/betterquesting/client/gui2/GuiQuest.java +++ b/src/main/java/betterquesting/client/gui2/GuiQuest.java @@ -31,11 +31,14 @@ import betterquesting.api2.client.gui.panels.CanvasTextured; import betterquesting.api2.client.gui.panels.IGuiPanel; import betterquesting.api2.client.gui.panels.bars.PanelVScrollBar; +import betterquesting.api2.client.gui.panels.content.PanelGeneric; import betterquesting.api2.client.gui.panels.content.PanelLine; import betterquesting.api2.client.gui.panels.content.PanelTextBox; import betterquesting.api2.client.gui.panels.lists.CanvasScrolling; import betterquesting.api2.client.gui.popups.PopContextMenu; +import betterquesting.api2.client.gui.resources.colors.GuiColorStatic; import betterquesting.api2.client.gui.themes.presets.PresetColor; +import betterquesting.api2.client.gui.themes.presets.PresetIcon; import betterquesting.api2.client.gui.themes.presets.PresetLine; import betterquesting.api2.client.gui.themes.presets.PresetTexture; import betterquesting.api2.storage.DBEntry; @@ -48,7 +51,6 @@ import betterquesting.questing.tasks.TaskRetrieval; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.resources.I18n; public class GuiQuest extends GuiScreenCanvas implements IPEventListener, INeedsRefresh { @@ -66,6 +68,7 @@ public class GuiQuest extends GuiScreenCanvas implements IPEventListener, INeeds private PanelButton btnClaim; private CanvasEmpty cvInner; + private PanelTextBox logicTitle; private IGuiRect rectReward; private IGuiRect rectTask; @@ -154,6 +157,13 @@ else if (rectReward != null && rectReward.contains(mx, my) && QuestingAPI.getAPI panTxt.setColor(PresetColor.TEXT_HEADER.getColor()); cvBackground.addPanel(panTxt); + if (quest.getTasks().getEntries().size() > 1) { + // The text will be set in refreshGui() + logicTitle = new PanelTextBox(new GuiTransform(GuiAlign.TOP_EDGE, new GuiPadding(0, 16, 16, -32), 0), "").setAlignment(2); + logicTitle.setColor(PresetColor.TEXT_HEADER.getColor()); + cvBackground.addPanel(logicTitle); + } + if (QuestingAPI.getAPI(ApiReference.SETTINGS).canUserEdit(mc.player)) { cvBackground.addPanel(new PanelButton(new GuiTransform(GuiAlign.BOTTOM_CENTER, -100, -16, 100, 16, 0), 0, QuestTranslation.translate("gui.back"))); cvBackground.addPanel(new PanelButton(new GuiTransform(GuiAlign.BOTTOM_CENTER, 0, -16, 100, 16, 0), @@ -226,6 +236,9 @@ public boolean onMouseClick(int mx, int my, int click) { @Override public void refreshGui() { + if (logicTitle != null) + logicTitle.setText(QuestTranslation.translate("betterquesting.btn.logic") + ": " + quest.getProperty(NativeProps.LOGIC_TASK)); + this.refreshTaskPanel(); this.refreshRewardPanel(); this.updateButtons(); @@ -393,13 +406,6 @@ private void refreshTaskPanel() { int yOffset = 0; List> entries = quest.getTasks().getEntries(); - if (entries.size() > 1) { - PanelTextBox logicTitle = new PanelTextBox(new GuiTransform(new Vector4f(), 8, yOffset, rectTask.getWidth(), 12, 0), - I18n.format("betterquesting.btn.task_logic", quest.getProperty(NativeProps.LOGIC_TASK))); - logicTitle.setColor(PresetColor.TEXT_HEADER.getColor()); - csTask.addPanel(logicTitle); - yOffset += 12; - } for (int i = 0; i < entries.size(); i++) { ITask tsk = entries.get(i).getValue(); @@ -409,16 +415,28 @@ private void refreshTaskPanel() { if (entryLogic != EnumLogic.AND) taskName += " (" + entryLogic + ")"; } - PanelTextBox titleReward = new PanelTextBox(new GuiTransform(new Vector4f(), 0, yOffset, rectTask.getWidth(), 12, 0), taskName); + PanelTextBox titleReward = new PanelTextBox(new GuiTransform(new Vector4f(), 0, yOffset, csTask.getTransform().getWidth(), 12, 0), taskName); titleReward.setColor(PresetColor.TEXT_HEADER.getColor()).setAlignment(1); titleReward.setEnabled(true); csTask.addPanel(titleReward); + // Display checkmark if completed + if (tsk.isComplete(QuestingAPI.getQuestingUUID(Minecraft.getMinecraft().player))) { + int size = 18; + int x = csTask.getTransform().getWidth() / 2; + int y = yOffset - 4; + PanelGeneric panel = new PanelGeneric(new GuiTransform(new Vector4f(), x, y, size, size, 0), + PresetIcon.ICON_CHECK.getTexture(), + new GuiColorStatic(0, 255, 0, 255)); + csTask.addPanel(panel); + } + yOffset += 10; IGuiPanel taskGui = tsk.getTaskGui(new GuiTransform(GuiAlign.FULL_BOX, 8, - i == 0 && entries.size() == 1 && tsk.displaysCenteredAlone() ? rectTask.getHeight() / 3 : 0, + i == 0 && entries.size() == 1 && tsk.displaysCenteredAlone() ? csTask.getTransform() + .getHeight() / 3 : 0, csTask.getTransform().getWidth(), csTask.getTransform().getHeight(), 0), new DBEntry<>(questID, quest)); diff --git a/src/main/java/betterquesting/client/gui2/editors/GuiTaskEditor.java b/src/main/java/betterquesting/client/gui2/editors/GuiTaskEditor.java index f5378948b..ceb8fa6b8 100644 --- a/src/main/java/betterquesting/client/gui2/editors/GuiTaskEditor.java +++ b/src/main/java/betterquesting/client/gui2/editors/GuiTaskEditor.java @@ -1,5 +1,14 @@ package betterquesting.client.gui2.editors; +import java.util.ArrayDeque; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import javax.annotation.Nullable; + +import org.lwjgl.util.vector.Vector4f; + import betterquesting.api.client.gui.misc.INeedsRefresh; import betterquesting.api.client.gui.misc.IVolatileScreen; import betterquesting.api.questing.IQuest; @@ -14,7 +23,11 @@ import betterquesting.api2.client.gui.events.PEventBroadcaster; import betterquesting.api2.client.gui.events.PanelEvent; import betterquesting.api2.client.gui.events.types.PEventButton; -import betterquesting.api2.client.gui.misc.*; +import betterquesting.api2.client.gui.misc.GuiAlign; +import betterquesting.api2.client.gui.misc.GuiPadding; +import betterquesting.api2.client.gui.misc.GuiRectangle; +import betterquesting.api2.client.gui.misc.GuiTransform; +import betterquesting.api2.client.gui.misc.IGuiRect; import betterquesting.api2.client.gui.panels.CanvasTextured; import betterquesting.api2.client.gui.panels.bars.PanelVScrollBar; import betterquesting.api2.client.gui.panels.content.PanelLine; @@ -22,31 +35,32 @@ import betterquesting.api2.client.gui.panels.lists.CanvasScrolling; import betterquesting.api2.client.gui.panels.lists.CanvasSearch; import betterquesting.api2.client.gui.themes.presets.PresetColor; +import betterquesting.api2.client.gui.themes.presets.PresetIcon; import betterquesting.api2.client.gui.themes.presets.PresetLine; import betterquesting.api2.client.gui.themes.presets.PresetTexture; import betterquesting.api2.registry.IFactoryData; import betterquesting.api2.storage.DBEntry; +import betterquesting.api2.storage.IDatabaseNBT; import betterquesting.api2.utils.QuestTranslation; import betterquesting.client.gui2.editors.nbt.GuiNbtEditor; import betterquesting.network.handlers.NetQuestEdit; import betterquesting.questing.QuestDatabase; import betterquesting.questing.tasks.TaskRegistry; +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import net.minecraft.client.gui.GuiScreen; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.text.TextFormatting; -import org.lwjgl.util.vector.Vector4f; - -import java.util.ArrayDeque; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; public class GuiTaskEditor extends GuiScreenCanvas implements IPEventListener, IVolatileScreen, INeedsRefresh { + private CanvasScrolling qtList; private IQuest quest; private final int qID; + @Nullable // Not null when tasks are reordered. + private Int2IntMap taskIndexBeforeReorder = null; // currentIndex -> oldIndex public GuiTaskEditor(GuiScreen parent, IQuest quest) { super(parent); @@ -79,16 +93,24 @@ public void initPanel() { PEventBroadcaster.INSTANCE.register(this, PEventButton.class); // Background panel - CanvasTextured cvBackground = new CanvasTextured(new GuiTransform(GuiAlign.FULL_BOX, new GuiPadding(0, 0, 0, 0), 0), PresetTexture.PANEL_MAIN.getTexture()); + CanvasTextured cvBackground = new CanvasTextured(new GuiTransform(GuiAlign.FULL_BOX, new GuiPadding(0, 0, 0, 0), 0), + PresetTexture.PANEL_MAIN.getTexture()); this.addPanel(cvBackground); - PanelTextBox panTxt = new PanelTextBox(new GuiTransform(GuiAlign.TOP_EDGE, new GuiPadding(0, 16, 0, -32), 0), QuestTranslation.translate("betterquesting.title.edit_tasks")).setAlignment(1); + PanelTextBox panTxt = new PanelTextBox(new GuiTransform(GuiAlign.TOP_EDGE, new GuiPadding(0, 16, 0, -32), 0), + QuestTranslation.translate("betterquesting.title.edit_tasks")).setAlignment(1); panTxt.setColor(PresetColor.TEXT_HEADER.getColor()); cvBackground.addPanel(panTxt); cvBackground.addPanel(new PanelButton(new GuiTransform(GuiAlign.BOTTOM_CENTER, -100, -16, 200, 16, 0), 0, QuestTranslation.translate("gui.back"))); - CanvasSearch, IFactoryData> cvRegSearch = new CanvasSearch, IFactoryData>((new GuiTransform(GuiAlign.HALF_RIGHT, new GuiPadding(8, 48, 24, 32), 0))) { + CanvasSearch, IFactoryData> cvRegSearch = new CanvasSearch, IFactoryData>((new GuiTransform(GuiAlign.HALF_RIGHT, + new GuiPadding(8, + 48, + 24, + 32), + 0))) { + @Override protected Iterator> getIterator() { List> list = TaskRegistry.INSTANCE.getAll(); @@ -98,7 +120,8 @@ protected Iterator> getIterator() { @Override protected void queryMatches(IFactoryData value, String query, ArrayDeque> results) { - if (value.getRegistryName().toString().toLowerCase().contains(query.toLowerCase())) results.add(value); + if (value.getRegistryName().toString().toLowerCase().contains(query.toLowerCase())) + results.add(value); } @Override @@ -106,6 +129,7 @@ protected boolean addResult(IFactoryData entry, int index this.addPanel(new PanelButtonStorage<>(new GuiRectangle(0, index * 16, cachedWidth, 16, 0), 1, entry.getRegistryName().toString(), entry)); return true; } + }; cvBackground.addPanel(cvRegSearch); @@ -113,7 +137,9 @@ protected boolean addResult(IFactoryData entry, int index cvBackground.addPanel(scReg); cvRegSearch.setScrollDriverY(scReg); - PanelTextField tfSearch = new PanelTextField<>(new GuiTransform(new Vector4f(0.5F, 0F, 1F, 0F), new GuiPadding(8, 32, 16, -48), 0), "", FieldFilterString.INSTANCE); + PanelTextField tfSearch = new PanelTextField<>(new GuiTransform(new Vector4f(0.5F, 0F, 1F, 0F), new GuiPadding(8, 32, 16, -48), 0), + "", + FieldFilterString.INSTANCE); tfSearch.setCallback(cvRegSearch::setSearchFilter); tfSearch.setWatermark("Search..."); cvBackground.addPanel(tfSearch); @@ -177,6 +203,16 @@ private void onButtonPress(PEventButton event) { SendChanges(); })); } + } else if (btn.getButtonID() == 4 && btn instanceof PanelButtonStorage) // Up + { + ITask task = ((PanelButtonStorage) btn).getStoredValue(); + int idx = quest.getTasks().getID(task); + reorder(idx, false); + } else if (btn.getButtonID() == 5 && btn instanceof PanelButtonStorage) // Down + { + ITask task = ((PanelButtonStorage) btn).getStoredValue(); + int idx = quest.getTasks().getID(task); + reorder(idx, true); } } @@ -188,8 +224,23 @@ private void refreshTasks() { for (int i = 0; i < dbTsk.size(); i++) { ITask task = dbTsk.get(i).getValue(); - qtList.addPanel(new PanelButtonStorage<>(new GuiRectangle(0, i * 16, w - 16, 16, 0), 3, QuestTranslation.translate(task.getUnlocalisedName()), task)); - qtList.addPanel(new PanelButtonStorage<>(new GuiRectangle(w - 16, i * 16, 16, 16, 0), 2, "" + TextFormatting.RED + TextFormatting.BOLD + "x", task)); + int index = taskIndexBeforeReorder == null ? i : taskIndexBeforeReorder.get(i); + qtList.addPanel(new PanelButtonStorage<>(new GuiRectangle(0, i * 16, w - 48, 16, 0), + 3, + (index + 1) + ". " + QuestTranslation.translate(task.getUnlocalisedName()), + task)); + + PanelButton btnUp = new PanelButtonStorage<>(new GuiRectangle(w - 48, i * 16, 16, 16, 0), 4, "", task).setIcon(PresetIcon.ICON_UP.getTexture()); + btnUp.setActive(i > 0); + qtList.addPanel(btnUp); + PanelButton btnDown = new PanelButtonStorage<>(new GuiRectangle(w - 32, i * 16, 16, 16, 0), 5, "", task).setIcon(PresetIcon.ICON_DOWN.getTexture()); + btnDown.setActive(i < dbTsk.size() - 1); + qtList.addPanel(btnDown); + + qtList.addPanel(new PanelButtonStorage<>(new GuiRectangle(w - 16, i * 16, 16, 16, 0), + 2, + "" + TextFormatting.RED + TextFormatting.BOLD + "x", + task)); } } @@ -204,4 +255,34 @@ private void SendChanges() { payload.setInteger("action", 0); NetQuestEdit.sendEdit(payload); } + + private void reorder(int index, boolean down) { + + int size = quest.getTasks().size(); + + int indexFrom = (index + (down ? 1 : -1) + size) % size; + + IDatabaseNBT tasks = quest.getTasks(); + + if (taskIndexBeforeReorder == null) { + taskIndexBeforeReorder = new Int2IntOpenHashMap(); + for (DBEntry entry : tasks.getEntries()) { + taskIndexBeforeReorder.put(entry.getID(), entry.getID()); + } + } + + ITask task = tasks.getValue(index); + ITask task2 = tasks.getValue(indexFrom); + tasks.removeID(index); + tasks.removeID(indexFrom); + tasks.add(index, task2); + tasks.add(indexFrom, task); + + int tmp = taskIndexBeforeReorder.get(index); + taskIndexBeforeReorder.put(index, taskIndexBeforeReorder.get(indexFrom)); + taskIndexBeforeReorder.put(indexFrom, tmp); + + SendChanges(); + } + } diff --git a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskAdvancement.java b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskAdvancement.java index 03ac684a1..cfeb4838d 100644 --- a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskAdvancement.java +++ b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskAdvancement.java @@ -6,6 +6,8 @@ import betterquesting.api2.client.gui.misc.*; import betterquesting.api2.client.gui.panels.CanvasEmpty; import betterquesting.api2.client.gui.panels.content.PanelGeneric; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay.State; import betterquesting.api2.client.gui.panels.content.PanelTextBox; import betterquesting.api2.client.gui.resources.textures.ItemTexture; import betterquesting.api2.client.gui.themes.presets.PresetColor; @@ -45,7 +47,12 @@ public void initPanel() { } this.addPanel(new PanelGeneric(new GuiRectangle(0, 0, 24, 24, 0), PresetTexture.ITEM_FRAME.getTexture())); - this.addPanel(new PanelGeneric(new GuiRectangle(0, 0, 24, 24, -1), new ItemTexture(icon))); + PanelTaskOverlay overlay = new PanelTaskOverlay(new PanelGeneric(new GuiRectangle(0, 0, 24, 24, -1), new ItemTexture(icon))); + if (isComplete) + overlay.setState(State.COMPLETE); + else + overlay.setState(State.INCOMPLETE); + this.addPanel(overlay); this.addPanel(new PanelTextBox(new GuiTransform(GuiAlign.TOP_EDGE, new GuiPadding(28, 2, 0, -12), 0), title).setColor(PresetColor.TEXT_MAIN.getColor())); String s = isComplete ? (TextFormatting.GREEN.toString() + QuestTranslation.translate("betterquesting.tooltip.complete")) : (TextFormatting.RED.toString() + QuestTranslation.translate("betterquesting.tooltip.incomplete")); diff --git a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskBlockBreak.java b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskBlockBreak.java index 3e808fe64..b276710f5 100644 --- a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskBlockBreak.java +++ b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskBlockBreak.java @@ -1,11 +1,15 @@ package betterquesting.client.gui2.tasks; +import java.util.UUID; + import betterquesting.api.api.QuestingAPI; import betterquesting.api.utils.BigItemStack; import betterquesting.api2.client.gui.misc.GuiRectangle; import betterquesting.api2.client.gui.misc.IGuiRect; import betterquesting.api2.client.gui.panels.CanvasMinimum; import betterquesting.api2.client.gui.panels.content.PanelItemSlot; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay.State; import betterquesting.api2.client.gui.panels.content.PanelTextBox; import betterquesting.api2.client.gui.themes.presets.PresetColor; import betterquesting.api2.utils.QuestTranslation; @@ -13,8 +17,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.util.text.TextFormatting; -import java.util.UUID; - public class PanelTaskBlockBreak extends CanvasMinimum { private final IGuiRect initialRect; @@ -42,19 +44,30 @@ public void initPanel() { if (stack == null) { continue; } + boolean completed = isComplete || progress[i] >= stack.stackSize; PanelItemSlot slot = new PanelItemSlot(new GuiRectangle(0, i * 36, 36, 36, 0), -1, stack, true, true); - this.addPanel(slot); + PanelTaskOverlay overlay = new PanelTaskOverlay(slot); + if (completed) + overlay.setState(State.COMPLETE); + else if (progress[i] > 0) + overlay.setState(State.IN_PROGRESS); + else + overlay.setState(State.INCOMPLETE); + if (!completed) + overlay.setText(progress[i] + "/" + stack.stackSize); + this.addPanel(overlay); StringBuilder sb = new StringBuilder(); sb.append(stack.getBaseStack().getDisplayName()); - if (stack.hasOreDict()) sb.append(" (").append(stack.getOreDict()).append(")"); + if (stack.hasOreDict()) + sb.append(" (").append(stack.getOreDict()).append(")"); sb.append("\n").append(progress[i]).append("/").append(stack.stackSize).append("\n"); - if (progress[i] >= stack.stackSize || isComplete) { + if (completed) { sb.append(TextFormatting.GREEN).append(QuestTranslation.translate("betterquesting.tooltip.complete")); } else { sb.append(TextFormatting.RED).append(QuestTranslation.translate("betterquesting.tooltip.incomplete")); diff --git a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskCrafting.java b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskCrafting.java index fe6b1f1d9..2746b814f 100644 --- a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskCrafting.java +++ b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskCrafting.java @@ -1,5 +1,7 @@ package betterquesting.client.gui2.tasks; +import java.util.UUID; + import betterquesting.api.api.QuestingAPI; import betterquesting.api.utils.BigItemStack; import betterquesting.api2.client.gui.misc.GuiRectangle; @@ -7,6 +9,8 @@ import betterquesting.api2.client.gui.panels.CanvasMinimum; import betterquesting.api2.client.gui.panels.content.PanelGeneric; import betterquesting.api2.client.gui.panels.content.PanelItemSlot; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay.State; import betterquesting.api2.client.gui.panels.content.PanelTextBox; import betterquesting.api2.client.gui.resources.colors.GuiColorStatic; import betterquesting.api2.client.gui.resources.textures.GuiTextureColored; @@ -20,8 +24,6 @@ import net.minecraft.init.Blocks; import net.minecraft.util.text.TextFormatting; -import java.util.UUID; - public class PanelTaskCrafting extends CanvasMinimum { private final IGuiRect initialRect; @@ -57,19 +59,30 @@ public void initPanel() { for (int i = 0; i < task.requiredItems.size(); i++) { BigItemStack stack = task.requiredItems.get(i); + boolean completed = isComplete || progress[i] >= stack.stackSize; PanelItemSlot slot = new PanelItemSlot(new GuiRectangle(0, i * 28 + 24, 28, 28, 0), -1, stack, false, true); - this.addPanel(slot); + PanelTaskOverlay overlay = new PanelTaskOverlay(slot); + if (completed) + overlay.setState(State.COMPLETE); + else if (progress[i] > 0) + overlay.setState(State.IN_PROGRESS); + else + overlay.setState(State.INCOMPLETE); + if (!completed) + overlay.setText(progress[i] + "/" + stack.stackSize); + this.addPanel(overlay); StringBuilder sb = new StringBuilder(); sb.append(stack.getBaseStack().getDisplayName()); - if (stack.hasOreDict()) sb.append(" (").append(stack.getOreDict()).append(")"); + if (stack.hasOreDict()) + sb.append(" (").append(stack.getOreDict()).append(")"); sb.append("\n").append(progress[i]).append("/").append(stack.stackSize).append("\n"); - if (isComplete || progress[i] >= stack.stackSize) { + if (completed) { sb.append(TextFormatting.GREEN).append(QuestTranslation.translate("betterquesting.tooltip.complete")); } else { sb.append(TextFormatting.RED).append(QuestTranslation.translate("betterquesting.tooltip.incomplete")); diff --git a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskFluid.java b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskFluid.java index ff943a8f7..f66f67a49 100644 --- a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskFluid.java +++ b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskFluid.java @@ -1,14 +1,19 @@ package betterquesting.client.gui2.tasks; +import java.util.List; +import java.util.UUID; + import betterquesting.api.api.QuestingAPI; -import betterquesting.api2.client.gui.misc.GuiAlign; +import betterquesting.api2.client.gui.controls.PanelButton; import betterquesting.api2.client.gui.misc.GuiRectangle; -import betterquesting.api2.client.gui.misc.GuiTransform; import betterquesting.api2.client.gui.misc.IGuiRect; import betterquesting.api2.client.gui.panels.CanvasMinimum; import betterquesting.api2.client.gui.panels.content.PanelFluidSlot; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay.State; import betterquesting.api2.client.gui.panels.content.PanelTextBox; import betterquesting.api2.client.gui.themes.presets.PresetColor; +import betterquesting.api2.client.gui.themes.presets.PresetIcon; import betterquesting.api2.utils.QuestTranslation; import betterquesting.core.BetterQuesting; import betterquesting.questing.tasks.TaskFluid; @@ -20,10 +25,11 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.Optional.Method; -import java.util.UUID; - public class PanelTaskFluid extends CanvasMinimum { + public static final int MAX_SLOT_SIZE = PanelTaskRetrieval.MAX_SLOT_SIZE; + public static final int MIN_SLOT_SIZE = PanelTaskRetrieval.MIN_SLOT_SIZE; + public static final int SLOT_PADDING = PanelTaskRetrieval.SLOT_PADDING; private final IGuiRect initialRect; private final TaskFluid task; @@ -42,37 +48,129 @@ public void initPanel() { int[] progress = task.getUsersProgress(uuid); boolean isComplete = task.isComplete(uuid); - String sCon = (task.consume ? TextFormatting.RED : TextFormatting.GREEN) + QuestTranslation.translate(task.consume ? "gui.yes" : "gui.no"); - this.addPanel(new PanelTextBox(new GuiTransform(GuiAlign.TOP_EDGE, 0, 0, listW, 12, 0), QuestTranslation.translate("bq_standard.btn.consume", sCon)).setColor(PresetColor.TEXT_MAIN.getColor())); - - for (int i = 0; i < task.requiredFluids.size(); i++) { - FluidStack stack = task.requiredFluids.get(i); + final int firstIconOffset = 10; - PanelFluidSlot slot = new PanelFluidSlot(new GuiRectangle(0, i * 28 + 12, 28, 28, 0), -1, stack); - if (BetterQuesting.hasJEI) slot.setCallback(this::lookupRecipe); - this.addPanel(slot); + if (task.isFold() && task.requiredFluids.size() > 1) { + int x = firstIconOffset; + int y = 0; + int slotSize = MAX_SLOT_SIZE; + int canvasWidth = initialRect.getWidth(); + canvasWidth -= 8; //scrollbar width + canvasWidth -= (int) PanelTaskOverlay.FRAME_WIDTH / 2; + if (firstIconOffset + task.requiredFluids.size() * (slotSize + SLOT_PADDING) >= canvasWidth) { + // Fit it into the (parent) canvas + slotSize = (int) Math.max(MIN_SLOT_SIZE, (float) (canvasWidth - firstIconOffset) / task.requiredFluids.size() - SLOT_PADDING); + } - StringBuilder sb = new StringBuilder(); + PanelButton foldArrow = new PanelButton(new GuiRectangle(0, 0, 8, 8, 0), -1, ""); + foldArrow.setIcon(PresetIcon.ICON_RIGHT.getTexture()); + foldArrow.setClickAction(b -> setFold(false)); + this.addPanel(foldArrow); - sb.append(stack.getLocalizedName()).append("\n"); - sb.append(progress[i]).append("/").append(stack.amount).append("mB\n"); + for (int i = 0; i < task.requiredFluids.size(); i++) { + if (x + slotSize > canvasWidth) { + x = firstIconOffset; + y += slotSize + SLOT_PADDING; + } + FluidStack stack = task.requiredFluids.get(i); + boolean completed = isComplete || progress[i] >= stack.amount; - if (progress[i] >= stack.amount || isComplete) { - sb.append(TextFormatting.GREEN).append(QuestTranslation.translate("betterquesting.tooltip.complete")); - } else { - sb.append(TextFormatting.RED).append(QuestTranslation.translate("betterquesting.tooltip.incomplete")); + PanelFluidSlot slot = createPanelFluidSlot(new GuiRectangle(x, y, slotSize, slotSize, 0), stack); + if (BetterQuesting.hasJEI) + slot.setCallback(this::lookupRecipe); + PanelTaskOverlay overlay = new PanelTaskOverlay(slot); + if (completed) + overlay.setState(State.COMPLETE); + else if (progress[i] > 0) + overlay.setState(State.IN_PROGRESS); + else + overlay.setState(State.INCOMPLETE); + if (!completed) + overlay.setText(progress[i] + "/" + stack.amount); + if (task.consume) + overlay.setConsume(true); + this.addPanel(overlay); + x += slotSize + SLOT_PADDING; } + } else { + if (task.requiredFluids.size() > 1) { + PanelButton foldArrow = new PanelButton(new GuiRectangle(0, 0, 8, 8, 0), -1, ""); + foldArrow.setIcon(PresetIcon.ICON_DOWN.getTexture()); + foldArrow.setClickAction(b -> setFold(true)); + this.addPanel(foldArrow); + } + + for (int i = 0; i < task.requiredFluids.size(); i++) { + FluidStack stack = task.requiredFluids.get(i); + boolean completed = isComplete || progress[i] >= stack.amount; + + PanelFluidSlot slot = createPanelFluidSlot(new GuiRectangle(firstIconOffset, + i * (MAX_SLOT_SIZE + SLOT_PADDING), + MAX_SLOT_SIZE, + MAX_SLOT_SIZE, + 0), stack); + if (BetterQuesting.hasJEI) + slot.setCallback(this::lookupRecipe); + PanelTaskOverlay overlay = new PanelTaskOverlay(slot); + if (completed) + overlay.setState(State.COMPLETE); + else if (progress[i] > 0) + overlay.setState(State.IN_PROGRESS); + else + overlay.setState(State.INCOMPLETE); + if (!completed) + overlay.setText(progress[i] + "/" + stack.amount); + if (task.consume) + overlay.setConsume(true); + this.addPanel(overlay); + + StringBuilder sb = new StringBuilder(); + + sb.append(stack.getLocalizedName()).append("\n"); + sb.append(progress[i]).append("/").append(stack.amount).append("mB\n"); - PanelTextBox text = new PanelTextBox(new GuiRectangle(36, i * 28 + 12, listW - 36, 28, 0), sb.toString()); - text.setColor(PresetColor.TEXT_MAIN.getColor()); - this.addPanel(text); + if (progress[i] >= stack.amount || isComplete) { + sb.append(TextFormatting.GREEN).append(QuestTranslation.translate("betterquesting.tooltip.complete")); + } else { + sb.append(TextFormatting.RED).append(QuestTranslation.translate("betterquesting.tooltip.incomplete")); + } + + PanelTextBox text = new PanelTextBox(new GuiRectangle(firstIconOffset + (MAX_SLOT_SIZE + SLOT_PADDING), + i * (MAX_SLOT_SIZE + SLOT_PADDING), + listW - MAX_SLOT_SIZE, + MAX_SLOT_SIZE, + 0), sb.toString()); + text.setColor(PresetColor.TEXT_MAIN.getColor()); + this.addPanel(text); + } } + recalculateSizes(); } @Method(modid = "jei") private void lookupRecipe(FluidStack fluid) { - if (fluid == null || Internal.getRuntime() == null) return; + if (fluid == null || Internal.getRuntime() == null) + return; Internal.getRuntime().getRecipesGui().show(new Focus<>(Mode.OUTPUT, fluid)); } + + private PanelFluidSlot createPanelFluidSlot(GuiRectangle rect, FluidStack stack) { + return new PanelFluidSlot(rect, -1, stack, false) { + + @Override + public PanelButton setTooltip(List tooltip) { + if (tooltip != null && task.consume) { + tooltip.add(TextFormatting.RED + "[" + QuestTranslation.translate("bq_standard.tooltip.consume") + "]"); + } + return super.setTooltip(tooltip); + } + + }; + } + + private void setFold(boolean fold) { + task.setFold(fold); + } + } diff --git a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskRetrieval.java b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskRetrieval.java index 08acdaf97..eb746a49b 100644 --- a/src/main/java/betterquesting/client/gui2/tasks/PanelTaskRetrieval.java +++ b/src/main/java/betterquesting/client/gui2/tasks/PanelTaskRetrieval.java @@ -1,24 +1,30 @@ package betterquesting.client.gui2.tasks; +import java.util.List; +import java.util.UUID; + import betterquesting.api.api.QuestingAPI; import betterquesting.api.utils.BigItemStack; -import betterquesting.api2.client.gui.misc.GuiAlign; +import betterquesting.api2.client.gui.controls.PanelButton; import betterquesting.api2.client.gui.misc.GuiRectangle; -import betterquesting.api2.client.gui.misc.GuiTransform; import betterquesting.api2.client.gui.misc.IGuiRect; import betterquesting.api2.client.gui.panels.CanvasMinimum; import betterquesting.api2.client.gui.panels.content.PanelItemSlot; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay; +import betterquesting.api2.client.gui.panels.content.PanelTaskOverlay.State; import betterquesting.api2.client.gui.panels.content.PanelTextBox; import betterquesting.api2.client.gui.themes.presets.PresetColor; +import betterquesting.api2.client.gui.themes.presets.PresetIcon; import betterquesting.api2.utils.QuestTranslation; import betterquesting.questing.tasks.TaskRetrieval; import net.minecraft.client.Minecraft; import net.minecraft.util.text.TextFormatting; -import java.util.UUID; - public class PanelTaskRetrieval extends CanvasMinimum { + public static final int MAX_SLOT_SIZE = 28; + public static final int MIN_SLOT_SIZE = 20; + public static final int SLOT_PADDING = 4; private final IGuiRect initialRect; private final TaskRetrieval task; @@ -37,34 +43,120 @@ public void initPanel() { int[] progress = task.getUsersProgress(uuid); boolean isComplete = task.isComplete(uuid); - String sCon = (task.consume ? TextFormatting.RED : TextFormatting.GREEN) + QuestTranslation.translate(task.consume ? "gui.yes" : "gui.no"); - - this.addPanel(new PanelTextBox(new GuiTransform(GuiAlign.TOP_EDGE, 0, 0, listW, 16, 0), QuestTranslation.translate("bq_standard.btn.consume", sCon)).setColor(PresetColor.TEXT_MAIN.getColor())); + final int firstIconOffset = 10; - for (int i = 0; i < task.requiredItems.size(); i++) { - BigItemStack stack = task.requiredItems.get(i); + if (task.isFold() && task.requiredItems.size() > 1) { - PanelItemSlot slot = new PanelItemSlot(new GuiRectangle(0, i * 32 + 16, 28, 28, 0), -1, stack, false, true); - this.addPanel(slot); - - StringBuilder sb = new StringBuilder(); + int x = firstIconOffset; + int y = 0; + int slotSize = MAX_SLOT_SIZE; + int canvasWidth = initialRect.getWidth(); + canvasWidth -= 8; //scrollbar width + canvasWidth -= (int) PanelTaskOverlay.FRAME_WIDTH / 2; + if (firstIconOffset + task.requiredItems.size() * (slotSize + SLOT_PADDING) >= canvasWidth) { + // Fit it into the (parent) canvas + slotSize = (int) Math.max(MIN_SLOT_SIZE, (float) (canvasWidth - firstIconOffset) / task.requiredItems.size() - SLOT_PADDING); + } - sb.append(stack.getBaseStack().getDisplayName()); + PanelButton foldArrow = new PanelButton(new GuiRectangle(0, 0, 8, 8, 0), -1, ""); + foldArrow.setIcon(PresetIcon.ICON_RIGHT.getTexture()); + foldArrow.setClickAction(b -> setFold(false)); + this.addPanel(foldArrow); + + for (int i = 0; i < task.requiredItems.size(); i++) { + if (x + slotSize > canvasWidth) { + x = firstIconOffset; + y += slotSize + SLOT_PADDING; + } + BigItemStack stack = task.requiredItems.get(i); + boolean completed = isComplete || progress[i] >= stack.stackSize; + + PanelItemSlot slot = createPanelItemSlot(new GuiRectangle(x, y, slotSize, slotSize, 0), stack); + PanelTaskOverlay overlay = new PanelTaskOverlay(slot); + if (completed) + overlay.setState(State.COMPLETE); + else if (progress[i] > 0) + overlay.setState(State.IN_PROGRESS); + else + overlay.setState(State.INCOMPLETE); + if (!completed) + overlay.setText(progress[i] + "/" + stack.stackSize); + if (task.consume) + overlay.setConsume(true); + this.addPanel(overlay); + x += slotSize + SLOT_PADDING; + } + } else { + if (task.requiredItems.size() > 1) { + PanelButton foldArrow = new PanelButton(new GuiRectangle(0, 0, 8, 8, 0), -1, ""); + foldArrow.setIcon(PresetIcon.ICON_DOWN.getTexture()); + foldArrow.setClickAction(b -> setFold(true)); + this.addPanel(foldArrow); + } - if (stack.hasOreDict()) sb.append(" (").append(stack.getOreDict()).append(")"); + for (int i = 0; i < task.requiredItems.size(); i++) { + BigItemStack stack = task.requiredItems.get(i); + boolean completed = isComplete || progress[i] >= stack.stackSize; + + PanelItemSlot slot = createPanelItemSlot(new GuiRectangle(firstIconOffset, i * (MAX_SLOT_SIZE + SLOT_PADDING), MAX_SLOT_SIZE, MAX_SLOT_SIZE, 0), + stack); + PanelTaskOverlay overlay = new PanelTaskOverlay(slot); + if (completed) + overlay.setState(State.COMPLETE); + else if (progress[i] > 0) + overlay.setState(State.IN_PROGRESS); + else + overlay.setState(State.INCOMPLETE); + if (!completed) + overlay.setText(progress[i] + "/" + stack.stackSize); + if (task.consume) + overlay.setConsume(true); + this.addPanel(overlay); + + StringBuilder sb = new StringBuilder(); + + sb.append(stack.getBaseStack().getDisplayName()); + + if (stack.hasOreDict()) + sb.append(" (").append(stack.getOreDict()).append(")"); + + sb.append("\n").append(progress[i]).append("/").append(stack.stackSize).append("\n"); + + if (completed) { + sb.append(TextFormatting.GREEN).append(QuestTranslation.translate("betterquesting.tooltip.complete")); + } else { + sb.append(TextFormatting.RED).append(QuestTranslation.translate("betterquesting.tooltip.incomplete")); + } + + PanelTextBox text = new PanelTextBox(new GuiRectangle(firstIconOffset + (MAX_SLOT_SIZE + SLOT_PADDING), + i * (MAX_SLOT_SIZE + SLOT_PADDING), + listW - MAX_SLOT_SIZE, + MAX_SLOT_SIZE, + 0), sb.toString()); + text.setColor(PresetColor.TEXT_MAIN.getColor()); + this.addPanel(text); + } + } + recalculateSizes(); + } - sb.append("\n").append(progress[i]).append("/").append(stack.stackSize).append("\n"); + private PanelItemSlot createPanelItemSlot(GuiRectangle rect, BigItemStack stack) { + return new PanelItemSlot(rect, -1, stack, false, true) { - if (isComplete || progress[i] >= stack.stackSize) { - sb.append(TextFormatting.GREEN).append(QuestTranslation.translate("betterquesting.tooltip.complete")); - } else { - sb.append(TextFormatting.RED).append(QuestTranslation.translate("betterquesting.tooltip.incomplete")); + @Override + public List getTooltip(int mx, int my) { + List tooltip = super.getTooltip(mx, my); + if (tooltip != null && task.consume) { + tooltip.add(TextFormatting.RED + "[" + QuestTranslation.translate("bq_standard.tooltip.consume") + "]"); + } + return tooltip; } - PanelTextBox text = new PanelTextBox(new GuiRectangle(32, i * 32 + 16, listW - 28, 28, 0), sb.toString()); - text.setColor(PresetColor.TEXT_MAIN.getColor()); - this.addPanel(text); - } - recalculateSizes(); + }; + } + + private void setFold(boolean fold) { + task.setFold(fold); } + } diff --git a/src/main/java/betterquesting/questing/tasks/TaskFluid.java b/src/main/java/betterquesting/questing/tasks/TaskFluid.java index a13a9b109..bc981695d 100644 --- a/src/main/java/betterquesting/questing/tasks/TaskFluid.java +++ b/src/main/java/betterquesting/questing/tasks/TaskFluid.java @@ -1,5 +1,20 @@ package betterquesting.questing.tasks; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.UUID; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.apache.logging.log4j.Level; + +import betterquesting.api.client.gui.misc.INeedsRefresh; import betterquesting.api.questing.IQuest; import betterquesting.api.questing.tasks.IFluidTask; import betterquesting.api.questing.tasks.IItemTask; @@ -11,6 +26,7 @@ import betterquesting.client.gui2.tasks.PanelTaskFluid; import betterquesting.core.BetterQuesting; import betterquesting.questing.tasks.factory.FactoryTaskFluid; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; @@ -30,13 +46,9 @@ import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import org.apache.logging.log4j.Level; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; public class TaskFluid implements ITaskInventory, IFluidTask, IItemTask { + private final Set completeUsers = new TreeSet<>(); public final NonNullList requiredFluids = NonNullList.create(); public final TreeMap userProgress = new TreeMap<>(); @@ -45,16 +57,23 @@ public class TaskFluid implements ITaskInventory, IFluidTask, IItemTask { public boolean consume = true; public boolean groupDetect = false; public boolean autoConsume = false; + private boolean fold = true; // This remains through the game. - @Override - public ResourceLocation getFactoryID() { - return FactoryTaskFluid.INSTANCE.getRegistryName(); + public boolean isFold() { return fold; } + + public void setFold(boolean fold) { + this.fold = fold; + GuiScreen screen = Minecraft.getMinecraft().currentScreen; + if (screen instanceof INeedsRefresh needsRefresh) { + needsRefresh.refreshGui(); + } } @Override - public String getUnlocalisedName() { - return "bq_standard.task.fluid"; - } + public ResourceLocation getFactoryID() { return FactoryTaskFluid.INSTANCE.getRegistryName(); } + + @Override + public String getUnlocalisedName() { return "bq_standard.task.fluid"; } @Override public boolean isComplete(UUID uuid) { @@ -75,7 +94,8 @@ public void onInventoryChange(@Nonnull DBEntry quest, @Nonnull Participa @Override public void detect(ParticipantInfo pInfo, DBEntry quest) { - if (isComplete(pInfo.UUID)) return; + if (isComplete(pInfo.UUID)) + return; // Removing the consume check here would make the task cheaper on groups and for that reason sharing is restricted to detect only final List> progress = getBulkProgress(consume ? Collections.singletonList(pInfo.UUID) : pInfo.ALL_UUIDS); @@ -112,33 +132,41 @@ public void detect(ParticipantInfo pInfo, DBEntry quest) { for (InventoryPlayer invo : invoList) { for (int i = 0; i < invo.getSizeInventory(); i++) { ItemStack stack = invo.getStackInSlot(i); - if (stack.isEmpty()) continue; + if (stack.isEmpty()) + continue; IFluidHandlerItem handler = FluidUtil.getFluidHandler(stack); - if (handler == null) continue; + if (handler == null) + continue; boolean hasDrained = false; for (int j = 0; j < requiredFluids.size(); j++) { final FluidStack rStack = requiredFluids.get(j); FluidStack drainOG = rStack.copy(); - if (ignoreNbt) drainOG.tag = null; + if (ignoreNbt) + drainOG.tag = null; // Pre-check FluidStack sample = handler.drain(drainOG, false); - if (sample == null || sample.amount <= 0) continue; + if (sample == null || sample.amount <= 0) + continue; // Theoretically this could work in consume mode for parties but the priority order and manual submission code would need changing for (Tuple value : progress) { - if (value.getSecond()[j] >= rStack.amount) continue; + if (value.getSecond()[j] >= rStack.amount) + continue; int remaining = rStack.amount - value.getSecond()[j]; FluidStack drain = rStack.copy(); drain.amount = remaining / stack.getCount(); // Must be a multiple of the stack size - if (ignoreNbt) drain.tag = null; - if (drain.amount <= 0) continue; + if (ignoreNbt) + drain.tag = null; + if (drain.amount <= 0) + continue; FluidStack fluid = handler.drain(drain, consume); // TODO: Look into reducing this to a single call if possible - if (fluid == null || fluid.amount <= 0) continue; + if (fluid == null || fluid.amount <= 0) + continue; value.getSecond()[j] += fluid.amount * stack.getCount(); hasDrained = true; @@ -146,11 +174,13 @@ public void detect(ParticipantInfo pInfo, DBEntry quest) { } } - if (hasDrained && consume) invo.setInventorySlotContents(i, handler.getContainer()); + if (hasDrained && consume) + invo.setInventorySlotContents(i, handler.getContainer()); } } - if (updated) setBulkProgress(progress); + if (updated) + setBulkProgress(progress); checkAndComplete(pInfo, quest, updated); } @@ -161,7 +191,8 @@ private void checkAndComplete(ParticipantInfo pInfo, DBEntry quest, bool topLoop: for (Tuple value : progress) { for (int j = 0; j < requiredFluids.size(); j++) { - if (value.getSecond()[j] >= requiredFluids.get(j).amount) continue; + if (value.getSecond()[j] >= requiredFluids.get(j).amount) + continue; continue topLoop; } @@ -259,14 +290,16 @@ public NBTTagCompound writeProgressToNBT(NBTTagCompound nbt, @Nullable List { - if (completeUsers.contains(uuid)) jArray.appendTag(new NBTTagString(uuid.toString())); + if (completeUsers.contains(uuid)) + jArray.appendTag(new NBTTagString(uuid.toString())); int[] data = userProgress.get(uuid); if (data != null) { NBTTagCompound pJson = new NBTTagCompound(); pJson.setString("uuid", uuid.toString()); NBTTagList pArray = new NBTTagList(); // TODO: Why the heck isn't this just an int array?! - for (int i : data) pArray.appendTag(new NBTTagInt(i)); + for (int i : data) + pArray.appendTag(new NBTTagInt(i)); pJson.setTag("data", pArray); progArray.appendTag(pJson); } @@ -278,7 +311,8 @@ public NBTTagCompound writeProgressToNBT(NBTTagCompound nbt, @Nullable List quest) { return new PanelTaskFluid(rect, this); } - @Override - @SideOnly(Side.CLIENT) + @Override @SideOnly(Side.CLIENT) public GuiScreen getTaskEditor(GuiScreen screen, DBEntry quest) { return null; } @@ -323,8 +355,10 @@ public boolean canAcceptFluid(UUID owner, DBEntry quest, FluidStack flui for (int j = 0; j < requiredFluids.size(); j++) { FluidStack rStack = requiredFluids.get(j).copy(); - if (ignoreNbt) rStack.tag = null; - if (progress[j] < rStack.amount && rStack.equals(fluid)) return true; + if (ignoreNbt) + rStack.tag = null; + if (progress[j] < rStack.amount && rStack.equals(fluid)) + return true; } return false; @@ -338,13 +372,16 @@ public boolean canAcceptItem(UUID owner, DBEntry quest, ItemStack item) IFluidHandlerItem handler = FluidUtil.getFluidHandler(item); - if (handler == null) return false; + if (handler == null) + return false; for (IFluidTankProperties tank : handler.getTankProperties()) { - if (!tank.canDrain()) continue; + if (!tank.canDrain()) + continue; for (FluidStack rStack : requiredFluids) { - if (rStack.equals(tank.getContents())) return true; + if (rStack.equals(tank.getContents())) + return true; } } @@ -367,7 +404,8 @@ private FluidStack submitFluidInternal(UUID owner, DBEntry quest, FluidS for (int j = 0; j < requiredFluids.size(); j++) { FluidStack rStack = requiredFluids.get(j); - if (progress[j] >= rStack.amount) continue; + if (progress[j] >= rStack.amount) + continue; int remaining = rStack.amount - progress[j]; @@ -396,13 +434,15 @@ private FluidStack submitFluidInternal(UUID owner, DBEntry quest, FluidS // It's implied to be a consume task so no need to lookup the party boolean hasAll = true; for (int j = 0; j < requiredFluids.size(); j++) { - if (progress[j] >= requiredFluids.get(j).amount) continue; + if (progress[j] >= requiredFluids.get(j).amount) + continue; hasAll = false; break; } - if (hasAll) setComplete(owner); + if (hasAll) + setComplete(owner); } } @@ -411,24 +451,28 @@ private FluidStack submitFluidInternal(UUID owner, DBEntry quest, FluidS @Override public ItemStack submitItem(UUID owner, DBEntry quest, ItemStack input) { - if (owner == null || input.isEmpty() || !consume || isComplete(owner)) return input; + if (owner == null || input.isEmpty() || !consume || isComplete(owner)) + return input; ItemStack item = input.splitStack(1); // Prevents issues with stack filling/draining IFluidHandlerItem handler = FluidUtil.getFluidHandler(item); - if (handler == null) return item; + if (handler == null) + return item; boolean hasDrained = false; for (IFluidTankProperties tank : handler.getTankProperties()) { - if (!tank.canDrain() || tank.getContents() == null || !tank.canDrainFluidType(tank.getContents())) continue; + if (!tank.canDrain() || tank.getContents() == null || !tank.canDrainFluidType(tank.getContents())) + continue; // Figure out how much of this fluid is left to submit to the task FluidStack remaining = submitFluidInternal(owner, quest, tank.getContents().copy(), false); FluidStack drain = tank.getContents().copy(); drain.amount -= remaining == null ? 0 : remaining.amount; - if (drain.amount <= 0) continue; + if (drain.amount <= 0) + continue; // Attempt drain of remaining amount and submit to task progress submitFluidInternal(owner, quest, handler.drain(drain, true), true); @@ -448,7 +492,8 @@ public int[] getUsersProgress(UUID uuid) { } private List> getBulkProgress(@Nonnull List uuids) { - if (uuids.size() <= 0) return Collections.emptyList(); + if (uuids.size() <= 0) + return Collections.emptyList(); List> list = new ArrayList<>(); uuids.forEach((key) -> list.add(new Tuple<>(key, getUsersProgress(key)))); return list; @@ -467,4 +512,5 @@ public List getTextForSearch() { } return texts; } + } diff --git a/src/main/java/betterquesting/questing/tasks/TaskRetrieval.java b/src/main/java/betterquesting/questing/tasks/TaskRetrieval.java index 96de78345..09005c357 100644 --- a/src/main/java/betterquesting/questing/tasks/TaskRetrieval.java +++ b/src/main/java/betterquesting/questing/tasks/TaskRetrieval.java @@ -1,5 +1,21 @@ package betterquesting.questing.tasks; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.UUID; +import java.util.stream.IntStream; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.apache.logging.log4j.Level; + +import betterquesting.api.client.gui.misc.INeedsRefresh; import betterquesting.api.enums.EnumLogic; import betterquesting.api.questing.IQuest; import betterquesting.api.questing.tasks.IItemTask; @@ -13,6 +29,7 @@ import betterquesting.client.gui2.tasks.PanelTaskRetrieval; import betterquesting.core.BetterQuesting; import betterquesting.questing.tasks.factory.FactoryTaskRetrieval; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; @@ -28,14 +45,9 @@ import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import org.apache.logging.log4j.Level; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; -import java.util.stream.IntStream; public class TaskRetrieval implements ITaskInventory, IItemTask { + private final Set completeUsers = new TreeSet<>(); public final NonNullList requiredItems = NonNullList.create(); private final TreeMap userProgress = new TreeMap<>(); @@ -45,16 +57,23 @@ public class TaskRetrieval implements ITaskInventory, IItemTask { public boolean groupDetect = false; public boolean autoConsume = false; public EnumLogic entryLogic = EnumLogic.AND; + private boolean fold = true; // This remains through the game. - @Override - public String getUnlocalisedName() { - return BetterQuesting.MODID_STD + ".task.retrieval"; + public boolean isFold() { return fold; } + + public void setFold(boolean fold) { + this.fold = fold; + GuiScreen screen = Minecraft.getMinecraft().currentScreen; + if (screen instanceof INeedsRefresh needsRefresh) { + needsRefresh.refreshGui(); + } } @Override - public ResourceLocation getFactoryID() { - return FactoryTaskRetrieval.INSTANCE.getRegistryName(); - } + public String getUnlocalisedName() { return BetterQuesting.MODID_STD + ".task.retrieval"; } + + @Override + public ResourceLocation getFactoryID() { return FactoryTaskRetrieval.INSTANCE.getRegistryName(); } @Override public boolean isComplete(UUID uuid) { @@ -120,7 +139,8 @@ public void detect(ParticipantInfo pInfo, DBEntry quest) { for (int j = 0; j < requiredItems.size(); j++) { BigItemStack rStack = requiredItems.get(j); - if (!ItemComparison.StackMatch(rStack.getBaseStack(), stack, !ignoreNBT, partialMatch) && !ItemComparison.OreDictionaryMatch(rStack.getOreIngredient(), rStack.GetTagCompound(), stack, !ignoreNBT, partialMatch)) { + if (!ItemComparison.StackMatch(rStack.getBaseStack(), stack, !ignoreNBT, partialMatch) && !ItemComparison.OreDictionaryMatch(rStack + .getOreIngredient(), rStack.GetTagCompound(), stack, !ignoreNBT, partialMatch)) { continue; } @@ -338,7 +358,8 @@ public boolean canAcceptItem(UUID owner, DBEntry quest, ItemStack stack) if (progress[j] >= rStack.stackSize) continue; - if (ItemComparison.StackMatch(rStack.getBaseStack(), stack, !ignoreNBT, partialMatch) || ItemComparison.OreDictionaryMatch(rStack.getOreIngredient(), rStack.GetTagCompound(), stack, !ignoreNBT, partialMatch)) { + if (ItemComparison.StackMatch(rStack.getBaseStack(), stack, !ignoreNBT, partialMatch) || ItemComparison.OreDictionaryMatch(rStack + .getOreIngredient(), rStack.GetTagCompound(), stack, !ignoreNBT, partialMatch)) { return true; } } @@ -367,7 +388,8 @@ public ItemStack submitItem(UUID owner, DBEntry quest, ItemStack input) int remaining = rStack.stackSize - progress[j]; - if (ItemComparison.StackMatch(rStack.getBaseStack(), stack, !ignoreNBT, partialMatch) || ItemComparison.OreDictionaryMatch(rStack.getOreIngredient(), rStack.GetTagCompound(), stack, !ignoreNBT, partialMatch)) { + if (ItemComparison.StackMatch(rStack.getBaseStack(), stack, !ignoreNBT, partialMatch) || ItemComparison.OreDictionaryMatch(rStack + .getOreIngredient(), rStack.GetTagCompound(), stack, !ignoreNBT, partialMatch)) { int removed = Math.min(stack.getCount(), remaining); stack.shrink(removed); progress[j] += removed; @@ -397,8 +419,7 @@ public ItemStack submitItem(UUID owner, DBEntry quest, ItemStack input) return stack.isEmpty() ? ItemStack.EMPTY : stack; } - @Override - @SideOnly(Side.CLIENT) + @Override @SideOnly(Side.CLIENT) public GuiScreen getTaskEditor(GuiScreen parent, DBEntry quest) { return null; } @@ -436,4 +457,5 @@ public List getTextForSearch() { } return texts; } + } diff --git a/src/main/resources/assets/betterquesting/lang/en_us.lang b/src/main/resources/assets/betterquesting/lang/en_us.lang index 1983a1f89..d9d88af2e 100644 --- a/src/main/resources/assets/betterquesting/lang/en_us.lang +++ b/src/main/resources/assets/betterquesting/lang/en_us.lang @@ -313,6 +313,7 @@ bq_standard.tooltip.fixed_loot=Loot Set: %s bq_standard.tooltip.fixed_loot_size=Contains %s items bq_standard.tooltip.loot_table=Loot Table: %s bq_standard.tooltip.loot_chest=Rarity: %s +bq_standard.tooltip.consume=This will be consumed!! betterquesting.notification.enabled=Quest Notifications: On betterquesting.notification.disabled=Quest Notifications: Off