added discord rpc

This commit is contained in:
2026-07-13 17:23:05 +02:00
parent cc8e670d9b
commit 7dbf06698e
5 changed files with 187 additions and 14 deletions
@@ -6,6 +6,7 @@ import de.fullrisk.citrusDev.UI.*;
import de.fullrisk.citrusDev.UIHelper.DraggableHud;
import de.fullrisk.citrusDev.helper.RankHelper;
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.keymapping.v1.KeyMappingHelper;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
@@ -31,7 +32,11 @@ public class CitrusDevClient implements ClientModInitializer {
Module_KeyStrokes.register();
Module_Coords.register();
Module_Effects.register();
DiscordRPCManager.init();
ClientLifecycleEvents.CLIENT_STOPPING.register(client -> DiscordRPCManager.shutdown());
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> DiscordRPCManager.setIdle());
KeyMapping.Category category = KeyMapping.Category.register(
Identifier.fromNamespaceAndPath("citrus-dev", "general"));
@@ -53,6 +58,9 @@ public class CitrusDevClient implements ClientModInitializer {
QuestsPanel.tick();
}
if (client.player != null) {
DiscordRPCManager.maybeUpdateFromPlayer(client.player);
}
Module_FPS.tick();
Module_KeyStrokes.tick();
@@ -0,0 +1,174 @@
package de.fullrisk.citrusDev.client;
import com.google.gson.JsonObject;
import com.jagrosh.discordipc.IPCClient;
import com.jagrosh.discordipc.IPCListener;
import com.jagrosh.discordipc.entities.ActivityType;
import com.jagrosh.discordipc.entities.Packet;
import com.jagrosh.discordipc.entities.RichPresence;
import com.jagrosh.discordipc.entities.User;
import com.jagrosh.discordipc.exceptions.NoDiscordClientException;
import com.mojang.authlib.minecraft.client.MinecraftClient;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.Holder;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class DiscordRPCManager {
private static final long UPDATE_COOLDOWN_MS = 15_000;
private static IPCClient client;
private static boolean connected = false;
private static long lastUpdate = 0;
private static long sessionStart;
private static final List<String> IDLE_LINES = List.of(
"Contemplating the void",
"Staring at a crafting table",
"Definetely not AFK",
"Waiting for something to happen",
"Just chilling",
"Admiring the scenery",
"Listening to some tunes"
);
private DiscordRPCManager() {}
public static void init() {
startClient();
}
private static void startClient() {
client = new IPCClient(1525935861747945502L);
client.setListener(new IPCListener() {
@Override
public void onPacketSent(IPCClient client, Packet packet) {
}
@Override
public void onPacketReceived(IPCClient client, Packet packet) {
}
@Override
public void onActivityJoin(IPCClient client, String secret) {
}
@Override
public void onActivitySpectate(IPCClient client, String secret) {
}
@Override
public void onActivityJoinRequest(IPCClient client, String secret, User user) {
}
@Override
public void onReady(IPCClient client) {
connected = true;
sessionStart = OffsetDateTime.now().toEpochSecond();
updatePresence("In the menus", randomIdleLine());
}
@Override
public void onClose(IPCClient client, JsonObject json) {
}
@Override
public void onDisconnect(IPCClient client, Throwable t) {
connected = false;
}
});
new Thread(() -> {
try {
client.connect();
} catch (NoDiscordClientException e) {
connected = false;
}
}, "discord-rpc-init").start();
}
public static void maybeUpdateFromPlayer(LocalPlayer player) {
long now = System.currentTimeMillis();
if (now - lastUpdate < UPDATE_COOLDOWN_MS) return;
lastUpdate = now;
updateFromPlayer(player);
}
private static void updateFromPlayer(LocalPlayer player) {
ResourceKey<Level> dimension = player.level().dimension();
String details;
if (dimension == Level.OVERWORLD) {
details = "Overworld";
} else if (dimension == Level.NETHER) {
details = "Nether";
} else if (dimension == Level.END) {
details = "The End";
} else {
details = "Custom Dimension: " + dimension.toString();
}
String serverIp = "Singleplayer";
var serverData = Minecraft.getInstance().getCurrentServer();
if (serverData != null && serverData.ip != null && !serverData.ip.isEmpty()) {
serverIp = serverData.ip;
}
String state = serverIp;
updatePresence(details, state);
}
public static void setIdle() {
updatePresence("In the menus", randomIdleLine());
}
public static void updatePresence(String details, String state) {
if (!connected) return;
RichPresence presence = new RichPresence.Builder()
.setActivityType(ActivityType.Playing)
.setDetails(details)
.setState(state)
.setStartTimestamp(OffsetDateTime.now().toEpochSecond())
.setLargeImage("icon_large", "My Mod")
.build();
client.sendRichPresence(presence);
}
public static String randomIdleLine() {
return IDLE_LINES.get(ThreadLocalRandom.current().nextInt(IDLE_LINES.size()));
}
private static String prettify(String raw) {
String spaced = raw.replace('_', ' ');
return spaced.substring(0, 1).toUpperCase() + spaced.substring(1);
}
public static void shutdown() {
if (client != null) {
try {
if (connected) {
client.close();
}
} catch (Exception e) {
CitrusDevClient.logger.error("Error while closing Discord RPC client", e);
} finally {
client = null;
connected = false;
}
}
}
}