Add Fabric client IRC chat mod and Drone pipeline

This commit is contained in:
2026-06-21 14:31:38 +06:00
commit 910c58c30b
13 changed files with 837 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
package ru.nevetime.clientirc;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class ClientIrcMod implements ClientModInitializer {
public static final String MOD_ID = "clientirc";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
private static final String COMMAND_PREFIX = ".irc";
private static IrcConfig config;
private static IrcService service;
@Override
public void onInitializeClient() {
config = IrcConfig.load(FabricLoader.getInstance().getConfigDir().resolve("clientirc.json"));
service = new IrcService(config, LOGGER);
ClientLifecycleEvents.CLIENT_STARTED.register(client -> {
if (config.autoConnect) {
service.connect(resolvePlayerName(client));
}
});
ClientTickEvents.END_CLIENT_TICK.register(client -> {
IrcService.DisplayLine line;
while ((line = service.pollLine()) != null) {
Formatting color = line.system() ? Formatting.GRAY : Formatting.AQUA;
pushClientChat(client, Text.literal(line.text()).formatted(color));
}
});
ClientSendMessageEvents.ALLOW_CHAT.register(message -> !interceptOutgoingChat(message));
}
private static boolean interceptOutgoingChat(String rawMessage) {
String trimmed = rawMessage.trim();
if (!trimmed.startsWith(COMMAND_PREFIX)) {
return false;
}
MinecraftClient client = MinecraftClient.getInstance();
String argument = trimmed.length() == COMMAND_PREFIX.length() ? "" : trimmed.substring(COMMAND_PREFIX.length()).trim();
if (argument.isBlank()) {
pushClientChat(client, Text.literal("[IRC] Usage: .irc <message> | .irc status | .irc reconnect | .irc reload").formatted(Formatting.YELLOW));
return true;
}
if ("status".equalsIgnoreCase(argument)) {
String status = service.isConnected() ? "connected" : "disconnected";
pushClientChat(client, Text.literal("[IRC] " + status + " | " + config.host + ":" + config.port + " | clientName=" + config.clientName).formatted(Formatting.YELLOW));
return true;
}
if ("reconnect".equalsIgnoreCase(argument)) {
boolean connected = service.reconnect(resolvePlayerName(client));
Formatting color = connected ? Formatting.GREEN : Formatting.RED;
pushClientChat(client, Text.literal("[IRC] reconnect " + (connected ? "ok" : "failed")).formatted(color));
return true;
}
if ("reload".equalsIgnoreCase(argument)) {
config = IrcConfig.load(FabricLoader.getInstance().getConfigDir().resolve("clientirc.json"));
service.updateConfig(config);
pushClientChat(client, Text.literal("[IRC] config reloaded").formatted(Formatting.YELLOW));
return true;
}
if (!service.ensureConnected(resolvePlayerName(client))) {
pushClientChat(client, Text.literal("[IRC] server is offline or config is wrong").formatted(Formatting.RED));
return true;
}
boolean sent = service.sendChat(resolvePlayerName(client), argument);
if (!sent) {
pushClientChat(client, Text.literal("[IRC] send failed").formatted(Formatting.RED));
}
return true;
}
private static void pushClientChat(MinecraftClient client, Text text) {
if (client == null) {
return;
}
client.execute(() -> client.inGameHud.getChatHud().addMessage(text));
}
private static String resolvePlayerName(MinecraftClient client) {
if (client != null && client.player != null) {
return client.player.getGameProfile().getName();
}
if (client != null && client.getSession() != null) {
return client.getSession().getUsername();
}
return "unknown";
}
}