diff --git a/TODO.md b/TODO.md index 826bb2f..5b35697 100644 --- a/TODO.md +++ b/TODO.md @@ -4,9 +4,9 @@ This file is basically a checklist of things to do in the codebase. ## Chores -* Add comments -* fix possible race condition so that the bot doesn't start with nonexistent ids +* parse timestamp message +* figure out the black magic of `ServerMessageEvents.GAME_MESSAGE` (?) ## Implement -* Performance improvements, don't know how yet \ No newline at end of file +* Performance improvements, don't know how yet diff --git a/build.gradle b/build.gradle index a783406..33f631d 100644 --- a/build.gradle +++ b/build.gradle @@ -69,7 +69,7 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 17 + it.options.release = 21 } java { diff --git a/gradle.properties b/gradle.properties index afa06d6..91934aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,18 +4,17 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.20.4 -yarn_mappings=1.20.4+build.3 +minecraft_version=1.21.1 +yarn_mappings=1.21.1+build.3 loader_version=0.16.10 +tserver_mcver=1.21.1 # Mod Properties -mod_version=1.0.0+fabric +mod_version=1.1.0+fabric.1.21.1 maven_group=com.github.pinmacaroon.dchook archives_base_name=dchook # Dependencies -fabric_version=0.97.2+1.20.4 - -owo_version=0.12.6+1.20.3 +fabric_version=0.116.7+1.21.1 org.gradle.warning.mode=None \ No newline at end of file diff --git a/src/main/java/com/github/pinmacaroon/dchook/Hook.java b/src/main/java/com/github/pinmacaroon/dchook/Hook.java index 97e5074..b6e2385 100644 --- a/src/main/java/com/github/pinmacaroon/dchook/Hook.java +++ b/src/main/java/com/github/pinmacaroon/dchook/Hook.java @@ -32,10 +32,10 @@ public class Hook implements DedicatedServerModInitializer { .create(); public static final Version VERSION = new Version.Builder() .setMajorVersion(1) - .setMinorVersion(0) + .setMinorVersion(1) .setPatchVersion(0) - .setBuildMetadata("fabric") - //.setPreReleaseVersion("alpha", "2") + .setBuildMetadata("fabric","1","21","1") +// .setPreReleaseVersion("newyear", "1") .build(); public static final String DOCS_URL = "https://modrinth.com/mod/dchook"; public static final Random RANDOM = new Random(Instant.now().getEpochSecond()); @@ -45,6 +45,7 @@ public class Hook implements DedicatedServerModInitializer { ); public static volatile Bot BOT; + public static boolean BOT_ENABLED = false; private static MinecraftServer MINECRAFT_SERVER; @@ -70,15 +71,8 @@ public void onInitializeServer() { return; } - if(ModConfigs.FUNCTIONS_BOT_ENABLED){ - try { - BOT = new Bot(ModConfigs.FUNCTIONS_BOT_TOKEN); - } catch (Exception e){ - LOGGER.error("couldn't initialise bot, two way chat disabled"); - LOGGER.error("{}:{}", e.getClass().getName(), e.getMessage()); - return; - } - } + if(ModConfigs.FUNCTIONS_BOT_ENABLED) bottedStart(); + else botlessStart(); try { HttpRequest get_webhook = HttpRequest.newBuilder() @@ -96,14 +90,16 @@ public void onInitializeServer() { ); return; } - Thread bot_rutime_thread = new Thread(() -> { - while (BOT == null) { - Thread.onSpinWait(); - } - BOT.setGUILD_ID(body.get("guild_id").getAsLong()); - BOT.setCHANNEL_ID(body.get("channel_id").getAsLong()); - }); - bot_rutime_thread.start(); + if (BOT_ENABLED) { + Thread bot_rutime_thread = new Thread(() -> { + while (BOT == null) { + Thread.onSpinWait(); + } + BOT.setGUILD_ID(body.get("guild_id").getAsLong()); + BOT.setCHANNEL_ID(body.get("channel_id").getAsLong()); + }); + bot_rutime_thread.start(); + } } catch (Exception e) { LOGGER.error("{}:{}", e.getClass().getName(), e.getMessage()); throw new RuntimeException(e); @@ -118,4 +114,19 @@ public void onInitializeServer() { EventListeners.registerEventListeners(); } + + private void botlessStart(){ + LOGGER.info("two way chat has been disabled by the config (botless start)"); + } + + private void bottedStart(){ + try { + BOT = new Bot(ModConfigs.FUNCTIONS_BOT_TOKEN); + BOT_ENABLED = true; + } catch (Exception e){ + LOGGER.error("couldn't initialise bot, two way chat disabled! please check your bot token or send a bug report on github!"); + LOGGER.error("{}:{}", e.getClass().getName(), e.getMessage()); + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/src/main/java/com/github/pinmacaroon/dchook/bot/CommandParser.java b/src/main/java/com/github/pinmacaroon/dchook/bot/CommandParser.java deleted file mode 100644 index 429f560..0000000 --- a/src/main/java/com/github/pinmacaroon/dchook/bot/CommandParser.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.github.pinmacaroon.dchook.bot; - -import java.util.ArrayList; -import java.util.List; - -/** - * im hella proud of this so it isn't going anywhere >:3 - */ -public class CommandParser { - - public static List parseString(String source) { - List parsed = new ArrayList<>(); - StringBuilder holder = new StringBuilder(); - boolean capture = false; - for (char i : source.toCharArray()) { - if (!(i == '\'' || i == '"' || i == ' ')) { - holder.append(i); - } else if (i == '\'' || i == '"') { - if (capture) { - capture = false; - parsed.add(holder.toString()); - holder.setLength(0); - } else { - parsed.add(holder.toString()); - holder.setLength(0); - capture = true; - } - } else { - if (capture) { - holder.append(i); - } else { - parsed.add(holder.toString()); - holder.setLength(0); - } - } - } - List scanned = new ArrayList<>(); - parsed.add(holder.toString()); - for (String i : parsed) { - if (i.isEmpty()) { - continue; - } - try { - scanned.add(Float.valueOf(i)); - } catch (NumberFormatException e) { - if (i.equals("true")) { - scanned.add(true); - } else if (i.equals("false")) { - scanned.add(false); - } else { - scanned.add(i.strip()); - } - } - } - return scanned; - } -} diff --git a/src/main/java/com/github/pinmacaroon/dchook/bot/commands/ListCommand.java b/src/main/java/com/github/pinmacaroon/dchook/bot/commands/ListCommand.java index ea50fbf..07260b8 100644 --- a/src/main/java/com/github/pinmacaroon/dchook/bot/commands/ListCommand.java +++ b/src/main/java/com/github/pinmacaroon/dchook/bot/commands/ListCommand.java @@ -1,21 +1,24 @@ package com.github.pinmacaroon.dchook.bot.commands; import com.github.pinmacaroon.dchook.Hook; +import com.github.pinmacaroon.dchook.conf.ModConfigs; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import java.text.MessageFormat; + public class ListCommand { public static void run(SlashCommandInteractionEvent event) { - StringBuilder list = new StringBuilder(); - list.append(""" - There are currently **%d**/%d players online:\s""".formatted( + StringBuilder message = new StringBuilder(); + message.append(MessageFormat.format( + ModConfigs.MESSAGES_BOT_LIST, Hook.getGameServer().getPlayerManager().getCurrentPlayerCount(), Hook.getGameServer().getPlayerManager().getMaxPlayerCount() )); Hook.getGameServer().getPlayerManager().getPlayerList().forEach( - serverPlayerEntity -> list.append("`").append(serverPlayerEntity.getName().getString()).append("` ") + serverPlayerEntity -> message.append("`").append(serverPlayerEntity.getName().getString()).append("` ") ); - event.reply(list.toString()).setEphemeral(event.getOption("ephemeral", false, OptionMapping::getAsBoolean)) + event.reply(message.toString()).setEphemeral(event.getOption("ephemeral", false, OptionMapping::getAsBoolean)) .queue(); } } diff --git a/src/main/java/com/github/pinmacaroon/dchook/bot/commands/ModsCommand.java b/src/main/java/com/github/pinmacaroon/dchook/bot/commands/ModsCommand.java index 69b975c..4790ad8 100644 --- a/src/main/java/com/github/pinmacaroon/dchook/bot/commands/ModsCommand.java +++ b/src/main/java/com/github/pinmacaroon/dchook/bot/commands/ModsCommand.java @@ -1,10 +1,12 @@ package com.github.pinmacaroon.dchook.bot.commands; +import com.github.pinmacaroon.dchook.conf.ModConfigs; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.ModEnvironment; +import java.text.MessageFormat; import java.util.concurrent.atomic.AtomicInteger; public class ModsCommand { @@ -24,9 +26,9 @@ public static void run(SlashCommandInteractionEvent event) { }); String response; if (mods_count.get() == 0) { - response = "The server currently has no required mods, you can join with a vanilla client!"; + response = ModConfigs.MESSAGES_BOT_MODS_NONE; } else { - response = "The server currently has " + mods_count.get() + " required mods:\n" + mod_list; + response = MessageFormat.format(ModConfigs.MESSAGES_BOT_MODS_LIST, mods_count.get()) + "\n" + mod_list; } if (response.length() > 2000) { response = response.substring(0, 1995) + "[...]"; diff --git a/src/main/java/com/github/pinmacaroon/dchook/bot/event/MessageReceivedListener.java b/src/main/java/com/github/pinmacaroon/dchook/bot/event/MessageReceivedListener.java index 185d1ce..81544ee 100644 --- a/src/main/java/com/github/pinmacaroon/dchook/bot/event/MessageReceivedListener.java +++ b/src/main/java/com/github/pinmacaroon/dchook/bot/event/MessageReceivedListener.java @@ -4,6 +4,7 @@ import com.github.pinmacaroon.dchook.bot.Bot; import com.github.pinmacaroon.dchook.conf.ModConfigs; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageReference; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.minecraft.text.MutableText; @@ -34,9 +35,10 @@ private static MutableText renderMessage(Message message) { MutableText reply; MutableText content; - if (message.getMessageReference() != null) { + MessageReference r = message.getMessageReference(); + if (r != null) { reply = Text.literal("<@%s -> ".formatted( - message.getReferencedMessage().getAuthor().getName() + r.getMessage().getAuthor().getName() )); } else { reply = Text.literal("<"); diff --git a/src/main/java/com/github/pinmacaroon/dchook/bot/event/SlashCommandInteractionListener.java b/src/main/java/com/github/pinmacaroon/dchook/bot/event/SlashCommandInteractionListener.java index 192e429..dcebc0c 100644 --- a/src/main/java/com/github/pinmacaroon/dchook/bot/event/SlashCommandInteractionListener.java +++ b/src/main/java/com/github/pinmacaroon/dchook/bot/event/SlashCommandInteractionListener.java @@ -28,7 +28,7 @@ public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent even case "about" -> AboutCommand.run(event); default -> event.reply(""" An internal error occurred! Please send a bug report: \ - """).setEphemeral(true) + """).setEphemeral(true) .addFiles(FileUpload.fromData(new File("https://pinmacaroon.github.io/hook/res/works.png"))) .queue(); } diff --git a/src/main/java/com/github/pinmacaroon/dchook/conf/ModConfigs.java b/src/main/java/com/github/pinmacaroon/dchook/conf/ModConfigs.java index 8d22955..0f76478 100644 --- a/src/main/java/com/github/pinmacaroon/dchook/conf/ModConfigs.java +++ b/src/main/java/com/github/pinmacaroon/dchook/conf/ModConfigs.java @@ -12,6 +12,10 @@ public class ModConfigs { public static String MESSAGES_SERVER_STOPPED; public static String MESSAGES_SERVER_STARTED; public static String MESSAGES_SERVER_STOPPING; + public static String MESSAGES_SERVER_WAYPOINT; + public static String MESSAGES_BOT_LIST; + public static String MESSAGES_BOT_MODS_LIST; + public static String MESSAGES_BOT_MODS_NONE; public static boolean FUNCTIONS_ALLOWOOCMESSAGES; public static boolean MESSAGES_SERVER_STARTING_ALLOWED; public static boolean MESSAGES_SERVER_STOPPED_ALLOWED; @@ -59,6 +63,14 @@ private static void createConfigs() { configs.addKeyValuePair(new Pair<>("messages.server.stopped.allowed", true), "stop message allowed?"); configs.addKeyValuePair(new Pair<>("messages.server.started.allowed", true), "opened/fully started message allowed?"); configs.addKeyValuePair(new Pair<>("messages.server.stopping.allowed", true), "stopping message allowed?"); + configs.addKeyValuePair( + new Pair<>("messages.server.waypoint", "Shared a waypoint called **{0} ({1})** at `{2}, {3}, {4}` from {5}!"), + "xaeos waypoint message.\n# {0}: waypoint name\n# {1}: waypoint letters\n# {2}, {3} and{4}: x, y and z\n# {5}: dimension name" + ); + configs.addKeyValuePair(new Pair<>("messages.bot.list", "There are currently **{0}**/{1} players online: "), "the list command preamble message\n# {0}: online players\n# {1}: max players"); + configs.addKeyValuePair(new Pair<>("messages.bot.mods.list", "The server currently has {0} required mods: "), "the mods command preamble message\n# {0}: number of mods"); + configs.addKeyValuePair(new Pair<>("messages.bot.mods.none", "The server currently has no required mods, you can join with a vanilla client!"), "the mods command message when no mods are needed by the client"); + configs.addDocumentationLine("note: the time command cannot be customised yet because im lazy :3"); configs.addBlankLine(); configs.addDocumentationLine("Something didn't work? See the documentation or report an issue at this url: <" + Hook.DOCS_URL + ">!"); @@ -70,6 +82,10 @@ private static void assignConfigs() { MESSAGES_SERVER_STARTED = CONFIG.getOrDefault("messages.server.started", "messages.server.started"); MESSAGES_SERVER_STOPPED = CONFIG.getOrDefault("messages.server.stopped", "messages.server.stopped"); MESSAGES_SERVER_STOPPING = CONFIG.getOrDefault("messages.server.stopping", "messages.server.stopping"); + MESSAGES_SERVER_WAYPOINT = CONFIG.getOrDefault("messages.server.waypoint", "messages.server.waypoint"); + MESSAGES_BOT_LIST = CONFIG.getOrDefault("messages.bot.list", "messages.bot.list"); + MESSAGES_BOT_MODS_LIST = CONFIG.getOrDefault("messages.bot.mods.list", "messages.bot.mods.list"); + MESSAGES_BOT_MODS_NONE = CONFIG.getOrDefault("messages.bot.mods.none", "messages.bot.mods.none"); FUNCTIONS_ALLOWOOCMESSAGES = CONFIG.getOrDefault("functions.allow_ooc_messages", false); MESSAGES_SERVER_STARTING_ALLOWED = CONFIG.getOrDefault("messages.server.starting.allowed", false); diff --git a/src/main/java/com/github/pinmacaroon/dchook/util/EventListeners.java b/src/main/java/com/github/pinmacaroon/dchook/util/EventListeners.java index f1ea054..ad7163c 100644 --- a/src/main/java/com/github/pinmacaroon/dchook/util/EventListeners.java +++ b/src/main/java/com/github/pinmacaroon/dchook/util/EventListeners.java @@ -7,17 +7,17 @@ import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; import net.minecraft.text.Text; -import java.lang.reflect.Array; import java.net.URI; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.text.MessageFormat; import java.util.HashMap; -import java.util.List; import java.util.concurrent.ExecutionException; public class EventListeners { + public static void registerEventListeners(){ + ServerLifecycleEvents.SERVER_STARTING.register(server -> { Hook.setMinecraftServer(server); if (!ModConfigs.MESSAGES_SERVER_STARTING_ALLOWED) return; @@ -39,54 +39,54 @@ public static void registerEventListeners(){ } }); - ServerLifecycleEvents.SERVER_STARTED.register(server -> { - if (!ModConfigs.MESSAGES_SERVER_STARTED_ALLOWED) return; - - HashMap request_body = new HashMap<>(); - request_body.put("content", "**"+ModConfigs.MESSAGES_SERVER_STARTED+"**"); - request_body.put("username", "server"); - - HttpRequest post = HttpRequest.newBuilder() - .POST(HttpRequest.BodyPublishers.ofString(Hook.GSON.toJson(request_body))) - .uri(URI.create(ModConfigs.WEBHOOK_URL)) - .header("Content-Type", "application/json") - .build(); - - try { - Hook.HTTPCLIENT.sendAsync(post, HttpResponse.BodyHandlers.ofString()).get().body(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - - if (ModConfigs.FUNCTIONS_PROMOTIONS_ENABLED) { - PromotionProvider.sendAutomaticPromotion(URI.create(ModConfigs.WEBHOOK_URL)); - } - }); + if (ModConfigs.MESSAGES_SERVER_STARTED_ALLOWED && ModConfigs.FUNCTIONS_PROMOTIONS_ENABLED) + ServerLifecycleEvents.SERVER_STARTED.register(server -> { + if (ModConfigs.MESSAGES_SERVER_STARTED_ALLOWED) { + HashMap request_body = new HashMap<>(); + request_body.put("content", "**"+ModConfigs.MESSAGES_SERVER_STARTED+"**"); + request_body.put("username", "server"); + + HttpRequest post = HttpRequest.newBuilder() + .POST(HttpRequest.BodyPublishers.ofString(Hook.GSON.toJson(request_body))) + .uri(URI.create(ModConfigs.WEBHOOK_URL)) + .header("Content-Type", "application/json") + .build(); + + try { + Hook.HTTPCLIENT.sendAsync(post, HttpResponse.BodyHandlers.ofString()).get().body(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + if (ModConfigs.FUNCTIONS_PROMOTIONS_ENABLED) { + PromotionProvider.sendPromotion(URI.create(ModConfigs.WEBHOOK_URL)); + } + }); ServerLifecycleEvents.SERVER_STOPPED.register(server -> { - if (!ModConfigs.MESSAGES_SERVER_STOPPED_ALLOWED) return; - - HashMap request_body = new HashMap<>(); - request_body.put("content", "**"+ModConfigs.MESSAGES_SERVER_STOPPED+"**"); - request_body.put("username", "server"); - - HttpRequest post = HttpRequest.newBuilder() - .POST(HttpRequest.BodyPublishers.ofString(Hook.GSON.toJson(request_body))) - .uri(URI.create(ModConfigs.WEBHOOK_URL)) - .header("Content-Type", "application/json") - .build(); - - try { - Hook.HTTPCLIENT.sendAsync(post, HttpResponse.BodyHandlers.ofString()).get().body(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); + if (ModConfigs.MESSAGES_SERVER_STOPPED_ALLOWED) { + HashMap request_body = new HashMap<>(); + request_body.put("content", "**" + ModConfigs.MESSAGES_SERVER_STOPPED + "**"); + request_body.put("username", "server"); + + HttpRequest post = HttpRequest.newBuilder() + .POST(HttpRequest.BodyPublishers.ofString(Hook.GSON.toJson(request_body))) + .uri(URI.create(ModConfigs.WEBHOOK_URL)) + .header("Content-Type", "application/json") + .build(); + + try { + Hook.HTTPCLIENT.sendAsync(post, HttpResponse.BodyHandlers.ofString()).get().body(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } } if(Hook.BOT != null) Hook.BOT.stop(); }); - ServerLifecycleEvents.SERVER_STOPPING.register(server -> { - if (!ModConfigs.MESSAGES_SERVER_STOPPING_ALLOWED) return; + if (ModConfigs.MESSAGES_SERVER_STOPPING_ALLOWED) ServerLifecycleEvents.SERVER_STOPPING.register(server -> { HashMap request_body = new HashMap<>(); request_body.put("content", "**"+ModConfigs.MESSAGES_SERVER_STOPPING+"**"); @@ -110,16 +110,14 @@ public static void registerEventListeners(){ HashMap request_body = new HashMap<>(); - if(WaypointParser.isWaypoint(message.getSignedContent())){ - List list = WaypointParser.constructWaypointFromString(message.getSignedContent()); + if(XaeoWaypoint.parse(message.getSignedContent())!=null){ + XaeoWaypoint point = XaeoWaypoint.parse(message.getSignedContent()); request_body.put("content", MessageFormat.format( - "*Shared a waypoint called **{0} ({1})** at `x={2} y={3} z={4}` from {5}!*", - list.get(0), - list.get(1), - Array.get(list.get(2), 0), - Array.get(list.get(2), 1), - Array.get(list.get(2), 2), - list.get(3) + "*"+ModConfigs.MESSAGES_SERVER_WAYPOINT+"*", + point.name, + point.marker, + point.x, point.y, point.z, + point.getDimension() )); } else request_body.put("content", MarkdownSanitizer.escape(message.getSignedContent())); diff --git a/src/main/java/com/github/pinmacaroon/dchook/util/PromotionProvider.java b/src/main/java/com/github/pinmacaroon/dchook/util/PromotionProvider.java index 11c9b30..e63d271 100644 --- a/src/main/java/com/github/pinmacaroon/dchook/util/PromotionProvider.java +++ b/src/main/java/com/github/pinmacaroon/dchook/util/PromotionProvider.java @@ -3,7 +3,6 @@ import com.github.pinmacaroon.dchook.Hook; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import org.jetbrains.annotations.Nullable; import java.net.URI; import java.net.http.HttpRequest; @@ -16,261 +15,200 @@ import static com.github.pinmacaroon.dchook.Hook.*; public class PromotionProvider { - public static JsonObject getMcfetchPromotion(){ - JsonObject embed = new JsonObject(); - - embed.addProperty("url", "https://pinmacaroon.github.io/mcfetch/legacy/index.html"); - - embed.addProperty("type", "rich"); - - embed.addProperty("title", "mcfetch: see minecraft server stats without starting the game!"); - - embed.addProperty("description", """ + private static JsonObject mcfetchEmbed = new JsonObject(); + private static JsonObject skinfetchEmbed = new JsonObject(); + private static JsonObject sequoiaEmbed = new JsonObject(); + private static JsonObject oocTip = new JsonObject(); + private static JsonObject docTip = new JsonObject(); + private static JsonObject hydrationTip = new JsonObject(); + private static JsonObject carTip = new JsonObject(); + + static { + mcfetchEmbed.addProperty("url", "https://pinmacaroon.github.io/mcfetch/legacy/index.html"); + mcfetchEmbed.addProperty("type", "rich"); + mcfetchEmbed.addProperty("title", "mcfetch: see minecraft server stats without starting the game!"); + mcfetchEmbed.addProperty("description", """ a **simple**, **easy to use** and **minimal tool** to see who are online on your \ favorite servers! **no download** needed, **no login** needed! **no ads** and no \ restrictions! all you need to get server information is the **IP** address of the \ server!"""); - - embed.addProperty("color", 15448355); - - JsonArray fields = new JsonArray(); - JsonObject field1 = new JsonObject(); - field1.addProperty("value", """ + mcfetchEmbed.addProperty("color", 15448355); + JsonArray mcfetchFlist = new JsonArray(); + JsonObject mcfetchField1 = new JsonObject(); + mcfetchField1.addProperty("value", """ start using it right now at this link: """); - field1.addProperty("name", "interested?"); - fields.add(field1); - embed.add("fields", fields); - - JsonObject author = new JsonObject(); - author.addProperty("name", "mcfetch"); - author.addProperty("url", "https://pinmacaroon.github.io/mcfetch/legacy/index.html"); - embed.add("author", author); - - embed.addProperty("timestamp", + mcfetchField1.addProperty("name", "interested?"); + mcfetchFlist.add(mcfetchField1); + mcfetchEmbed.add("fields", mcfetchFlist); + JsonObject mcfetchAuthor = new JsonObject(); + mcfetchAuthor.addProperty("name", "mcfetch"); + mcfetchAuthor.addProperty("url", "https://pinmacaroon.github.io/mcfetch/legacy/index.html"); + mcfetchEmbed.add("author", mcfetchAuthor); + mcfetchEmbed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT) ); - - JsonObject footer = new JsonObject(); - footer.addProperty("text", """ + JsonObject mcfetchFooter = new JsonObject(); + mcfetchFooter.addProperty("text", """ this was a promotion of first-party services or a tip message! \ if you wish to turn this off, go to the configuration file!"""); - embed.add("footer", footer); - return embed; - } - - public static JsonObject getSkinfetchPromotion(){ - JsonObject embed = new JsonObject(); + mcfetchEmbed.add("footer", mcfetchFooter); - embed.addProperty("url", "https://pinmacaroon.github.io/skinfetch/index.html"); - embed.addProperty("type", "rich"); - embed.addProperty("title", "skinfetch: quickly take a look at one's current skin"); - - embed.addProperty("description", """ + skinfetchEmbed.addProperty("url", "https://pinmacaroon.github.io/skinfetch/index.html"); + skinfetchEmbed.addProperty("type", "rich"); + skinfetchEmbed.addProperty("title", "skinfetch: quickly take a look at one's current skin"); + skinfetchEmbed.addProperty("description", """ a small and simple web tool to quickly get a view of a user's skin "from multiple angles"! choose from \ multiple modes, including but not limited to bust, body, head, skin! toggle the outer layer if you \ wish! choose a size (in pixels) and boom! just click on it and download the image!"""); + skinfetchEmbed.addProperty("color", 15448355); - embed.addProperty("color", 15448355); - - JsonArray fields = new JsonArray(); - JsonObject field1 = new JsonObject(); - field1.addProperty("value", """ + JsonArray skinfetchfields = new JsonArray(); + JsonObject skinfetchfield1 = new JsonObject(); + skinfetchfield1.addProperty("value", """ gaze upon your fabulous look from your browser now at this link: \ """); - field1.addProperty("name", "interested?"); - fields.add(field1); - embed.add("fields", fields); + skinfetchfield1.addProperty("name", "interested?"); + skinfetchfields.add(skinfetchfield1); + skinfetchEmbed.add("fields", skinfetchfields); - JsonObject author = new JsonObject(); - author.addProperty("name", "skinfetch"); - author.addProperty("url", "https://pinmacaroon.github.io/skinfetch/index.html"); - embed.add("author", author); + JsonObject skinfetchauthor = new JsonObject(); + skinfetchauthor.addProperty("name", "skinfetch"); + skinfetchauthor.addProperty("url", "https://pinmacaroon.github.io/skinfetch/index.html"); + skinfetchEmbed.add("author", skinfetchauthor); - embed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + skinfetchEmbed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); - JsonObject footer = new JsonObject(); - footer.addProperty("text", """ + JsonObject skinfetchfooter = new JsonObject(); + skinfetchfooter.addProperty("text", """ this was a promotion of first-party services or a tip message! \ if you wish to turn this off, go to the configuration file!"""); - embed.add("footer", footer); - return embed; - } + skinfetchEmbed.add("footer", skinfetchfooter); - public static JsonObject getSequoiaPromotion(){ - JsonObject embed = new JsonObject(); - embed.addProperty("url", "https://pinmacaroon.github.io/mcfetch/legacy/index.html"); - embed.addProperty("type", "rich"); - - embed.addProperty("title", "Sequoia: Adds a really nice biome with some really tall trees!"); - - embed.addProperty("description", """ + sequoiaEmbed.addProperty("url", "https://pinmacaroon.github.io/mcfetch/legacy/index.html"); + sequoiaEmbed.addProperty("type", "rich"); + sequoiaEmbed.addProperty("title", "Sequoia: Adds a really nice biome with some really tall trees!"); + sequoiaEmbed.addProperty("description", """ A mod that adds the amazing sequoia forests! Custom \ tree types, blocks, structures!"""); - - embed.addProperty("color", 15448355); - - //noinspection ExtractMethodRecommender - JsonArray fields = new JsonArray(); - - JsonObject field1 = new JsonObject(); - field1.addProperty("value", """ + sequoiaEmbed.addProperty("color", 15448355); + JsonArray sequoiafields = new JsonArray(); + JsonObject sequoiafield1 = new JsonObject(); + sequoiafield1.addProperty("value", """ Full block set like you would expect: * Log and Stripped Log * Wood and Stripped Wood * Planks * etc..."""); - field1.addProperty("name", "Sequoia wood type"); - fields.add(field1); - - JsonObject field2 = new JsonObject(); - field2.addProperty("value", """ + sequoiafield1.addProperty("name", "Sequoia wood type"); + sequoiafields.add(sequoiafield1); + JsonObject sequoiafield2 = new JsonObject(); + sequoiafield2.addProperty("value", """ Fresh air, big trees. Really beautiful place to set up camp. \ You can even find berry bushes! You can find three types of sequoia trees: * small * medium size * huge (structure, to be added)"""); - field2.addProperty("name", "Sequoia forest"); - fields.add(field2); - - embed.add("fields", fields); - - JsonObject author = new JsonObject(); - author.addProperty("name", "Sequoia"); - author.addProperty("url", "https://modrinth.com/mod/sequoia-pine"); - author.addProperty("icon_url", + sequoiafield2.addProperty("name", "Sequoia forest"); + sequoiafields.add(sequoiafield2); + sequoiaEmbed.add("fields", sequoiafields); + JsonObject sequoiaauthor = new JsonObject(); + sequoiaauthor.addProperty("name", "Sequoia"); + sequoiaauthor.addProperty("url", "https://modrinth.com/mod/sequoia-pine"); + sequoiaauthor.addProperty("icon_url", "https://cdn.modrinth.com/data/GYYIncFH/2fabee293b4be237825df51defe3b977058d31e7.png"); - embed.add("author", author); - - JsonObject image = new JsonObject(); - image.addProperty("url", + sequoiaEmbed.add("author", sequoiaauthor); + JsonObject sequoiaimage = new JsonObject(); + sequoiaimage.addProperty("url", "https://cdn.modrinth.com/data/GYYIncFH/images/5dd0848d40469d0dd4767c73ac926e112978645d.jpeg"); - embed.add("image", image); - - embed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); - - JsonObject footer = new JsonObject(); - footer.addProperty("text", """ + sequoiaEmbed.add("image", sequoiaimage); + sequoiaEmbed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + JsonObject sequoiafooter = new JsonObject(); + sequoiafooter.addProperty("text", """ this was a promotion of first-party services or a tip message! \ if you wish to turn this off, go to the configuration file!"""); + sequoiaEmbed.add("footer", sequoiafooter); - embed.add("footer", footer); - return embed; - } - - public static JsonObject getOocMessageTip(){ - JsonObject embed = new JsonObject(); - - embed.addProperty("type", "rich"); - embed.addProperty("title", "out of character messages"); - embed.addProperty("description", """ + oocTip.addProperty("type", "rich"); + oocTip.addProperty("title", "out of character messages"); + oocTip.addProperty("description", """ make messages hidden from the mod by ending it with `//`! it wont get transferred to \ Discord! you can configure this in the config file!"""); - - JsonObject author = new JsonObject(); - author.addProperty("name", "tips and hints"); - embed.add("author", author); - - embed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); - - JsonObject footer = new JsonObject(); - footer.addProperty("text", """ + JsonObject oocauthor = new JsonObject(); + oocauthor.addProperty("name", "tips and hints"); + oocTip.add("author", oocauthor); + oocTip.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + JsonObject oocfooter = new JsonObject(); + oocfooter.addProperty("text", """ this was a promotion of first-party services or a tip message! \ if you wish to turn this off, go to the configuration file!"""); - embed.add("footer", footer); - return embed; - } + oocTip.add("footer", oocfooter); - public static JsonObject getDocumentationTip(){ - JsonObject embed = new JsonObject(); - embed.addProperty("type", "rich"); - embed.addProperty("title", "documentation"); - - embed.addProperty("url", "https://pinmacaroon.github.io/hook/docs.html"); - - embed.addProperty("description", """ + docTip.addProperty("type", "rich"); + docTip.addProperty("title", "documentation"); + docTip.addProperty("url", "https://pinmacaroon.github.io/hook/docs.html"); + docTip.addProperty("description", """ oh noes! you couldn't figure out how to use the mod? i got your back! go to\ and see the table with the configuration keys and\ values! this page will be your hub for updates and information concerning the mod."""); - - JsonObject author = new JsonObject(); - author.addProperty("name", "tips and hints"); - embed.add("author", author); - - embed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); - - JsonObject image = new JsonObject(); - image.addProperty("url", "https://c.tenor.com/BRBnJitMZBYAAAAd/tenor.gif"); - embed.add("image", image); - - JsonObject footer = new JsonObject(); - footer.addProperty("text", """ + JsonObject docauthor = new JsonObject(); + docauthor.addProperty("name", "tips and hints"); + docTip.add("author", docauthor); + docTip.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + JsonObject docimage = new JsonObject(); + docimage.addProperty("url", "https://c.tenor.com/BRBnJitMZBYAAAAd/tenor.gif"); + docTip.add("image", docimage); + JsonObject docfooter = new JsonObject(); + docfooter.addProperty("text", """ this was a promotion of first-party services or a tip message! \ if you wish to turn this off, go to the configuration file!"""); - embed.add("footer", footer); - return embed; - } + docTip.add("footer", docfooter); - public static JsonObject getHydrationTip(){ - JsonObject embed = new JsonObject(); - embed.addProperty("type", "rich"); - embed.addProperty("title", "hydration"); - - embed.addProperty("description", """ + hydrationTip.addProperty("type", "rich"); + hydrationTip.addProperty("title", "hydration"); + hydrationTip.addProperty("description", """ **did you drink water today? do you drink enough?** an average daily "total water"\ intake of 3 liters is recommended by the USDA (this includes water from non-drinking water sources,\ like foods). specifically, **eight cups of drinking water a day** is the amount recommended by most\ nutritionists."""); - - JsonObject author = new JsonObject(); - author.addProperty("name", "tips and hints"); - embed.add("author", author); - - embed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); - - JsonObject footer = new JsonObject(); - footer.addProperty("text", """ + JsonObject hydrauthor = new JsonObject(); + hydrauthor.addProperty("name", "tips and hints"); + hydrationTip.add("author", hydrauthor); + hydrationTip.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + JsonObject hydrfooter = new JsonObject(); + hydrfooter.addProperty("text", """ this was a promotion of first-party services or a tip message! \ if you wish to turn this off, go to the configuration file!"""); - embed.add("footer", footer); - return embed; - } - - public static JsonObject getCar(){ - JsonObject embed = new JsonObject(); - - embed.addProperty("type", "rich"); - - JsonObject image = new JsonObject(); - image.addProperty("url", - "https://pinmacaroon.github.io/kocsi.gif"); - embed.add("image", image); - - embed.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); - - JsonObject footer = new JsonObject(); - footer.addProperty("text", """ + hydrationTip.add("footer", hydrfooter); + + carTip.addProperty("type", "rich"); + JsonObject carimage = new JsonObject(); + carimage.addProperty("url", + "https://raw.githubusercontent.com/pinmacaroon/hook/refs/heads/master/kocsi.gif"); + carTip.add("image", carimage); + carTip.addProperty("timestamp", ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + JsonObject carfooter = new JsonObject(); + carfooter.addProperty("text", """ this was a promotion of first-party services or a tip message! \ if you wish to turn this off, go to the configuration file!"""); - embed.add("footer", footer); - return embed; + carTip.add("footer", carfooter); } /** * @param embeds {@link JsonArray} of {@link JsonObject} which are discord embeds * @param webhook {@link URI} of the webhook api endpoint */ - public static void sendPromotion(JsonArray embeds, URI webhook){ + private static void sendPromotionMessageAPIRequest(JsonArray embeds, URI webhook){ JsonObject request_body = new JsonObject(); request_body.addProperty("username", "promotion"); request_body.add("embeds", embeds); @@ -290,31 +228,22 @@ public static void sendPromotion(JsonArray embeds, URI webhook){ } /** - * @return {@link JsonObject} of the single promotion embed, or a {@code null} if the gods decide that the rng shall - * be more than 6 + * @param webhook {@link URI} of the webhook api endpoint */ - public static @Nullable JsonObject automaticPromotionSelector(){ - int id = Hook.RANDOM.nextInt(0, 10); - return switch (id) { - case 0 -> getMcfetchPromotion(); - case 1 -> getOocMessageTip(); - case 2 -> getSequoiaPromotion(); - case 3 -> getDocumentationTip(); - case 4 -> getHydrationTip(); - case 5 -> getSkinfetchPromotion(); - case 6 -> getCar(); + public static void sendPromotion(URI webhook){ + JsonObject promotion = switch (Hook.RANDOM.nextInt(0, 10)) { + case 0 -> mcfetchEmbed; + case 1 -> skinfetchEmbed; + case 2 -> sequoiaEmbed; + case 3 -> oocTip; + case 4 -> docTip; + case 5 -> hydrationTip; + case 6 -> carTip; default -> null; }; - } - - /** - * @param webhook {@link URI} of the webhook api endpoint - */ - public static void sendAutomaticPromotion(URI webhook){ - JsonObject promotion = automaticPromotionSelector(); if(promotion == null) return; JsonArray promotions = new JsonArray(); promotions.add(promotion); - sendPromotion(promotions, webhook); + sendPromotionMessageAPIRequest(promotions, webhook); } } diff --git a/src/main/java/com/github/pinmacaroon/dchook/util/WaypointParser.java b/src/main/java/com/github/pinmacaroon/dchook/util/WaypointParser.java deleted file mode 100644 index 4ea6d7c..0000000 --- a/src/main/java/com/github/pinmacaroon/dchook/util/WaypointParser.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.github.pinmacaroon.dchook.util; - -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class WaypointParser { - private static final Pattern WAYPOINT_PATTERN = Pattern.compile( - // name marker x y z yaw ? ? dimension - "^xaero-waypoint:([^:]+):(.{1,2}):(-?\\d+):(-?\\d+):(-?\\d+):(-?\\d+):([^:]+):([^:]+):Internal-(the-nether|overworld|the-end)[-waypoints]?$" - ); - - public static boolean isWaypoint(String text) { - return WAYPOINT_PATTERN.matcher(text).matches(); - } - - /** - 1. name - 2. marker - 3. xyz - 4. dimension - */ - public static List constructWaypointFromString(String text) { - Matcher matcher = WAYPOINT_PATTERN.matcher(text); - //noinspection ResultOfMethodCallIgnored - matcher.matches(); - return List.of( - matcher.group(1), - matcher.group(2), - new int[]{ - Integer.parseInt(matcher.group(3)), - Integer.parseInt(matcher.group(4)), - Integer.parseInt(matcher.group(5)), - Integer.parseInt(matcher.group(6)), - }, - switch (matcher.group(9)) { - case "overworld" -> "The Overworld"; - case "the-nether" -> "The Nether"; - case "the-end" -> "The End"; - default -> "Narnia"; - } - ); - } -} diff --git a/src/main/java/com/github/pinmacaroon/dchook/util/XaeoWaypoint.java b/src/main/java/com/github/pinmacaroon/dchook/util/XaeoWaypoint.java new file mode 100644 index 0000000..5129cc9 --- /dev/null +++ b/src/main/java/com/github/pinmacaroon/dchook/util/XaeoWaypoint.java @@ -0,0 +1,62 @@ +package com.github.pinmacaroon.dchook.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class XaeoWaypoint { + private static final Pattern WAYPOINT_PATTERN = Pattern.compile( + // name1 marker2 x3 y4 z5 yaw6 ? ? dimension7 + "^xaero-waypoint:([^:]+):(.{1,2}):(-?\\d+):(-?\\d+):(-?\\d+):(-?\\d+):[^:]+:[^:]+:Internal-(the-nether|overworld|the-end)-waypoints$" + ); + + public static XaeoWaypoint parse(String text) { + Matcher matcher = WAYPOINT_PATTERN.matcher(text); + if (!matcher.matches()) return null; + return new XaeoWaypoint( + matcher.group(1), + matcher.group(2), + Integer.parseInt(matcher.group(3)), + Integer.parseInt(matcher.group(4)), + Integer.parseInt(matcher.group(5)), + Integer.parseInt(matcher.group(6)), + matcher.group(7) + ); + } + + private enum Dimension { + OVERWORLD, NETHER, END, OTHER + } + + public final String name; + public final String marker; + public final int x; + public final int y; + public final int z; + public final int yaw; + private final Dimension dimension; + + private XaeoWaypoint(String name, String marker, int x, int y, int z, int yaw, String dimension) { + if (name.equals("gui.xaero-deathpoint")) this.name = "Death Point"; + else this.name = name; + this.marker = marker; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.dimension = switch (dimension) { + case "overworld" -> Dimension.OVERWORLD; + case "the-nether" -> Dimension.NETHER; + case "the-end" -> Dimension.END; + default -> Dimension.OTHER; + }; + } + + public String getDimension(){ + return switch (this.dimension) { + case OVERWORLD -> "The Overworld"; + case NETHER -> "The Nether"; + case END -> "The End"; + default -> "non vanilla dimension"; + }; + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index c017d7b..551df7b 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -20,8 +20,8 @@ }, "depends": { "fabricloader": ">=0.16.10", - "minecraft": "1.20.*", - "java": ">=17", + "minecraft": ">=1.21.1", + "java": ">=21", "fabric-api": "*" }, "suggests": {