Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -57,7 +57,7 @@
import org.slf4j.Logger;

public class SkyblockerConfigManager {
public static final int CONFIG_VERSION = 6;
public static final int CONFIG_VERSION = 7;
private static final Logger LOGGER = LogUtils.getLogger();
private static final Path CONFIG_DIR = FabricLoader.getInstance().getConfigDir();
private static final Path CONFIG_FILE = CONFIG_DIR.resolve("skyblocker.json");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
import de.hysky.skyblocker.config.ConfigUtils;
import de.hysky.skyblocker.config.SkyblockerConfig;
import de.hysky.skyblocker.config.configs.EventNotificationsConfig;
import de.hysky.skyblocker.config.screens.eventnotifications.EventConfigTimesEditScreen;
import de.hysky.skyblocker.skyblock.events.EventNotifications;
import de.hysky.skyblocker.utils.config.DurationController;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import net.azureaaron.dandelion.api.ButtonOption;
import net.azureaaron.dandelion.api.ConfigCategory;
import net.azureaaron.dandelion.api.LabelOption;
import net.azureaaron.dandelion.api.ListOption;
import net.azureaaron.dandelion.api.Option;
import net.azureaaron.dandelion.api.OptionGroup;
import net.azureaaron.dandelion.api.OptionListener.UpdateType;
Expand Down Expand Up @@ -61,21 +60,28 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig
}

