Skip to content

Commit

Permalink
Migrate to json for groups and add icon editing
Browse files Browse the repository at this point in the history
  • Loading branch information
ThatGravyBoat committed Nov 9, 2023
1 parent 5072d77 commit f66210c
Show file tree
Hide file tree
Showing 13 changed files with 228 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
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 net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.util.ExtraCodecs;

import java.util.Optional;

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

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

public Group(String id) {
this(Optional.empty(), Component.nullToEmpty(id), CommonComponents.EMPTY);
}

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

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

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

@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public Group edit(Optional<QuestIcon<?>> icon, Optional<Component> title, Optional<Component> description) {
return new Group(
this.icon.or(() -> icon),
title.orElse(this.title),
description.orElse(this.description)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,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,19 @@ 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 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,7 +37,7 @@ public static void sync(Map<String, Quest> quests, List<String> groups) {
addEntry(entry.getKey(), entry.getValue(), quests);
}

GROUPS.addAll(groups);
GROUPS.putAll(groups);
for (QuestEntry value : ENTRIES.values()) {
for (String s : value.value.display().groups().keySet()) {
BY_GROUPS.computeIfAbsent(s, k -> new ArrayList<>()).add(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
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.groups.Group;
import earth.terrarium.heracles.api.quests.defaults.ItemQuestIcon;
import earth.terrarium.heracles.client.handlers.ClientQuests;
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.utils.ItemValue;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
Expand All @@ -22,6 +26,8 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;

public class GroupsList extends SelectionList<GroupsList.Entry> {
Expand All @@ -48,12 +54,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 @@ -64,27 +70,36 @@ public void update(List<String> groups, String selected) {
}
}

public void addGroup(String group) {
addEntry(new Entry(this, group));
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
@SuppressWarnings("SuspiciousNameCombination")
protected void render(@NotNull GuiGraphics graphics, @NotNull ScissorBoxStack scissorStack, int id, int left, int top, int width, int height, int mouseX, int mouseY, boolean hovered, float partialTick, boolean selected) {
graphics.fill(left, top, left + width, top + height, selected ? 0x22FFFFFF : 0x22808080);
if (hovered) {
graphics.renderOutline(left, top, width, height, 0x44FFFFFF);
}
graphics.drawCenteredString(Minecraft.getInstance().font, name, left + width / 2, top + height / 2 - 4, 0xFFFFFF);
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, name, x, top + height / 2 - 4, 0xFFFFFF);
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 Down Expand Up @@ -134,9 +149,21 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
MouseClick mouse = ClientUtils.getMousePos();
ContextualMenuScreen.getMenu()
.ifPresent(menu -> menu.start(this.list.x + this.list.width + 6, mouse.y())
.addOption(Component.literal("\uD83D\uDDBC Edit Icon"), () ->
System.out.println("Edit Icon") //TODO
)
.addOption(Component.literal("\uD83D\uDDBC Edit Icon"), () -> {
if (Minecraft.getInstance().screen instanceof QuestsEditScreen screen) {
screen.itemModal().setVisible(true);
screen.itemModal().setCallback(item -> {
this.group = this.group.withIcon(new ItemQuestIcon(new ItemValue(item)));
NetworkHandler.CHANNEL.sendToServer(new EditGroupPacket(
name,
this.group.icon(),
Optional.empty(),
Optional.empty()
));
screen.itemModal().setVisible(false);
});
}
})
.addDivider()
.addOption(Component.literal("⬆ Move Up"), () ->
System.out.println("Move UP") //TODO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.mojang.blaze3d.platform.InputConstants;
import com.teamresourceful.resourcefullib.client.components.context.ContextualMenuScreen;
import com.teamresourceful.resourcefullib.client.components.context.ContextMenu;
import earth.terrarium.heracles.api.groups.Group;
import earth.terrarium.heracles.api.quests.GroupDisplay;
import earth.terrarium.heracles.api.quests.Quest;
import earth.terrarium.heracles.api.quests.QuestDisplay;
Expand Down Expand Up @@ -100,12 +101,12 @@ protected void init() {

this.uploadModal = addTemporary(new UploadModal(this.width, this.height));
this.groupModal = addTemporary(new TextInputModal<>(this.width, this.height, ConstantComponents.Groups.CREATE, (ignored, text) -> {
NetworkHandler.CHANNEL.sendToServer(new CreateGroupPacket(text));
ClientQuests.groups().add(text);
NetworkHandler.CHANNEL.sendToServer(new CreateGroupPacket(text.trim()));
ClientQuests.groups().put(text.trim(), new Group(text.trim()));
if (Minecraft.getInstance().screen instanceof QuestsScreen screen) {
screen.getGroupsList().addGroup(text);
screen.getGroupsList().addGroup(text.trim(), new Group(text.trim()));
}
}, text -> !ClientQuests.groups().contains(text.trim())));
}, text -> !ClientQuests.groups().containsKey(text.trim())));
this.iconBackgroundModal = addTemporary(new IconBackgroundModal(this.width, this.height));
this.itemModal = addTemporary(new ItemModal(this.width, this.height));
this.dependencyModal = addTemporary(new AddDependencyModal(this.width, this.height));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
import com.google.common.collect.Sets;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.teamresourceful.resourcefullib.common.lib.Constants;
import com.teamresourceful.resourcefullib.common.utils.FileUtils;
import com.teamresourceful.resourcefullib.common.utils.Scheduling;
import earth.terrarium.heracles.Heracles;
import static earth.terrarium.heracles.Heracles.LOGGER;

import earth.terrarium.heracles.api.groups.Group;
import earth.terrarium.heracles.api.quests.Quest;
import earth.terrarium.heracles.common.utils.ModUtils;
import net.minecraft.core.RegistryAccess;
Expand All @@ -29,7 +32,7 @@ public class QuestHandler {

private static final Map<String, Quest> QUESTS = HashBiMap.create();
private static final Set<String> QUEST_KEYS = Sets.newConcurrentHashSet();
private static final List<String> GROUPS = new ArrayList<>();
private static final Map<String, Group> GROUPS = new LinkedHashMap<>();
private static Path lastPath;

private static final Map<String, ScheduledFuture<?>> SAVING_FUTURES = new HashMap<>();
Expand Down Expand Up @@ -59,7 +62,7 @@ public static void load(RegistryAccess access, Path path) {
for (Quest value : QUESTS.values()) {
value.dependencies().removeIf(Predicate.not(QUESTS::containsKey));
}
loadGroups(heraclesPath.resolve("groups.txt").toFile());
loadGroups(heraclesPath);
}

private static void load(RegistryAccess access, Reader reader, String id, Map<String, Quest> quests) {
Expand All @@ -73,22 +76,43 @@ private static void load(RegistryAccess access, Reader reader, String id, Map<St
}
}

private static void loadGroups(File file) {
private static void loadGroups(Path path) {
GROUPS.clear();
if (file.exists()) {
File json = path.resolve("groups.json").toFile();
File txt = path.resolve("groups.txt").toFile();
boolean save = false;
if (json.exists()) {
try {
GROUPS.addAll(org.apache.commons.io.FileUtils.readLines(file, StandardCharsets.UTF_8));
Reader reader = Files.newBufferedReader(json.toPath());
JsonObject element = Constants.PRETTY_GSON.fromJson(reader, JsonObject.class);
Map<String, Group> groups = Codec.unboundedMap(Codec.STRING, Group.CODEC)
.parse(JsonOps.INSTANCE, element)
.getOrThrow(false, LOGGER::error);
GROUPS.putAll(groups);
} catch (Exception e) {
LOGGER.error("Failed to load quest groups", e);
}
} else if (txt.exists()) {
try {
for (String group : org.apache.commons.io.FileUtils.readLines(txt, StandardCharsets.UTF_8)) {
GROUPS.put(group, new Group(group));
}
Files.deleteIfExists(txt.toPath());
save = true;
} catch (Exception e) {
LOGGER.error("Failed to load quest groups", e);
}
}
for (Quest value : QUESTS.values()) {
for (String s : value.display().groups().keySet()) {
if (!GROUPS.contains(s)) {
GROUPS.add(s);
if (!GROUPS.containsKey(s)) {
GROUPS.put(s, new Group(s));
}
}
}
if (save) {
saveGroups();
}
}

public static void markDirty(String id) {
Expand Down Expand Up @@ -139,8 +163,11 @@ public static void saveGroups() {
return;
}
try {
File file = new File(lastPath.toFile(), "groups.txt");
org.apache.commons.io.FileUtils.writeLines(file, GROUPS);
File file = new File(lastPath.toFile(), "groups.json");
JsonElement json = Codec.unboundedMap(Codec.STRING, Group.CODEC)
.encodeStart(JsonOps.INSTANCE, GROUPS)
.getOrThrow(false, LOGGER::error);
org.apache.commons.io.FileUtils.write(file, Constants.PRETTY_GSON.toJson(json), StandardCharsets.UTF_8);
} catch (Exception e) {
LOGGER.error("Failed to save quest groups", e);
}
Expand Down Expand Up @@ -191,9 +218,9 @@ public static Map<String, Quest> quests() {
return QUESTS;
}

public static List<String> groups() {
public static Map<String, Group> groups() {
if (GROUPS.isEmpty()) {
GROUPS.add("Main");
GROUPS.put("main", new Group("Main"));
saveGroups();
}
return GROUPS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import earth.terrarium.heracles.common.network.packets.QuestUnlockedPacket;
import earth.terrarium.heracles.common.network.packets.groups.CreateGroupPacket;
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.groups.OpenGroupPacket;
import earth.terrarium.heracles.common.network.packets.pinned.SetPinnedQuestPacket;
import earth.terrarium.heracles.common.network.packets.pinned.SyncPinnedQuestsPacket;
Expand Down Expand Up @@ -51,5 +52,6 @@ public static void init() {
CHANNEL.registerPacket(NetworkDirection.CLIENT_TO_SERVER, CheckTaskPacket.ID, CheckTaskPacket.HANDLER, CheckTaskPacket.class);
CHANNEL.registerPacket(NetworkDirection.CLIENT_TO_SERVER, ManualItemTaskPacket.ID, ManualItemTaskPacket.HANDLER, ManualItemTaskPacket.class);
CHANNEL.registerPacket(NetworkDirection.CLIENT_TO_SERVER, ManualXpTaskPacket.ID, ManualXpTaskPacket.HANDLER, ManualXpTaskPacket.class);
CHANNEL.registerPacket(NetworkDirection.CLIENT_TO_SERVER, EditGroupPacket.ID, EditGroupPacket.HANDLER, EditGroupPacket.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.teamresourceful.resourcefullib.common.networking.base.PacketContext;
import com.teamresourceful.resourcefullib.common.networking.base.PacketHandler;
import earth.terrarium.heracles.Heracles;
import earth.terrarium.heracles.api.groups.Group;
import earth.terrarium.heracles.common.handlers.quests.QuestHandler;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
Expand Down Expand Up @@ -37,8 +38,8 @@ public CreateGroupPacket decode(FriendlyByteBuf buffer) {
@Override
public PacketContext handle(CreateGroupPacket message) {
return (player, level) -> {
if (player.hasPermissions(2) && !QuestHandler.groups().contains(message.group)) {
QuestHandler.groups().add(message.group);
if (player.hasPermissions(2) && !QuestHandler.groups().containsKey(message.group)) {
QuestHandler.groups().put(message.group, new Group(message.group));
QuestHandler.saveGroups();
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public DeleteGroupPacket decode(FriendlyByteBuf buffer) {
@Override
public PacketContext handle(DeleteGroupPacket message) {
return (player, level) -> {
if (player.hasPermissions(2) && QuestHandler.groups().contains(message.group)) {
if (player.hasPermissions(2) && QuestHandler.groups().containsKey(message.group)) {
QuestHandler.groups().remove(message.group);
QuestHandler.saveGroups();
}
Expand Down
Loading

0 comments on commit f66210c

Please sign in to comment.