diff options
Diffstat (limited to 'src/main/java/dev/plutorocks/MinecraftIRC.java')
| -rw-r--r-- | src/main/java/dev/plutorocks/MinecraftIRC.java | 233 |
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 |
