diff options
Diffstat (limited to 'src')
6 files changed, 280 insertions, 33 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/events/EventNotifications.java b/src/main/java/de/hysky/skyblocker/skyblock/events/EventNotifications.java index 1d5761a5..ad85e7da 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/events/EventNotifications.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/events/EventNotifications.java @@ -3,15 +3,19 @@ package de.hysky.skyblocker.skyblock.events; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.logging.LogUtils; import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.events.SkyblockEvents; import de.hysky.skyblocker.utils.Http; import de.hysky.skyblocker.utils.scheduler.Scheduler; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.toast.SystemToast; -import net.minecraft.text.Text; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import org.apache.commons.lang3.builder.ToStringBuilder; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -24,10 +28,42 @@ public class EventNotifications { private static long currentTime = System.currentTimeMillis() / 1000; + public static final Map<String, ItemStack> eventIcons = new Object2ObjectOpenHashMap<>(); + + static { + eventIcons.put("Dark Auction", new ItemStack(Items.NETHER_BRICK)); + eventIcons.put("Bonus Fishing Festival", new ItemStack(Items.FISHING_ROD)); + eventIcons.put("Bonus Mining Fiesta", new ItemStack(Items.IRON_PICKAXE)); + eventIcons.put("Jacob's Farming Contest", new ItemStack(Items.IRON_HOE)); + eventIcons.put("New Year Celebration", new ItemStack(Items.CAKE)); + eventIcons.put("Election Over!", new ItemStack(Items.JUKEBOX)); + eventIcons.put("Election Booth Opens", new ItemStack(Items.JUKEBOX)); + eventIcons.put("Spooky Festival", new ItemStack(Items.JACK_O_LANTERN)); + eventIcons.put("Season of Jerry", new ItemStack(Items.SNOWBALL)); + eventIcons.put("Jerry's Workshop Opens", new ItemStack(Items.SNOW_BLOCK)); + eventIcons.put("Traveling Zoo", new ItemStack(Items.HAY_BLOCK)); // change to the custom head one day + } + public static void init() { Scheduler.INSTANCE.scheduleCyclic(EventNotifications::timeUpdate, 20); SkyblockEvents.JOIN.register(EventNotifications::refreshEvents); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register( + ClientCommandManager.literal("skyblocker").then( + ClientCommandManager.literal("ye").then( + ClientCommandManager.argument("time", IntegerArgumentType.integer(6)).executes(context -> { + MinecraftClient.getInstance().getToastManager().add( + new EventToast(System.currentTimeMillis() / 1000 + context.getArgument("time", int.class), "Jacob's or something idk", new ItemStack(Items.PAPER)) + ); + return 0; + }) + ).executes(context -> { + MinecraftClient.getInstance().getToastManager().add( + new JacobEventToast(System.currentTimeMillis() / 1000 + 60, "Jacob's farming contest", new String[]{"Cactus","Cocoa Beans","Pumpkin"}) + ); + return 0;}) + ) + )); } private static final Map<String, LinkedList<SkyblockEvent>> events = new Object2ObjectOpenHashMap<>(); @@ -59,6 +95,9 @@ public class EventNotifications { private static void timeUpdate() { + List<Integer> reminderTimes = SkyblockerConfigManager.get().general.eventNotifications.reminderTimes; + if (reminderTimes.isEmpty()) return; + long newTime = System.currentTimeMillis() / 1000; for (Map.Entry<String, LinkedList<SkyblockEvent>> entry : events.entrySet()) { LinkedList<SkyblockEvent> nextEvents = entry.getValue(); @@ -69,11 +108,21 @@ public class EventNotifications { skyblockEvent = nextEvents.peekFirst(); if (skyblockEvent == null) continue; } - if (currentTime + 60 < skyblockEvent.start() && newTime + 60 >= skyblockEvent.start()) { - MinecraftClient.getInstance().getToastManager().add(new SystemToast( - SystemToast.Type.PERIODIC_NOTIFICATION, - Text.literal(entry.getKey()), - Text.literal("Starting soon!"))); + String eventName = entry.getKey(); + + for (Integer reminderTime : reminderTimes) { + if (currentTime + reminderTime < skyblockEvent.start() && newTime + reminderTime >= skyblockEvent.start()) { + if (eventName.equals("Jacob's Farming Contest")) { + MinecraftClient.getInstance().getToastManager().add( + new JacobEventToast(skyblockEvent.start(), eventName, skyblockEvent.extras()) + ); + } + else { + MinecraftClient.getInstance().getToastManager().add( + new EventToast(skyblockEvent.start(), eventName, eventIcons.getOrDefault(eventName, new ItemStack(Items.PAPER))) + ); + } + } } } currentTime = newTime; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java b/src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java index 4a0d139b..bd44c0a5 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java @@ -1,13 +1,13 @@ package de.hysky.skyblocker.skyblock.events; import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.utils.Utils; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.toast.Toast; import net.minecraft.client.toast.ToastManager; import net.minecraft.item.ItemStack; -import net.minecraft.screen.ScreenTexts; import net.minecraft.text.MutableText; import net.minecraft.text.OrderedText; import net.minecraft.text.Text; @@ -18,17 +18,20 @@ import net.minecraft.util.Identifier; import java.util.List; public class EventToast implements Toast { - private static final Identifier TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "notification"); + protected static final Identifier TEXTURE = new Identifier(SkyblockerMod.NAMESPACE, "notification"); private final long eventStartTime; - private final List<OrderedText> message; - private final ItemStack icon; + protected final List<OrderedText> message; + protected final int messageWidth; + protected final ItemStack icon; public EventToast(long eventStartTime, String name, ItemStack icon) { this.eventStartTime = eventStartTime; MutableText formatted = Text.translatable("skyblocker.events.startsSoon", Text.literal(name).formatted(Formatting.YELLOW)).formatted(Formatting.WHITE); - message = MinecraftClient.getInstance().textRenderer.wrapLines(formatted, 200); + TextRenderer renderer = MinecraftClient.getInstance().textRenderer; + message = renderer.wrapLines(formatted, 150); + messageWidth = message.stream().mapToInt(renderer::getWidth).max().orElse(150); this.icon = icon; } @@ -36,41 +39,40 @@ public class EventToast implements Toast { public Visibility draw(DrawContext context, ToastManager manager, long startTime) { context.drawGuiTexture(TEXTURE, 0, 0, getWidth(), getHeight()); - long currentTime = System.currentTimeMillis() / 1000; - int timeTillEvent = (int) (eventStartTime - currentTime); + int y = 7; + y = 2 + drawMessage(context, 30, y, Colors.WHITE); + drawTimer(context, 30, y); - int seconds = timeTillEvent % 60; - int minutes = (timeTillEvent/60) % 60; - int hours = (timeTillEvent/3600) % 24; - - MutableText time = Text.empty(); - if (hours > 0) { - time.append(hours + "h").append(" "); - } - if (hours > 0 || minutes > 0) { - time.append(minutes + "m").append(" "); - } - time.append(seconds + "s"); + context.drawItemWithoutEntity(icon, 8, getHeight()/2 - 8); + return startTime > 5_000 ? Visibility.HIDE: Visibility.SHOW; + } - int y = 4; + protected int drawMessage(DrawContext context, int x, int y, int color) { TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; for (OrderedText orderedText : message) { - context.drawText(textRenderer, orderedText, 30, y, Colors.WHITE, false); + context.drawText(textRenderer, orderedText, x, y, color, false); y += textRenderer.fontHeight; } - context.drawText(textRenderer, time, 30, y, Colors.LIGHT_YELLOW, false); + return y; + } - context.drawItemWithoutEntity(icon, 8, getHeight()/2 - 8); - return startTime > 5_000 ? Visibility.HIDE: Visibility.SHOW; + protected void drawTimer(DrawContext context, int x, int y) { + long currentTime = System.currentTimeMillis() / 1000; + int timeTillEvent = (int) (eventStartTime - currentTime); + + Text time = timeTillEvent < 0 ? Text.literal("Starts now!"): Utils.getDurationText(timeTillEvent); + + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawText(textRenderer, time, x, y, Colors.LIGHT_YELLOW, false); } @Override public int getWidth() { - return 200 + 30 + 5; + return messageWidth + 30 + 6; } @Override public int getHeight() { - return 8 + 9 + message.size()*9; + return 12 + 2 + (message.size()+1)*9; } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/events/JacobEventToast.java b/src/main/java/de/hysky/skyblocker/skyblock/events/JacobEventToast.java new file mode 100644 index 00000000..4f9c3fd7 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/events/JacobEventToast.java @@ -0,0 +1,71 @@ +package de.hysky.skyblocker.skyblock.events; + +import com.mojang.blaze3d.platform.GlStateManager; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.toast.ToastManager; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Colors; +import net.minecraft.util.math.MathHelper; + +import java.util.HashMap; +import java.util.Map; + +public class JacobEventToast extends EventToast{ + + private final String[] crops; + + private static final Map<String, ItemStack> cropItems = new HashMap<>(); + + static { + cropItems.put("Wheat", new ItemStack(Items.WHEAT)); + cropItems.put("Mushroom", new ItemStack(Items.RED_MUSHROOM)); + cropItems.put("Pumpkin", new ItemStack(Items.CARVED_PUMPKIN)); + cropItems.put("Melon", new ItemStack(Items.MELON)); + cropItems.put("Sugar Cane", new ItemStack(Items.SUGAR_CANE)); + cropItems.put("Cactus", new ItemStack(Items.CACTUS)); + cropItems.put("Carrot", new ItemStack(Items.CARROT)); + cropItems.put("Cocoa Beans", new ItemStack(Items.COCOA_BEANS)); + cropItems.put("Potato", new ItemStack(Items.POTATO)); + cropItems.put("Nether Wart", new ItemStack(Items.NETHER_WART)); + } + + public JacobEventToast(long eventStartTime, String name, String[] crops) { + super(eventStartTime, name, new ItemStack(Items.IRON_HOE)); + this.crops = crops; + } + + @Override + public Visibility draw(DrawContext context, ToastManager manager, long startTime) { + context.drawGuiTexture(TEXTURE, 0, 0, getWidth(), getHeight()); + + int y = 7; + TextRenderer textRenderer = manager.getClient().textRenderer; + if (startTime < 3_000){ + int k = MathHelper.floor(MathHelper.clamp((3_000 - startTime) / 200.0f, 0.0f, 1.0f) * 255.0f) << 24 | 0x4000000; + y = 2 + drawMessage(context, 30, y, 0xFFFFFF | k); + } else { + int k = (~MathHelper.floor(MathHelper.clamp((startTime - 3_000) / 200.0f, 0.0f, 1.0f) * 255.0f)) << 24 | 0x4000000; + + + String s = "Crops:"; + int x = 30 + textRenderer.getWidth(s) + 4; + context.drawText(textRenderer, s, 30, 7 + (16 - textRenderer.fontHeight)/2, Colors.WHITE, false); + for (int i = 0; i < crops.length; i++) { + context.drawItem(cropItems.get(crops[i]), x + i * (16 + 8), 7); + } + context.fill(30, 6, 30 + messageWidth, 22, 400, 0x212121 | k); + y += textRenderer.fontHeight * message.size(); + } + drawTimer(context, 30, y); + + context.drawItemWithoutEntity(icon, 8, getHeight()/2 - 8); + return startTime > 5_000 ? Visibility.HIDE: Visibility.SHOW; + } + + @Override + public int getHeight() { + return Math.max(super.getHeight(), 32); + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java index 62a3b897..8316bb9c 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Utils.java +++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java @@ -19,6 +19,7 @@ import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.scoreboard.*; +import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import org.jetbrains.annotations.NotNull; @@ -355,6 +356,22 @@ public class Utils { } } + public static Text getDurationText(int timeInSeconds) { + int seconds = timeInSeconds % 60; + int minutes = (timeInSeconds/60) % 60; + int hours = (timeInSeconds/3600) % 24; + + MutableText time = Text.empty(); + if (hours > 0) { + time.append(hours + "h").append(" "); + } + if (hours > 0 || minutes > 0) { + time.append(minutes + "m").append(" "); + } + time.append(seconds + "s"); + return time; + } + private static void updateFromPlayerList(MinecraftClient client) { if (client.getNetworkHandler() == null) { return; diff --git a/src/main/java/de/hysky/skyblocker/utils/config/DurationController.java b/src/main/java/de/hysky/skyblocker/utils/config/DurationController.java new file mode 100644 index 00000000..09edcf3c --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/config/DurationController.java @@ -0,0 +1,70 @@ +package de.hysky.skyblocker.utils.config; + +import de.hysky.skyblocker.utils.Utils; +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.utils.Dimension; +import dev.isxander.yacl3.gui.AbstractWidget; +import dev.isxander.yacl3.gui.YACLScreen; +import dev.isxander.yacl3.gui.controllers.string.IStringController; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public record DurationController(Option<Integer> option) implements IStringController<Integer> { + + private static final Pattern secondsPattern = Pattern.compile("(^|\\s)(\\d+)s(\\s|$)"); + private static final Pattern minutesPattern = Pattern.compile("(^|\\s)(\\d+)m(\\s|$)"); + private static final Pattern hoursPattern = Pattern.compile("(^|\\s)(\\d+)h(\\s|$)"); + + @Override + public String getString() { + return Utils.getDurationText(option.pendingValue()).getString(); + } + + + @Override + public void setFromString(String value) { + Matcher hoursMatcher = hoursPattern.matcher(value); + Matcher minutesMatcher = minutesPattern.matcher(value); + Matcher secondsMatcher = secondsPattern.matcher(value); + + int result = 0; + if (hoursMatcher.find()) { + result += Integer.parseInt(hoursMatcher.group(2)) * 3600; + } + if (minutesMatcher.find()) { + result += Integer.parseInt(minutesMatcher.group(2)) * 60; + } + if (secondsMatcher.find()) { + result += Integer.parseInt(secondsMatcher.group(2)); + } + option.requestSet(result); + } + + + @Override + public boolean isInputValid(String s) { + Matcher hoursMatcher = hoursPattern.matcher(s); + Matcher minutesMatcher = minutesPattern.matcher(s); + Matcher secondsMatcher = secondsPattern.matcher(s); + + int hoursCount = 0; + while (hoursMatcher.find()) hoursCount++; + int minutesCount = 0; + while (minutesMatcher.find()) minutesCount++; + int secondsCount = 0; + while (secondsMatcher.find()) secondsCount++; + + if (hoursCount == 0 && minutesCount == 0 && secondsCount == 0) return false; + if (hoursCount > 1 || minutesCount > 1 || secondsCount > 1) return false; + s = s.replaceAll(hoursPattern.pattern(), ""); + s = s.replaceAll(minutesPattern.pattern(), ""); + s = s.replaceAll(secondsPattern.pattern(), ""); + return s.isBlank(); + } + + @Override + public AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension) { + return new DurationControllerWidget(this, screen, widgetDimension); + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/config/DurationControllerWidget.java b/src/main/java/de/hysky/skyblocker/utils/config/DurationControllerWidget.java new file mode 100644 index 00000000..f25cd088 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/config/DurationControllerWidget.java @@ -0,0 +1,38 @@ +package de.hysky.skyblocker.utils.config; + +import dev.isxander.yacl3.api.utils.Dimension; +import dev.isxander.yacl3.gui.YACLScreen; +import dev.isxander.yacl3.gui.controllers.string.IStringController; +import dev.isxander.yacl3.gui.controllers.string.StringControllerElement; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.function.Consumer; + +public class DurationControllerWidget extends StringControllerElement { + + public DurationControllerWidget(IStringController<?> control, YACLScreen screen, Dimension<Integer> dim) { + super(control, screen, dim, false); + } + + @Override + public void unfocus() { + if (control.isInputValid(inputField)) super.unfocus(); + else modifyInput(stringBuilder -> stringBuilder.replace(0, stringBuilder.length(), control.getString())); + } + + @Override + public boolean modifyInput(Consumer<StringBuilder> consumer) { + StringBuilder temp = new StringBuilder(inputField); + consumer.accept(temp); + inputField = temp.toString(); + return true; + } + + @Override + protected Text getValueText() { + Text valueText = super.getValueText(); + boolean inputValid = control.isInputValid(valueText.getString()); + return valueText.copy().formatted(inputValid ? Formatting.WHITE: Formatting.RED); + } +} |