Advanced DiscordRPC | Not finished yet

This commit is contained in:
Patrick
2026-06-20 22:43:02 +02:00
parent cf5745808e
commit e8ac62ac56
4 changed files with 128 additions and 2 deletions
@@ -3,6 +3,8 @@ package de.winniepat.parrotmod;
import de.winniepat.parrotmod.discord.DiscordRPCManager; import de.winniepat.parrotmod.discord.DiscordRPCManager;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; 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.networking.v1.ClientPlayConnectionEvents;
public class Parrotmod implements ModInitializer { public class Parrotmod implements ModInitializer {
@@ -11,5 +13,13 @@ public class Parrotmod implements ModInitializer {
DiscordRPCManager.init(); DiscordRPCManager.init();
ClientLifecycleEvents.CLIENT_STOPPING.register(client -> DiscordRPCManager.shutdown()); ClientLifecycleEvents.CLIENT_STOPPING.register(client -> DiscordRPCManager.shutdown());
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> DiscordRPCManager.setIdle());
ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (client.player != null) {
DiscordRPCManager.maybeUpdateFromPlayer(client.player);
}
});
} }
} }
@@ -8,13 +8,41 @@ import com.jagrosh.discordipc.entities.Packet;
import com.jagrosh.discordipc.entities.RichPresence; import com.jagrosh.discordipc.entities.RichPresence;
import com.jagrosh.discordipc.entities.User; import com.jagrosh.discordipc.entities.User;
import com.jagrosh.discordipc.exceptions.NoDiscordClientException; import com.jagrosh.discordipc.exceptions.NoDiscordClientException;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.item.ItemStack;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class DiscordRPCManager { public class DiscordRPCManager {
private static final long APPLICATION_ID = 1517985621396820039L; private static final long APPLICATION_ID = 1517985621396820039L;
private static final long UPDATE_COOLDOWN_MS = 15_000;
private static IPCClient client; private static IPCClient client;
private static boolean connected = false; 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",
"Trying to find a use for all these parrots",
"Listening to some tunes",
"Wondering if parrots can be tamed with cookies",
"Watching some parrots fly around",
"Just hanging out with my parrots",
"Trying to teach my parrots some new tricks",
"Just a parrot enthusiast",
"Trying to find the perfect seed for my parrot farm",
"Just a parrot in a Minecraft world",
"Trying to find a way to make parrots dance",
"Just a parrot, doing parrot things"
);
private DiscordRPCManager() {} private DiscordRPCManager() {}
@@ -49,7 +77,8 @@ public class DiscordRPCManager {
@Override @Override
public void onReady(IPCClient client) { public void onReady(IPCClient client) {
connected = true; connected = true;
updatePresence("In the menus", "Just launched"); sessionStart = OffsetDateTime.now().toEpochSecond();
updatePresence("In the menus", randomIdleLine());
} }
@Override @Override
@@ -72,6 +101,36 @@ public class DiscordRPCManager {
}, "discord-rpc-init").start(); }, "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) {
String dimension = player.level().dimension().registry().getPath();
String biomeName = player.level().getBiome(player.blockPosition())
.unwrapKey()
.map(key -> key.registry().getPath())
.orElse("unknown");
ItemStack held = player.getMainHandItem();
String heldName = held.isEmpty() ? "empty hands" : held.getHoverName().getString();
String details = switch (dimension) {
case "the_nether" -> "Surviving the Nether";
case "the_end" -> "Facing the End";
default -> "Exploring the " + prettify(biomeName);
};
String state = "Wielding " + heldName + " · " + (int) player.getHealth() + " HP";
updatePresence(details, state);
}
public static void setIdle() {
updatePresence("In the menus", randomIdleLine());
}
public static void updatePresence(String details, String state) { public static void updatePresence(String details, String state) {
if (!connected) return; if (!connected) return;
RichPresence presence = new RichPresence.Builder() RichPresence presence = new RichPresence.Builder()
@@ -84,6 +143,15 @@ public class DiscordRPCManager {
client.sendRichPresence(presence); 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() { public static void shutdown() {
if (client != null) client.close(); if (client != null) client.close();
} }
@@ -0,0 +1,49 @@
package de.winniepat.parrotmod.ui;
import icyllis.modernui.fragment.Fragment;
import icyllis.modernui.util.DataSet;
import icyllis.modernui.view.LayoutInflater;
import icyllis.modernui.view.View;
import icyllis.modernui.view.ViewGroup;
import icyllis.modernui.widget.LinearLayout;
import icyllis.modernui.widget.Switch;
import icyllis.modernui.widget.TextView;
import net.minecraft.client.Minecraft;
public class DiscordTabFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, DataSet savedInstanceData) {
LinearLayout layout = new LinearLayout(getContext());
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding(dp(12), dp(12), dp(12), dp(12));
layout.addView(makeLabel("Enable DiscordRPC"));
Switch toggleDiscordRPC = new Switch(getContext());
toggleDiscordRPC.setChecked(true); // TODO: load from config
toggleDiscordRPC.setOnCheckedChangeListener((v, checked) -> {
// TODO: save to config
// MyConfig.enableDiscordRPC = checked;
});
layout.addView(toggleDiscordRPC);
return layout;
}
private TextView makeLabel(String text) {
TextView tv = new TextView(getContext());
tv.setText(text);
tv.setTextSize(12);
tv.setTextColor(0xFFCCCCCC);
var p = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
p.topMargin = dp(8);
p.bottomMargin = dp(2);
tv.setLayoutParams(p);
return tv;
}
private int dp(float dp) {
return (int) (dp * getContext().getResources().getDisplayMetrics().density);
}
}
@@ -1,6 +1,5 @@
package de.winniepat.parrotmod.ui; package de.winniepat.parrotmod.ui;
import de.winniepat.parrotmod.Parrotmod;
import icyllis.modernui.fragment.Fragment; import icyllis.modernui.fragment.Fragment;
import icyllis.modernui.util.DataSet; import icyllis.modernui.util.DataSet;
import icyllis.modernui.view.LayoutInflater; import icyllis.modernui.view.LayoutInflater;