diff --git a/src/main/java/de/winniepat/parrotmod/Parrotmod.java b/src/main/java/de/winniepat/parrotmod/Parrotmod.java index 6342f98..390267d 100644 --- a/src/main/java/de/winniepat/parrotmod/Parrotmod.java +++ b/src/main/java/de/winniepat/parrotmod/Parrotmod.java @@ -3,6 +3,8 @@ package de.winniepat.parrotmod; import de.winniepat.parrotmod.discord.DiscordRPCManager; import net.fabricmc.api.ModInitializer; 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 { @@ -11,5 +13,13 @@ public class Parrotmod implements ModInitializer { DiscordRPCManager.init(); 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); + } + }); } } diff --git a/src/main/java/de/winniepat/parrotmod/discord/DiscordRPCManager.java b/src/main/java/de/winniepat/parrotmod/discord/DiscordRPCManager.java index b104799..8b350c8 100644 --- a/src/main/java/de/winniepat/parrotmod/discord/DiscordRPCManager.java +++ b/src/main/java/de/winniepat/parrotmod/discord/DiscordRPCManager.java @@ -8,13 +8,41 @@ 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 net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.item.ItemStack; import java.time.OffsetDateTime; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; public class DiscordRPCManager { private static final long APPLICATION_ID = 1517985621396820039L; + 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", + "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() {} @@ -49,7 +77,8 @@ public class DiscordRPCManager { @Override public void onReady(IPCClient client) { connected = true; - updatePresence("In the menus", "Just launched"); + sessionStart = OffsetDateTime.now().toEpochSecond(); + updatePresence("In the menus", randomIdleLine()); } @Override @@ -72,6 +101,36 @@ public class DiscordRPCManager { }, "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) { if (!connected) return; RichPresence presence = new RichPresence.Builder() @@ -84,6 +143,15 @@ public class DiscordRPCManager { 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) client.close(); } diff --git a/src/main/java/de/winniepat/parrotmod/ui/DiscordTabFragment.java b/src/main/java/de/winniepat/parrotmod/ui/DiscordTabFragment.java new file mode 100644 index 0000000..db8d4aa --- /dev/null +++ b/src/main/java/de/winniepat/parrotmod/ui/DiscordTabFragment.java @@ -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); + } + +} diff --git a/src/main/java/de/winniepat/parrotmod/ui/InfoTabFragment.java b/src/main/java/de/winniepat/parrotmod/ui/InfoTabFragment.java index e851f4e..65a55b5 100644 --- a/src/main/java/de/winniepat/parrotmod/ui/InfoTabFragment.java +++ b/src/main/java/de/winniepat/parrotmod/ui/InfoTabFragment.java @@ -1,6 +1,5 @@ package de.winniepat.parrotmod.ui; -import de.winniepat.parrotmod.Parrotmod; import icyllis.modernui.fragment.Fragment; import icyllis.modernui.util.DataSet; import icyllis.modernui.view.LayoutInflater;