diff --git a/build.gradle b/build.gradle index 1066186..2801d65 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,7 @@ base { } repositories { + mavenCentral() maven { url 'https://maven.wispforest.io/releases/' } maven { url 'https://jitpack.io' } } @@ -24,6 +25,9 @@ dependencies { implementation "io.wispforest:owo-lib:0.13.0+26.1" include "io.wispforest:owo-sentinel:0.13.0+26.1" + + include(implementation("io.github.CDAGaming:DiscordIPC:0.10.2")) + } processResources { diff --git a/src/main/java/de/fullrisk/citrusDev/UI/MyScreen.java b/src/main/java/de/fullrisk/citrusDev/UI/MyScreen.java index ef64dca..94270af 100644 --- a/src/main/java/de/fullrisk/citrusDev/UI/MyScreen.java +++ b/src/main/java/de/fullrisk/citrusDev/UI/MyScreen.java @@ -460,13 +460,6 @@ public class MyScreen extends BaseOwoScreen { rowsContainer.horizontalAlignment(HorizontalAlignment.LEFT); rowsContainer.padding(Insets.of(0)); - FlowLayout editButton = SettingsControls.makeTextButton(GLASS_PANEL, "Edit Positions", () -> { - DraggableHud.setEditMode(true); - Minecraft.getInstance().setScreen(null); - }); - editButton.horizontalSizing(Sizing.fixed(CONTENT_WIDTH - 8)); - rowsContainer.child(editButton); - FlowLayout blurSlider = SettingsControls.makeSlider( FLAT, 80, @@ -492,12 +485,6 @@ public class MyScreen extends BaseOwoScreen { blurRow.child(blurSlider); rowsContainer.child(blurRow); - FlowLayout hintRow = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content()); - hintRow.padding(Insets.of(4, 0, 0, 0)); - hintRow.child(UIComponents.label(Component.literal("Drag HUD modules to reposition. Press ESC to stop.")) - .color(Color.ofRgb(0xFF5c5c66))); - rowsContainer.child(hintRow); - content.child(rowsContainer); } diff --git a/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java b/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java index bfe35fe..c88baa8 100644 --- a/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java +++ b/src/main/java/de/fullrisk/citrusDev/UIHelper/SettingsControls.java @@ -198,7 +198,7 @@ public class SettingsControls { var label = UIComponents.label(Component.literal(text.toUpperCase()) .withStyle(style -> style.withFont(new FontDescription.Resource(MC_FIVE)))) - .color(Color.ofRgb(0x9a9aa5)); + .color(Color.ofRgb(0xFF5c5c66)); row.child(label); FlowLayout longLine = UIContainers.horizontalFlow(Sizing.fill(100), Sizing.fixed(1)); diff --git a/src/main/java/de/fullrisk/citrusDev/client/CitrusDevClient.java b/src/main/java/de/fullrisk/citrusDev/client/CitrusDevClient.java index ea4bc37..62a6f57 100644 --- a/src/main/java/de/fullrisk/citrusDev/client/CitrusDevClient.java +++ b/src/main/java/de/fullrisk/citrusDev/client/CitrusDevClient.java @@ -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(); diff --git a/src/main/java/de/fullrisk/citrusDev/client/DiscordRPCManager.java b/src/main/java/de/fullrisk/citrusDev/client/DiscordRPCManager.java new file mode 100644 index 0000000..b249428 --- /dev/null +++ b/src/main/java/de/fullrisk/citrusDev/client/DiscordRPCManager.java @@ -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 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 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; + } + } + } +}