Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Groups Refactor #136

Draft
wants to merge 6 commits into
base: 1.20.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package earth.terrarium.heracles.api.groups;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import earth.terrarium.heracles.api.quests.QuestIcon;
import earth.terrarium.heracles.api.quests.QuestIcons;

import java.util.Optional;

public record Group(
Optional<QuestIcon<?>> icon,
String title,
String description
) {

public static final Codec<Group> CODEC = RecordCodecBuilder.create(instance -> instance.group(
QuestIcons.CODEC.optionalFieldOf("icon").forGetter(Group::icon),
Codec.STRING.fieldOf("title").forGetter(Group::title),
Codec.STRING.fieldOf("description").forGetter(Group::description)
).apply(instance, Group::new));

public Group(String id) {
this(Optional.empty(), id, "");
}

public Group withIcon(QuestIcon<?> icon) {
return new Group(Optional.of(icon), this.title, this.description);
}

public Group withTitle(String title) {
return new Group(this.icon, title, this.description);
}

public Group withDescription(String description) {
return new Group(this.icon, this.title, description);
}

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public Group edit(Optional<QuestIcon<?>> icon, Optional<String> title, Optional<String> description) {
return new Group(
icon.or(() -> this.icon),
title.orElse(this.title),
description.orElse(this.description)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static void clientTick() {
}

public static void openQuestScreen() {
if (!ClientQuests.groups().contains(lastGroup)) {
if (!ClientQuests.groups().containsKey(lastGroup)) {
lastGroup = "";
}
if (DisplayConfig.showTutorial) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package earth.terrarium.heracles.client.handlers;

import earth.terrarium.heracles.api.groups.Group;
import earth.terrarium.heracles.api.quests.Quest;
import earth.terrarium.heracles.common.handlers.progress.QuestProgress;
import earth.terrarium.heracles.common.menus.quests.QuestsContent;
Expand All @@ -15,19 +16,20 @@ public class ClientQuests {
private static final Map<String, QuestEntry> ENTRIES = new HashMap<>();
private static final Map<String, ModUtils.QuestStatus> STATUS = new HashMap<>();
private static final Map<String, List<QuestEntry>> BY_GROUPS = new HashMap<>();
private static final List<String> GROUPS = new ArrayList<>();
private static final Map<String, Group> GROUPS = new LinkedHashMap<>();
private static final List<String> GROUP_ORDERS = new ArrayList<>();

private static final Map<String, QuestProgress> PROGRESS = new HashMap<>();

public static Optional<QuestEntry> get(String key) {
return Optional.ofNullable(ENTRIES.get(key));
}

public static List<String> groups() {
public static Map<String, Group> groups() {
return GROUPS;
}

public static void sync(Map<String, Quest> quests, List<String> groups) {
public static void sync(Map<String, Quest> quests, Map<String, Group> groups) {
ENTRIES.clear();
BY_GROUPS.clear();
GROUPS.clear();
Expand All @@ -36,14 +38,35 @@ public static void sync(Map<String, Quest> quests, List<String> groups) {
addEntry(entry.getKey(), entry.getValue(), quests);
}

GROUPS.addAll(groups);
updateGroupsWithOrder(groups);

for (QuestEntry value : ENTRIES.values()) {
for (String s : value.value.display().groups().keySet()) {
BY_GROUPS.computeIfAbsent(s, k -> new ArrayList<>()).add(value);
}
}
}

public static void syncGroupOrders(List<String> groupOrders) {
GROUP_ORDERS.clear();
GROUP_ORDERS.addAll(groupOrders);
updateGroupsWithOrder(new LinkedHashMap<>(GROUPS));
}

public static void updateGroupsWithOrder(Map<String, Group> groups) {
GROUPS.clear();
for (String id : ClientQuests.GROUP_ORDERS) {
Group group = groups.get(id);
if (group == null) continue;
GROUPS.put(id, group);
}

for (var entry : groups.entrySet()) {
if (GROUPS.containsKey(entry.getKey())) continue;
GROUPS.put(entry.getKey(), entry.getValue());
}
}

public static void syncDescriptions(Map<String, String> descriptions) {
for (Map.Entry<String, String> entry : descriptions.entrySet()) {
get(entry.getKey())
Expand Down Expand Up @@ -126,6 +149,10 @@ public static Collection<QuestEntry> entries() {
return ENTRIES.values();
}

public static List<String> groupOrders() {
return GROUP_ORDERS;
}

public static QuestProgress getProgress(String id) {
return PROGRESS.get(id);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package earth.terrarium.heracles.client.screens;

import com.mojang.blaze3d.systems.RenderSystem;
import com.teamresourceful.resourcefullib.client.screens.BaseCursorScreen;
import com.teamresourceful.resourcefullib.client.screens.PriorityScreen;
import earth.terrarium.heracles.Heracles;
import earth.terrarium.heracles.api.client.theme.QuestsScreenTheme;
import earth.terrarium.heracles.client.utils.ClientUtils;
Expand All @@ -23,7 +23,7 @@
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractQuestScreen<T> extends BaseCursorScreen {
public abstract class AbstractQuestScreen<T> extends PriorityScreen {

public static final ResourceLocation HEADING = new ResourceLocation(Heracles.MOD_ID, "textures/gui/heading.png");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package earth.terrarium.heracles.client.screens.quests;

import com.teamresourceful.resourcefullib.client.components.context.ContextMenu;

public class GroupsContextMenu extends ContextMenu {

@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (this.visible && this.active) {
return super.mouseClicked(mouseX, mouseY, button);
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,50 @@
package earth.terrarium.heracles.client.screens.quests;

import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.systems.RenderSystem;
import com.teamresourceful.resourcefullib.client.components.context.ContextMenu;
import com.teamresourceful.resourcefullib.client.components.context.ContextualMenuScreen;
import com.teamresourceful.resourcefullib.client.components.selection.ListEntry;
import com.teamresourceful.resourcefullib.client.components.selection.SelectionList;
import com.teamresourceful.resourcefullib.client.scissor.ScissorBoxStack;
import com.teamresourceful.resourcefullib.client.screens.CursorScreen;
import com.teamresourceful.resourcefullib.client.utils.CursorUtils;
import com.teamresourceful.resourcefullib.client.utils.ScreenUtils;
import earth.terrarium.heracles.api.client.theme.QuestsScreenTheme;
import earth.terrarium.heracles.api.groups.Group;
import earth.terrarium.heracles.api.quests.QuestIcon;
import earth.terrarium.heracles.api.quests.defaults.ItemQuestIcon;
import earth.terrarium.heracles.client.handlers.ClientQuests;
import earth.terrarium.heracles.client.screens.AbstractQuestScreen;
import earth.terrarium.heracles.client.utils.ClientUtils;
import earth.terrarium.heracles.client.utils.MouseClick;
import earth.terrarium.heracles.common.constants.ConstantComponents;
import earth.terrarium.heracles.common.network.NetworkHandler;
import earth.terrarium.heracles.common.network.packets.groups.DeleteGroupPacket;
import earth.terrarium.heracles.common.network.packets.groups.EditGroupPacket;
import earth.terrarium.heracles.common.network.packets.quests.ServerboundUpdateGroupOrderPacket;
import earth.terrarium.heracles.common.utils.ItemValue;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvents;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.function.Consumer;

public class GroupsList extends SelectionList<GroupsList.Entry> {

private final int width;
private final Consumer<@Nullable Entry> onSelection;
private final int x;

public GroupsList(int x, int y, int width, int height, Consumer<@Nullable Entry> onSelection) {
super(x, y, width, height, 20, onSelection, true);
super(x, y, width, height, 20, entry -> {}, true);
this.x = x;
this.onSelection = onSelection;
this.width = width;
}

Expand All @@ -44,12 +59,12 @@ private void internalSetSelected(@Nullable Entry entry) {
super.setSelected(entry);
}

public void update(List<String> groups, String selected) {
public void update(Map<String, Group> groups, String selected) {
List<Entry> entries = new ArrayList<>(groups.size());
Entry selectedEntry = null;
for (String group : groups) {
Entry entry = new Entry(this, group);
if (group.equals(selected)) {
for (var group : groups.entrySet()) {
Entry entry = new Entry(this, group.getKey(), group.getValue());
if (group.getKey().equals(selected)) {
selectedEntry = entry;
}
entries.add(entry);
Expand All @@ -60,18 +75,24 @@ public void update(List<String> groups, String selected) {
}
}

public void addGroup(String group) {
addEntry(new Entry(this, group));
public void updateOrder() {
update(ClientQuests.groups(), getSelected() == null ? null : getSelected().name());
}

public void addGroup(String id, Group group) {
addEntry(new Entry(this, id, group));
}

public static class Entry extends ListEntry {

private final GroupsList list;
private final String name;
private Group group;

public Entry(GroupsList list, String name) {
public Entry(GroupsList list, String name, Group group) {
this.list = list;
this.name = name;
this.group = group;
}

@Override
Expand All @@ -82,7 +103,13 @@ protected void render(@NotNull GuiGraphics graphics, @NotNull ScissorBoxStack sc
graphics.blitNineSliced(AbstractQuestScreen.HEADING, left, top, width, height, 5, 64, 20, 192, 55);
}
RenderSystem.disableBlend();
graphics.drawCenteredString(Minecraft.getInstance().font, name, left + width / 2, top + height / 2 - 4, QuestsScreenTheme.getGroupName());
int x = left + 5;
if (group.icon().isPresent()) {
int size = height - 2;
group.icon().get().render(graphics, scissorStack, x, top + 1 + ((size - 16) / 2), size, size);
}
x += height;
graphics.drawString(Minecraft.getInstance().font, Component.translatable(group.title()), x, top + height / 2 - 4, QuestsScreenTheme.getGroupName());
CursorUtils.setCursor(hovered, CursorScreen.Cursor.POINTER);
if (Minecraft.getInstance().screen instanceof QuestsEditScreen) {
if (mouseX - left >= width - 11 && mouseX - left <= width - 2 && mouseY - top >= 2 && mouseY - top <= 12 && hovered) {
Expand All @@ -106,9 +133,10 @@ protected void render(@NotNull GuiGraphics graphics, @NotNull ScissorBoxStack sc

@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (this.list.getSelected() != this) Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
if (this.list.getSelected() != this)
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
boolean cant = !ClientQuests.byGroup(name).isEmpty() || this.list.children().size() == 1;
if (Minecraft.getInstance().screen instanceof QuestsEditScreen screen && button == 0 && !cant) {
if (Minecraft.getInstance().screen instanceof QuestsEditScreen screen && button == InputConstants.MOUSE_BUTTON_LEFT && !cant) {
boolean closingButton = mouseX >= this.list.width - 11 && mouseX <= this.list.width - 2 && mouseY >= 2 && mouseY <= 12;
if (closingButton) {
screen.confirmModal().setVisible(true);
Expand All @@ -129,6 +157,62 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
return true;
}
}
if (button == InputConstants.MOUSE_BUTTON_RIGHT) {
MouseClick mouse = ClientUtils.getMousePos();
Optional<ContextMenu> menu = ContextualMenuScreen.getMenu();
if (menu.isPresent()) {
menu.get()
.start(this.list.x + this.list.width + 6, mouse.y())
.addOption(Component.literal("\uD83D\uDCAC Edit Name"), () -> {
if (Minecraft.getInstance().screen instanceof QuestsEditScreen screen) {
screen.textModal().setVisible(true);
screen.textModal().setText(this.group.title());
screen.textModal().setCallback((unused, text) -> {
this.group = this.group.withTitle(text);
NetworkHandler.CHANNEL.sendToServer(EditGroupPacket.ofTitle(name, text));
screen.textModal().setVisible(false);
});
}
})
.addOption(Component.literal("\uD83D\uDDBC Edit Icon"), () -> {
if (Minecraft.getInstance().screen instanceof QuestsEditScreen screen) {
screen.itemModal().setVisible(true);
screen.itemModal().setCallback(item -> {
QuestIcon<?> icon = new ItemQuestIcon(new ItemValue(item));
this.group = this.group.withIcon(icon);
NetworkHandler.CHANNEL.sendToServer(EditGroupPacket.ofIcon(name, icon));
screen.itemModal().setVisible(false);
});
}
})
.addDivider()
.addOption(Component.literal("⬆ Move Up"), () -> {
int currentIndex = ClientQuests.groupOrders().indexOf(name);
if (currentIndex > 0) {
String previous = ClientQuests.groupOrders().get(currentIndex - 1);
ClientQuests.groupOrders().set(currentIndex - 1, name);
ClientQuests.groupOrders().set(currentIndex, previous);
ClientQuests.updateGroupsWithOrder(new LinkedHashMap<>(ClientQuests.groups()));
this.list.updateOrder();
NetworkHandler.CHANNEL.sendToServer(new ServerboundUpdateGroupOrderPacket(ClientQuests.groupOrders()));
}
})
.addOption(Component.literal("⬇ Move Down"), () -> {
int currentIndex = ClientQuests.groupOrders().indexOf(name);
if (currentIndex < ClientQuests.groupOrders().size() - 1) {
String next = ClientQuests.groupOrders().get(currentIndex + 1);
ClientQuests.groupOrders().set(currentIndex + 1, name);
ClientQuests.groupOrders().set(currentIndex, next);
ClientQuests.updateGroupsWithOrder(new LinkedHashMap<>(ClientQuests.groups()));
this.list.updateOrder();
NetworkHandler.CHANNEL.sendToServer(new ServerboundUpdateGroupOrderPacket(ClientQuests.groupOrders()));
}
})
.open();
return true;
}
}
this.list.onSelection.accept(this);
return super.mouseClicked(mouseX, mouseY, button);
}

Expand Down
Loading