private static List<OptionGroup> createGroups(SkyblockerConfig config) {
Map<String, IntArrayList> eventsReminderTimes = config.eventNotifications.eventsReminderTimes;
List<OptionGroup> groups = new ArrayList<>(eventsReminderTimes.size());
Map<String, EventNotificationsConfig.EventConfig> eventsReminderTimes = config.eventNotifications.events;
if (eventsReminderTimes.isEmpty()) return List.of(OptionGroup.createBuilder().option(LabelOption.createBuilder().label(Component.translatable("skyblocker.config.eventNotifications.monologue")).build()).build());
for (Map.Entry<String, IntArrayList> entry : eventsReminderTimes.entrySet()) {
groups.add(ListOption.<Integer>createBuilder()
List<OptionGroup> groups = new ArrayList<>(eventsReminderTimes.size());
for (Map.Entry<String, EventNotificationsConfig.EventConfig> entry : eventsReminderTimes.entrySet()) {
groups.add(OptionGroup.createBuilder()
.name(Component.literal(entry.getKey()))
.binding(EventNotifications.DEFAULT_REMINDERS, entry::getValue, integers -> entry.setValue(new IntArrayList(integers)))
.controller(new DurationController())
.description(Component.translatable("skyblocker.config.eventNotifications.@Tooltip[0]"),
Component.empty(),
Component.translatable("skyblocker.config.eventNotifications.@Tooltip[1]"),
Component.empty(),
Component.translatable("skyblocker.config.eventNotifications.@Tooltip[2]", entry.getKey()))
.initial(60)
.collapsed(true)
.option(Option.<Boolean>createBuilder()
.name(Component.translatable("skyblocker.config.eventNotifications.event.enabled", entry.getKey()))
.binding(EventNotifications.DEFAULT_REMINDERS.enabled,
() -> entry.getValue().enabled,
enabled -> entry.getValue().enabled = enabled
)
.controller(ConfigUtils.createBooleanController())
.build()
)
.option(ButtonOption.createBuilder()
.name(Component.translatable("skyblocker.config.eventNotifications.event.editReminders", entry.getKey()))
.prompt(Component.translatable("skyblocker.config.eventNotifications.event.editReminders.prompt"))
.description(Component.translatable("skyblocker.config.eventNotifications.event.editReminders.tooltip"))
.action(s -> Minecraft.getInstance().setScreen(new EventConfigTimesEditScreen(s, entry.getKey(), entry.getValue())))
.build()
)
.build()
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.hysky.skyblocker.config.configs;

import de.hysky.skyblocker.annotations.GenToString;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -13,7 +14,7 @@ public class EventNotificationsConfig {

public Sound reminderSound = Sound.PLING;

public Map<String, IntArrayList> eventsReminderTimes = new HashMap<>();
public Map<String, EventConfig> events = new HashMap<>();

public enum Criterion {
NONE,
Expand All @@ -27,6 +28,20 @@ public String toString() {
}
}

public static class EventConfig {
public boolean enabled;
public IntArrayList reminderTimes;

public EventConfig() {
enabled = true;
reminderTimes = new IntArrayList();
}

@GenToString
@Override
public native String toString();
}

public enum Sound {
NONE(null),
BELL(SoundEvents.BELL_BLOCK),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ private static DataFixer build() {
builder.addFixer(new ConfigFix4ChatRulesObject(schema5, true));
Schema schema6 = builder.addSchema(6, Schema::new);
builder.addFixer(new ConfigFix5ChatRulesSeparateOutputs(schema6, true));
Schema schema7 = builder.addSchema(7, Schema::new);
builder.addFixer(new ConfigFix6EventNotifications(schema7, true));

return dataFixer = builder.build().fixer();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package de.hysky.skyblocker.config.datafixer;

import com.mojang.datafixers.DSL;
import com.mojang.datafixers.TypeRewriteRule;
import com.mojang.datafixers.schemas.Schema;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Dynamic;

import java.util.Map;
import java.util.function.Function;

public class ConfigFix6EventNotifications extends ConfigDataFix {
public ConfigFix6EventNotifications(Schema outputSchema, boolean changesType) {
super(outputSchema, changesType);
}

@Override
protected TypeRewriteRule makeRule() {
return fixTypeEverywhereTyped(
getClass().getSimpleName(),
getInputSchema().getType(ConfigDataFixer.CONFIG_TYPE),
typed -> typed.update(DSL.remainderFinder(), this::fix)
);
}

private <T> Dynamic<T> fix(Dynamic<T> dynamic) {
return fixVersion(dynamic).update("eventNotifications", eventNotifications -> eventNotifications.renameAndFixField("eventsReminderTimes", "events", events -> events.updateMapValues(pair ->
Pair.of(pair.getFirst(), dynamic.createMap(Map.of(
dynamic.createString("enabled"), dynamic.createBoolean(!pair.getSecond().asList(Function.identity()).isEmpty()),
dynamic.createString("reminderTimes"), pair.getSecond()
))
))));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package de.hysky.skyblocker.config.screens.eventnotifications;

import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.config.configs.EventNotificationsConfig;
import de.hysky.skyblocker.utils.SkyblockTime;
import de.hysky.skyblocker.utils.config.DurationController;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.SpriteIconButton;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.resources.Identifier;
import net.minecraft.util.FormattedCharSequence;

import java.util.List;

public class EventConfigTimesEditScreen extends Screen {

private final EventNotificationsConfig.EventConfig eventConfig;
private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this);
private final Screen parent;
private EntryList list;

public EventConfigTimesEditScreen(Screen parent, String name, EventNotificationsConfig.EventConfig eventConfig) {
super(Component.translatable("skyblocker.config.eventNotifications.screen.title", name));
this.eventConfig = eventConfig;
this.parent = parent;
}

@Override
protected void init() {
super.init();
layout.addTitleHeader(getTitle(), font);
list = layout.addToContents(new EntryList(width, layout.getContentHeight(), 0, 24));
list.replaceEntries(eventConfig.reminderTimes.intStream().sorted().mapToObj(Entry::new).toList());

LinearLayout footerLayout = LinearLayout.horizontal().spacing(2);
footerLayout.addChild(Button.builder(Component.translatable("skyblocker.config.eventNotifications.screen.addReminder"), b -> list.addEntry(new Entry(5 * 60))).build());
footerLayout.addChild(Button.builder(CommonComponents.GUI_DONE, b -> onClose()).build());
layout.addToFooter(footerLayout);
layout.visitWidgets(this::addRenderableWidget);
repositionElements();
}

@Override
protected void repositionElements() {
list.updateSize(this.width, this.layout);
layout.arrangeElements();
}

@Override
public void onClose() {
SkyblockerConfigManager.update(c -> eventConfig.reminderTimes = list.children().stream()
.map(e -> e.box)
.filter(b -> b.valid)
.mapToInt(b -> b.seconds)
.sorted()
.collect(IntArrayList::new, IntArrayList::add, IntArrayList::addAll));
minecraft.setScreen(parent);
}

private class EntryList extends ContainerObjectSelectionList<EventConfigTimesEditScreen.Entry> {

private EntryList(int width, int height, int y, int itemHeight) {
super(EventConfigTimesEditScreen.this.minecraft, width, height, y, itemHeight);
}

@Override
protected void removeEntry(EventConfigTimesEditScreen.Entry entry) {
super.removeEntry(entry);
}

@Override
protected int addEntry(EventConfigTimesEditScreen.Entry entry) {
return super.addEntry(entry);
}
}

private class Entry extends ContainerObjectSelectionList.Entry<Entry> {
private static final Identifier DELETE_ICON = SkyblockerMod.id("trash_can");
private static final int ICON_WIDTH = 12, ICON_HEIGHT = 15;

private final TimeEditBox box;
private final List<AbstractWidget> widgets;
private final LinearLayout entryLayout = LinearLayout.horizontal().spacing(4);

private Entry(int seconds) {
box = new TimeEditBox(seconds);
Button buttonDelete = SpriteIconButton.builder(Component.translatable("selectServer.deleteButton"), ignored -> list.removeEntry(this), true).size(20, 20).sprite(DELETE_ICON, ICON_WIDTH, ICON_HEIGHT).build();
entryLayout.addChild(box);
entryLayout.addChild(buttonDelete);
entryLayout.arrangeElements();
widgets = List.of(box, buttonDelete);
}

@Override
public List<? extends NarratableEntry> narratables() {
return widgets;
}

@Override
public void renderContent(GuiGraphics guiGraphics, int i, int j, boolean bl, float f) {
entryLayout.setPosition(getContentRight() - entryLayout.getWidth(), getContentY());
for (AbstractWidget widget : widgets) {
widget.render(guiGraphics, i, j, f);
}
}

@Override
public List<? extends GuiEventListener> children() {
return widgets;
}
}

private static class TimeEditBox extends EditBox {

private int seconds;
private boolean valid = false;

TimeEditBox(int seconds) {
super(Minecraft.getInstance().font, 150, 20, Component.empty());
this.seconds = seconds;
setResponder(this::onUpdate);
setValue(SkyblockTime.formatTime(seconds).getString());
addFormatter((string, _firstCharacterIndex) -> FormattedCharSequence.forward(string, valid ? Style.EMPTY : Style.EMPTY.applyFormat(ChatFormatting.RED)));
}

private void onUpdate(String s) {
valid = DurationController.isValid(s);
if (valid) seconds = DurationController.fromString(s);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@NullMarked
package de.hysky.skyblocker.config.screens.eventnotifications;

import org.jspecify.annotations.NullMarked;
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.annotations.Init;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.config.configs.EventNotificationsConfig;
import de.hysky.skyblocker.events.SkyblockEvents;
import de.hysky.skyblocker.utils.Http;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.Minecraft;
Expand All @@ -37,7 +36,7 @@
public class EventNotifications {
private static final Logger LOGGER = LogUtils.getLogger();
public static final String JACOBS = "Jacob's Farming Contest";
public static final IntArrayList DEFAULT_REMINDERS = new IntArrayList(IntList.of(60, 60 * 5));
public static final EventNotificationsConfig.EventConfig DEFAULT_REMINDERS = new EventNotificationsConfig.EventConfig();
public static final Map<String, ItemStack> eventIcons = Map.ofEntries(
Map.entry("Dark Auction", new ItemStack(Items.NETHER_BRICK)),
Map.entry("Bonus Fishing Festival", new ItemStack(Items.FISHING_ROD)),
Expand Down Expand Up @@ -110,7 +109,7 @@ public static void refreshEvents() {

SkyblockerConfigManager.update(config -> {
for (String s : events.keySet()) {
config.eventNotifications.eventsReminderTimes.computeIfAbsent(s, s1 -> DEFAULT_REMINDERS);
config.eventNotifications.events.computeIfAbsent(s, s1 -> DEFAULT_REMINDERS);
}
});
}).exceptionally(EventNotifications::itBorked);
Expand All @@ -137,11 +136,10 @@ private static void timeUpdate() {
if (skyblockEvent == null) continue;
}
String eventName = entry.getKey();
// Cannot be changed to fast util due to casting issues
List<Integer> reminderTimes = SkyblockerConfigManager.get().eventNotifications.eventsReminderTimes.getOrDefault(eventName, DEFAULT_REMINDERS);
if (reminderTimes.isEmpty()) continue;
EventNotificationsConfig.EventConfig config = SkyblockerConfigManager.get().eventNotifications.events.getOrDefault(eventName, DEFAULT_REMINDERS);
if (!config.enabled) continue;

for (int reminderTime : reminderTimes) {
for (int reminderTime : config.reminderTimes) {
if (criterionMet() && currentTime + reminderTime < skyblockEvent.start() && newTime + reminderTime >= skyblockEvent.start()) {
Minecraft instance = Minecraft.getInstance();
if (eventName.equals(JACOBS)) {
Expand Down
Loading