summaryrefslogtreecommitdiff
path: root/src/main/java/dev/plutorocks/MinecraftIRC.java
diff options
context:
space:
mode:
authorplutorocks <>2026-02-24 19:49:08 -0500
committerplutorocks <>2026-02-24 19:49:08 -0500
commitd270f94eb002937677becaca638ec089f2294c42 (patch)
tree8e8ae9e02324cc2a07240e2e6e4314b787089743 /src/main/java/dev/plutorocks/MinecraftIRC.java
parentd23825b05ec9cba95429c6ef693f469e99e37b36 (diff)
feat: add IRC
Diffstat (limited to 'src/main/java/dev/plutorocks/MinecraftIRC.java')
-rw-r--r--src/main/java/dev/plutorocks/MinecraftIRC.java233
1 files changed, 223 insertions, 10 deletions
diff --git a/src/main/java/dev/plutorocks/MinecraftIRC.java b/src/main/java/dev/plutorocks/MinecraftIRC.java
index a8aeed9..c802f20 100644
--- a/src/main/java/dev/plutorocks/MinecraftIRC.java
+++ b/src/main/java/dev/plutorocks/MinecraftIRC.java
@@ -1,24 +1,237 @@
package dev.plutorocks;
-import net.fabricmc.api.ModInitializer;
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.arguments.StringArgumentType;
+
+import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents;
+import net.fabricmc.loader.api.FabricLoader;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class MinecraftIRC implements ModInitializer {
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+
+public class MinecraftIRC implements ClientModInitializer {
public static final String MOD_ID = "minecraftirc";
- // This logger is used to write text to the console and the log file.
- // It is considered best practice to use your mod id as the logger's name.
- // That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
+ private static final Gson GSON = new Gson();
+ private static final Path CONFIG_PATH = FabricLoader.getInstance().getConfigDir().resolve("minecraftirc.json");
+
+ public static String ircHost = "irc.libera.chat";
+ public static final int ircPort = 6667;
+ public static String ircChannel = "#chat";
+ public static String ircNick = "Player";
+
+ public static IrcClient IRC_CLIENT;
+
@Override
- public void onInitialize() {
- // This code runs as soon as Minecraft is in a mod-load-ready state.
- // However, some things (like resources) may still be uninitialized.
- // Proceed with mild caution.
+ public void onInitializeClient() {
+ loadConfig();
+
+ IRC_CLIENT = new IrcClient(ircHost, ircPort, ircChannel, ircNick);
+ IRC_CLIENT.connect();
+
+ ClientSendMessageEvents.CHAT.register(message -> {
+ if (message.startsWith("!")) {
+ if (IRC_CLIENT != null && IRC_CLIENT.isConnected()) {
+ IRC_CLIENT.sendChannelMessage(message.substring(1));
+ } else {
+ sendIrcMessage("Not connected.");
+ }
+ }
+ });
+
+ ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
+ dispatcher.register(
+ literal("irc")
+ .then(literal("connect").executes(this::handleConnect))
+ .then(literal("disconnect").executes(this::handleDisconnect))
+ .then(literal("status").executes(this::handleStatus))
+ .then(literal("host")
+ .then(argument("host", StringArgumentType.word())
+ .executes(this::handleSetHost)))
+ .then(literal("channel")
+ .then(argument("channel", StringArgumentType.word())
+ .executes(this::handleSetChannel)))
+ .then(literal("nick")
+ .then(argument("nick", StringArgumentType.word())
+ .executes(this::handleSetNick)))
+ );
+ });
+
+ LOGGER.info("MinecraftIRC loaded!");
+ }
+
+ private static void loadConfig() {
+ if (!Files.exists(CONFIG_PATH)) {
+ applyDefaultsFromSession();
+ saveConfig();
+ return;
+ }
+
+ try (Reader reader = Files.newBufferedReader(CONFIG_PATH)) {
+ Config cfg = GSON.fromJson(reader, Config.class);
+ if (cfg == null) {
+ applyDefaultsFromSession();
+ saveConfig();
+ return;
+ }
+
+ if (cfg.host != null && !cfg.host.isEmpty()) {
+ ircHost = cfg.host;
+ } else {
+ ircHost = "irc.libera.chat";
+ }
+
+ if (cfg.channel != null && !cfg.channel.isEmpty()) {
+ ircChannel = normalizeChannel(cfg.channel);
+ } else {
+ ircChannel = normalizeChannel("chat");
+ }
+
+ if (cfg.nick != null && !cfg.nick.isEmpty()) {
+ ircNick = cfg.nick;
+ } else {
+ ircNick = defaultNickFromSession();
+ }
+ } catch (IOException | JsonSyntaxException e) {
+ LOGGER.warn("Failed to read MinecraftIRC config, using defaults", e);
+ applyDefaultsFromSession();
+ }
+ }
+
+ private static void saveConfig() {
+ Config cfg = new Config();
+ cfg.host = ircHost;
+ cfg.channel = ircChannel;
+ cfg.nick = ircNick;
+
+ try (Writer writer = Files.newBufferedWriter(CONFIG_PATH)) {
+ GSON.toJson(cfg, writer);
+ } catch (IOException e) {
+ LOGGER.warn("Failed to save MinecraftIRC config", e);
+ }
+ }
+
+ private static void applyDefaultsFromSession() {
+ ircHost = "irc.libera.chat";
+ ircChannel = normalizeChannel("chat");
+ ircNick = defaultNickFromSession();
+ }
+
+ private static String defaultNickFromSession() {
+ MinecraftClient client = MinecraftClient.getInstance();
+ if (client != null && client.getSession() != null) {
+ String name = client.getSession().getUsername();
+ if (name != null && !name.isEmpty()) {
+ return name;
+ }
+ }
+ return "Player";
+ }
+
+ private int handleConnect(CommandContext<FabricClientCommandSource> ctx) {
+ if (IRC_CLIENT != null && IRC_CLIENT.isConnected()) {
+ IRC_CLIENT.disconnect();
+ }
+
+ IRC_CLIENT = new IrcClient(ircHost, ircPort, ircChannel, ircNick);
+
+ sendCmdFeedback(ctx, "Connecting to " + ircHost + " " + ircChannel
+ + " as " + ircNick + " (port " + ircPort + ")...");
+ IRC_CLIENT.connect();
+ return 1;
+ }
+
+ private int handleDisconnect(CommandContext<FabricClientCommandSource> ctx) {
+ if (IRC_CLIENT == null || !IRC_CLIENT.isConnected()) {
+ sendCmdFeedback(ctx, "Already disconnected.");
+ return 1;
+ }
+
+ IRC_CLIENT.disconnect();
+ sendCmdFeedback(ctx, "Disconnected.");
+ return 1;
+ }
+
+ private int handleStatus(CommandContext<FabricClientCommandSource> ctx) {
+ String state = (IRC_CLIENT != null && IRC_CLIENT.isConnected()) ? "Connected" : "Not connected";
+ sendCmdFeedback(ctx, state + ". Host=" + ircHost
+ + " Channel=" + ircChannel + " Nick=" + ircNick
+ + " Port=" + ircPort);
+ return 1;
+ }
+
+ private int handleSetHost(CommandContext<FabricClientCommandSource> ctx) {
+ ircHost = StringArgumentType.getString(ctx, "host");
+ saveConfig();
+ sendCmdFeedback(ctx, "Host set to " + ircHost + ". Use /irc connect to apply.");
+ return 1;
+ }
+
+ private static String normalizeChannel(String raw) {
+ raw = raw.trim();
+ if (raw.isEmpty()) return "#chat";
+ if (!raw.startsWith("#")) raw = "#" + raw;
+ return raw;
+ }
+
+ private int handleSetChannel(CommandContext<FabricClientCommandSource> ctx) {
+ String raw = StringArgumentType.getString(ctx, "channel");
+ ircChannel = normalizeChannel(raw);
+ saveConfig();
+ sendCmdFeedback(ctx, "Channel set to " + ircChannel + ". Use /irc connect to apply.");
+ return 1;
+ }
+
+ private int handleSetNick(CommandContext<FabricClientCommandSource> ctx) {
+ ircNick = StringArgumentType.getString(ctx, "nick");
+ saveConfig();
+ sendCmdFeedback(ctx, "Nick set to " + ircNick + ". Use /irc connect to apply.");
+ return 1;
+ }
+
+ private void sendCmdFeedback(CommandContext<FabricClientCommandSource> ctx, String grayMessage) {
+ MutableText prefix = Text.literal("[IRC] ").formatted(Formatting.AQUA);
+ MutableText body = Text.literal(grayMessage).formatted(Formatting.GRAY);
+ ctx.getSource().sendFeedback(prefix.append(body));
+ }
+
+ private void sendIrcMessage(String grayMessage) {
+ MinecraftClient client = MinecraftClient.getInstance();
+ if (client == null) return;
+
+ client.execute(() -> {
+ if (client.inGameHud != null) {
+ MutableText prefix = Text.literal("[IRC] ").formatted(Formatting.AQUA);
+ MutableText body = Text.literal(grayMessage).formatted(Formatting.GRAY);
+ client.inGameHud.getChatHud().addMessage(prefix.append(body));
+ }
+ });
+ }
- LOGGER.info("Hello Fabric world!");
+ private static class Config {
+ String host;
+ String channel;
+ String nick;
}
} \ No newline at end of file