diff --git a/build.gradle b/build.gradle index afbe524..e450c97 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,11 @@ plugins { id 'fabric-loom' version '1.4-SNAPSHOT' id 'maven-publish' + id 'com.github.johnrengelman.shadow' version '8.1.1' } +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + version = project.mod_version group = project.maven_group @@ -16,6 +19,7 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + mavenCentral() } loom { @@ -46,7 +50,25 @@ dependencies { // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - implementation 'org.javacord:javacord:3.8.0' + implementation('net.dv8tion:JDA:5.0.0-beta.17') { + exclude module: 'opus-java' + } + shadow 'net.dv8tion:JDA:5.0.0-beta.17' +} + +tasks.withType(ShadowJar).configureEach { + it.minimize() + it.configurations = [project.configurations.shadow] + it.enableRelocation = true + it.relocationPrefix = "dev.jonasjones.dev.impl.vendor" +} + + +remapJar { + from('LICENSE') // Include license + + inputFile.set shadowJar.archiveFile + dependsOn shadowJar } processResources { diff --git a/gradle.properties b/gradle.properties index ac2eb32..4acf652 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.20.2+build.1 loader_version=0.14.22 # Mod Properties -mod_version=0.0.0 +mod_version=1.1.0 maven_group=dev.jonasjones archives_base_name=yet-another-discord-chat-link diff --git a/src/main/java/dev/jonasjones/yadcl/YetAnotherDiscordChatLink.java b/src/main/java/dev/jonasjones/yadcl/YetAnotherDiscordChatLink.java index ca7843c..b690670 100644 --- a/src/main/java/dev/jonasjones/yadcl/YetAnotherDiscordChatLink.java +++ b/src/main/java/dev/jonasjones/yadcl/YetAnotherDiscordChatLink.java @@ -15,17 +15,16 @@ public class YetAnotherDiscordChatLink implements ModInitializer { public static final String MOD_ID = "yadcl"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); + public static DiscordBot discordBot; + @Override public void onInitialize() { // Register the config ModConfigs.registerConfigs(); - // Set the token and channel id - DiscordBot.setToken(ModConfigs.TOKEN); - DiscordBot.setTargetChannelId(ModConfigs.CHANNEL_ID); - // Start the bot - DiscordBot.startBot(); + discordBot = new DiscordBot(ModConfigs.TOKEN, ModConfigs.CHANNEL_ID); + discordBot.startBot(); // send starting message sendToDiscord("Server is starting up."); } diff --git a/src/main/java/dev/jonasjones/yadcl/dcbot/DiscordBot.java b/src/main/java/dev/jonasjones/yadcl/dcbot/DiscordBot.java index 3a2d051..725c4fe 100644 --- a/src/main/java/dev/jonasjones/yadcl/dcbot/DiscordBot.java +++ b/src/main/java/dev/jonasjones/yadcl/dcbot/DiscordBot.java @@ -1,51 +1,59 @@ package dev.jonasjones.yadcl.dcbot; import dev.jonasjones.yadcl.config.ModConfigs; -import lombok.Setter; +import lombok.Getter; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.requests.GatewayIntent; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.server.MinecraftServer; import net.minecraft.text.Text; +import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; import static dev.jonasjones.yadcl.YetAnotherDiscordChatLink.LOGGER; -public class DiscordBot { - @Setter +public class DiscordBot extends ListenerAdapter { private static String token; - @Setter + @Getter private static String targetChannelId; - private static DiscordApi api; + private static JDA jda; + @Getter private static MinecraftServer minecraftServer; + @Getter private static Boolean isBotRunning = false; + public DiscordBot(String token, String targetChannelId) { + this.token = token; + this.targetChannelId = targetChannelId; + // Register Minecraft Server events + registerEvents(); + } + public static void startBot() { if (isBotRunning) { return; } try { - registerEvents(); - api = new DiscordApiBuilder().setToken(token).setAllIntents().login().join(); - api.addMessageCreateListener(event -> { - // Check if the message is from the specific channel by comparing channel IDs - if (String.valueOf(event.getChannel().getId()).equals(targetChannelId)) { - //check if message author is the bot - if (event.getMessageAuthor().isBotUser()) { - return; - } - String discordMessage = "[" + event.getMessageAuthor().getDisplayName() + "] " + event.getMessageContent(); - // Broadcast the message to Minecraft chat - // You can implement a method to broadcast messages to Minecraft players - minecraftServer.getPlayerManager().broadcast(Text.of(discordMessage), false); - } - }); + + // Create the bot + jda = JDABuilder.createDefault(token) + .addEventListeners(new MessageListener()) + .enableIntents(GatewayIntent.MESSAGE_CONTENT) + .build(); // Set the bot status if (ModConfigs.BOT_STATUS.equals("Uptime")) { new Thread(() -> { while (isBotRunning) { - botStatus(ModConfigs.BOT_STATUS); + setBotStatus(ModConfigs.BOT_STATUS); try { Thread.sleep(60000); } catch (InterruptedException e) { @@ -54,7 +62,7 @@ public class DiscordBot { } }).start(); } else { - botStatus(ModConfigs.BOT_STATUS); + setBotStatus(ModConfigs.BOT_STATUS); } } catch (Exception e) { LOGGER.error("Failed to start Discord bot. Check the provided discord token in the config file."); @@ -67,7 +75,7 @@ public class DiscordBot { if (!isBotRunning) { return; } - api.disconnect(); + jda.shutdown(); isBotRunning = false; } @@ -77,12 +85,12 @@ public class DiscordBot { } // Get the text channel by its ID try { - TextChannel channel = api.getTextChannelById(targetChannelId).orElse(null); + TextChannel channel = jda.getTextChannelById(targetChannelId); // Check if the channel exists and send the message if (channel != null) { - channel.sendMessage(message); + channel.sendMessage(message).queue(); } else { - throw new Exception("Discord Channel does not exist!"); + //throw new Exception("Discord Channel does not exist!"); } } catch (Exception e) { LOGGER.error("Discord Channel does not exist!"); @@ -105,47 +113,49 @@ public class DiscordBot { }); } - public static void botStatus(String status) { + public static void setBotStatus(String statusType) { if (!isBotRunning) { return; } - switch (status) { - case "None" -> api.updateActivity(""); - case "PlayerCount" -> - api.updateActivity("Player Count: " + minecraftServer.getCurrentPlayerCount() + "/" + minecraftServer.getMaxPlayerCount()); - case "IP" -> api.updateActivity("IP: " + minecraftServer.getServerIp()); - case "Uptime" -> api.updateActivity("Uptime: " + calculateUptime()); - default -> api.updateActivity(null); + switch (statusType.toLowerCase()) { + case "player count" -> jda.getPresence().setActivity(Activity.playing("Players: 100")); + case "ip" -> jda.getPresence().setActivity(Activity.listening("Server IP: example.com")); + case "uptime" -> jda.getPresence().setActivity(Activity.watching("Uptime: " + calculateUptime())); + default -> System.out.println("Invalid status type!"); } } private static String calculateUptime() { - long secs = System.currentTimeMillis() - minecraftServer.getTicks() / 20; - long days = TimeUnit.SECONDS.toDays(secs); - secs -= TimeUnit.DAYS.toMillis(days); - long hours = TimeUnit.SECONDS.toHours(secs); - secs -= TimeUnit.HOURS.toMillis(hours); - long minutes = TimeUnit.SECONDS.toMinutes(secs); + try { + long secs = System.currentTimeMillis() - minecraftServer.getTicks() / 20; + long days = TimeUnit.SECONDS.toDays(secs); + secs -= TimeUnit.DAYS.toMillis(days); + long hours = TimeUnit.SECONDS.toHours(secs); + secs -= TimeUnit.HOURS.toMillis(hours); + long minutes = TimeUnit.SECONDS.toMinutes(secs); - StringBuilder duration = new StringBuilder(); - if (days > 0) { - duration.append(days).append(" Days, "); - } - if (hours > 0 || days > 0) { - if (hours == 1) { - duration.append(hours).append(" Hour, "); - } else { - duration.append(hours).append(" Hours, "); + StringBuilder duration = new StringBuilder(); + if (days > 0) { + duration.append(days).append(" Days, "); } - } - if (minutes > 0 || hours > 0 || days > 0) { - if (minutes == 1) { - duration.append(minutes).append(" Minute, "); - } else { - duration.append(minutes).append(" Minutes, "); + if (hours > 0 || days > 0) { + if (hours == 1) { + duration.append(hours).append(" Hour, "); + } else { + duration.append(hours).append(" Hours, "); + } + } + if (minutes > 0 || hours > 0 || days > 0) { + if (minutes == 1) { + duration.append(minutes).append(" Minute, "); + } else { + duration.append(minutes).append(" Minutes, "); + } } - } - return duration.toString(); + return duration.toString(); + } catch (Exception e) { + return "-"; + } } } diff --git a/src/main/java/dev/jonasjones/yadcl/dcbot/MessageListener.java b/src/main/java/dev/jonasjones/yadcl/dcbot/MessageListener.java new file mode 100644 index 0000000..fb99608 --- /dev/null +++ b/src/main/java/dev/jonasjones/yadcl/dcbot/MessageListener.java @@ -0,0 +1,22 @@ +package dev.jonasjones.yadcl.dcbot; + +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.minecraft.text.Text; + +import static dev.jonasjones.yadcl.YetAnotherDiscordChatLink.discordBot; + +public class MessageListener extends ListenerAdapter { + @Override + public void onMessageReceived(MessageReceivedEvent event) { + if (!DiscordBot.getIsBotRunning()) return; // Ignore messages if the bot is not running + if (event.getAuthor().isBot()) return; // Ignore messages from other bots + + // Check if the message was sent in the trigger channel + if (event.getChannel().getId().equals(DiscordBot.getTargetChannelId())) { + // Send the message to the server + DiscordBot.getMinecraftServer().getPlayerManager().broadcast(Text.of("[" +event.getAuthor().getName() + "]: " + event.getMessage().getContentRaw()), false); + } + } +} diff --git a/src/main/java/dev/jonasjones/yadcl/mixin/PlayerManagerMixin.java b/src/main/java/dev/jonasjones/yadcl/mixin/PlayerManagerMixin.java index e7e2a29..58eb29d 100644 --- a/src/main/java/dev/jonasjones/yadcl/mixin/PlayerManagerMixin.java +++ b/src/main/java/dev/jonasjones/yadcl/mixin/PlayerManagerMixin.java @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static dev.jonasjones.yadcl.dcbot.DiscordBot.botStatus; +import static dev.jonasjones.yadcl.dcbot.DiscordBot.setBotStatus; import static dev.jonasjones.yadcl.dcbot.DiscordBot.sendToDiscord; @Mixin(PlayerManager.class) @@ -20,7 +20,7 @@ public class PlayerManagerMixin { if (ModConfigs.PLAYER_JOIN_LEAVE_MSG) { sendToDiscord(player.getDisplayName().getString() + " joined the game"); if (ModConfigs.BOT_STATUS.equals("PlayerCount")) { - botStatus(ModConfigs.BOT_STATUS); + setBotStatus(ModConfigs.BOT_STATUS); } } } @@ -30,7 +30,7 @@ public class PlayerManagerMixin { if (ModConfigs.PLAYER_JOIN_LEAVE_MSG) { sendToDiscord(player.getDisplayName().getString() + " left the game"); if (ModConfigs.BOT_STATUS.equals("PlayerCount")) { - botStatus(ModConfigs.BOT_STATUS); + setBotStatus(ModConfigs.BOT_STATUS); } } }