From d91bec81dbfc60ddab1cfd8f642e6c84e1270e94 Mon Sep 17 00:00:00 2001 From: Turtlegamer_ Date: Thu, 26 Mar 2026 16:38:17 +0100 Subject: [PATCH 1/2] added sync option under .friends --- .../commands/commands/FriendsCommand.java | 34 ++++++++++--- .../meteorclient/systems/friends/Friends.java | 48 ++++++++++++++++--- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/main/java/meteordevelopment/meteorclient/commands/commands/FriendsCommand.java b/src/main/java/meteordevelopment/meteorclient/commands/commands/FriendsCommand.java index 23ae209cad..97ee95f21a 100644 --- a/src/main/java/meteordevelopment/meteorclient/commands/commands/FriendsCommand.java +++ b/src/main/java/meteordevelopment/meteorclient/commands/commands/FriendsCommand.java @@ -13,6 +13,7 @@ import meteordevelopment.meteorclient.systems.friends.Friend; import meteordevelopment.meteorclient.systems.friends.Friends; import meteordevelopment.meteorclient.utils.player.ChatUtils; +import net.minecraft.client.MinecraftClient; import net.minecraft.command.CommandSource; import net.minecraft.util.Formatting; @@ -23,6 +24,7 @@ public FriendsCommand() { @Override public void build(LiteralArgumentBuilder builder) { + // Add friend builder.then(literal("add") .then(argument("player", PlayerListEntryArgumentType.create()) .executes(context -> { @@ -30,15 +32,15 @@ public void build(LiteralArgumentBuilder builder) { Friend friend = new Friend(profile.name(), profile.id()); if (Friends.get().add(friend)) { - ChatUtils.sendMsg(friend.hashCode(), Formatting.GRAY, "Added (highlight)%s (default)to friends.".formatted(friend.getName())); - } - else error("Already friends with that player."); + ChatUtils.sendMsg(friend.hashCode(), Formatting.GRAY, "Added (highlight)%s (default) to friends.".formatted(friend.getName())); + } else error("Already friends with that player."); return SINGLE_SUCCESS; }) ) ); + // Remove friend builder.then(literal("remove") .then(argument("friend", FriendArgumentType.create()) .executes(context -> { @@ -49,15 +51,35 @@ public void build(LiteralArgumentBuilder builder) { } if (Friends.get().remove(friend)) { - ChatUtils.sendMsg(friend.hashCode(), Formatting.GRAY, "Removed (highlight)%s (default)from friends.".formatted(friend.getName())); - } - else error("Failed to remove that friend."); + ChatUtils.sendMsg(friend.hashCode(), Formatting.GRAY, "Removed (highlight)%s (default) from friends.".formatted(friend.getName())); + } else error("Failed to remove that friend."); return SINGLE_SUCCESS; }) ) ); + // Sync Mio friends for now + builder.then(literal("sync") + .executes(context -> { + try { + int added = Friends.get().importFromMio(); + + if (added == -1) { + error("Mio socials.json not found."); + } else { + ChatUtils.sendMsg(0, Formatting.GRAY, "Imported %d Mio friends.".formatted(added)); + } + } catch (Exception e) { + e.printStackTrace(); + error("Failed to sync Mio friends."); + } + + return SINGLE_SUCCESS; + }) + ); + + // List friends builder.then(literal("list").executes(context -> { info("--- Friends ((highlight)%s(default)) ---", Friends.get().count()); Friends.get().forEach(friend -> ChatUtils.info("(highlight)%s".formatted(friend.getName()))); diff --git a/src/main/java/meteordevelopment/meteorclient/systems/friends/Friends.java b/src/main/java/meteordevelopment/meteorclient/systems/friends/Friends.java index 271d6ae92e..50b8451dd1 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/friends/Friends.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/friends/Friends.java @@ -5,17 +5,25 @@ package meteordevelopment.meteorclient.systems.friends; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.mojang.util.UndashedUuid; import meteordevelopment.meteorclient.systems.System; import meteordevelopment.meteorclient.systems.Systems; import meteordevelopment.meteorclient.utils.misc.NbtUtils; import meteordevelopment.meteorclient.utils.network.MeteorExecutor; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import org.jetbrains.annotations.NotNull; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -38,7 +46,6 @@ public boolean add(Friend friend) { if (!friends.contains(friend)) { friends.add(friend); save(); - return true; } @@ -56,11 +63,8 @@ public boolean remove(Friend friend) { public Friend get(String name) { for (Friend friend : friends) { - if (friend.name.equalsIgnoreCase(name)) { - return friend; - } + if (friend.name.equalsIgnoreCase(name)) return friend; } - return null; } @@ -100,9 +104,7 @@ public boolean isEmpty() { @Override public NbtCompound toTag() { NbtCompound tag = new NbtCompound(); - tag.put("friends", NbtUtils.listToTag(friends)); - return tag; } @@ -131,4 +133,36 @@ public Friends fromTag(NbtCompound tag) { return this; } + + public int importFromMio() throws Exception { + Path path = Paths.get( + MinecraftClient.getInstance().runDirectory.getAbsolutePath(), + "mio-fabric", + "socials.json" + ); + + if (!Files.exists(path)) return -1; + + String json = Files.readString(path); + JsonObject root = JsonParser.parseString(json).getAsJsonObject(); + JsonArray socials = root.getAsJsonArray("socials"); + + int added = 0; + + for (JsonElement element : socials) { + JsonObject obj = element.getAsJsonObject(); + + String role = obj.get("role").getAsString(); + if (!role.equalsIgnoreCase("friend")) continue; + + String name = obj.get("name").getAsString(); + + if (get(name) == null) { + add(new Friend(name)); + added++; + } + } + + return added; + } } From 7200a06fd769e5aaef4d7138c2e0600eb57785aa Mon Sep 17 00:00:00 2001 From: Turtlegamer_ Date: Wed, 1 Apr 2026 16:43:11 +0200 Subject: [PATCH 2/2] added wurst support --- .../arguments/ClientArgumentType.java | 39 +++++++++++++++ .../commands/commands/FriendsCommand.java | 50 +++++++++++++------ .../meteorclient/systems/friends/Friends.java | 33 +++++++++++- 3 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 src/main/java/meteordevelopment/meteorclient/commands/arguments/ClientArgumentType.java diff --git a/src/main/java/meteordevelopment/meteorclient/commands/arguments/ClientArgumentType.java b/src/main/java/meteordevelopment/meteorclient/commands/arguments/ClientArgumentType.java new file mode 100644 index 0000000000..56e301737e --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/commands/arguments/ClientArgumentType.java @@ -0,0 +1,39 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.commands.arguments; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + +import java.util.Arrays; +import java.util.Collection; + +public class ClientArgumentType implements ArgumentType { + private static final String[] SUPPORTED_CLIENTS = { "mio", "wurst" }; + + public static ClientArgumentType create() { + return new ClientArgumentType(); + } + + public static String get(CommandContext context, String name) throws CommandSyntaxException { + String client = context.getArgument(name, String.class).toLowerCase(); + for (String s : SUPPORTED_CLIENTS) { + if (s.equals(client)) return s; + } + throw new SimpleCommandExceptionType(() -> "Unknown client: " + client).create(); + } + + @Override + public String parse(com.mojang.brigadier.StringReader reader) { + return reader.readUnquotedString(); + } + + public Collection getExamples() { + return Arrays.asList(SUPPORTED_CLIENTS); + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/commands/commands/FriendsCommand.java b/src/main/java/meteordevelopment/meteorclient/commands/commands/FriendsCommand.java index 97ee95f21a..149da10168 100644 --- a/src/main/java/meteordevelopment/meteorclient/commands/commands/FriendsCommand.java +++ b/src/main/java/meteordevelopment/meteorclient/commands/commands/FriendsCommand.java @@ -6,10 +6,12 @@ package meteordevelopment.meteorclient.commands.commands; import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import meteordevelopment.meteorclient.commands.Command; import meteordevelopment.meteorclient.commands.arguments.FriendArgumentType; import meteordevelopment.meteorclient.commands.arguments.PlayerListEntryArgumentType; +import meteordevelopment.meteorclient.commands.arguments.ClientArgumentType; import meteordevelopment.meteorclient.systems.friends.Friend; import meteordevelopment.meteorclient.systems.friends.Friends; import meteordevelopment.meteorclient.utils.player.ChatUtils; @@ -59,24 +61,44 @@ public void build(LiteralArgumentBuilder builder) { ) ); - // Sync Mio friends for now + // friend sync builder.then(literal("sync") .executes(context -> { - try { - int added = Friends.get().importFromMio(); - - if (added == -1) { - error("Mio socials.json not found."); - } else { - ChatUtils.sendMsg(0, Formatting.GRAY, "Imported %d Mio friends.".formatted(added)); - } - } catch (Exception e) { - e.printStackTrace(); - error("Failed to sync Mio friends."); - } - + ChatUtils.sendMsg(0, Formatting.GRAY, "Supported clients: mio, wurst, all"); return SINGLE_SUCCESS; }) + .then(argument("client", ClientArgumentType.create()) + .suggests((context, suggestionsBuilder) -> { + ClientArgumentType clientArg = ClientArgumentType.create(); + for (String client : clientArg.getExamples()) { + suggestionsBuilder.suggest(client); + } + return suggestionsBuilder.buildFuture(); + }) + .executes(context -> { + String client = ClientArgumentType.get(context, "client"); + int added = 0; + + try { + switch (client) { + case "mio" -> added = Friends.get().importFromMio(); + case "wurst" -> added = Friends.get().importFromWurst(); + } + + if (added == -1) { + error(client + " friend file not found."); + } else { + ChatUtils.sendMsg(0, Formatting.GRAY, "Imported " + added + " friends from " + client + "."); + } + + } catch (Exception e) { + e.printStackTrace(); + error("Failed to sync " + client + " friends."); + } + + return SINGLE_SUCCESS; + }) + ) ); // List friends diff --git a/src/main/java/meteordevelopment/meteorclient/systems/friends/Friends.java b/src/main/java/meteordevelopment/meteorclient/systems/friends/Friends.java index 50b8451dd1..c46a577a42 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/friends/Friends.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/friends/Friends.java @@ -96,6 +96,11 @@ public boolean isEmpty() { return friends.isEmpty(); } + public enum FriendClient { + MIO, + WURST + } + @Override public @NotNull Iterator iterator() { return friends.iterator(); @@ -133,7 +138,7 @@ public Friends fromTag(NbtCompound tag) { return this; } - + // Mio importer public int importFromMio() throws Exception { Path path = Paths.get( MinecraftClient.getInstance().runDirectory.getAbsolutePath(), @@ -151,12 +156,35 @@ public int importFromMio() throws Exception { for (JsonElement element : socials) { JsonObject obj = element.getAsJsonObject(); - String role = obj.get("role").getAsString(); if (!role.equalsIgnoreCase("friend")) continue; String name = obj.get("name").getAsString(); + if (get(name) == null) { + add(new Friend(name)); + added++; + } + } + return added; + } + + // Wurst importer + public int importFromWurst() throws Exception { + Path path = Paths.get( + MinecraftClient.getInstance().runDirectory.getAbsolutePath(), + "wurst", + "friends.json" + ); + + if (!Files.exists(path)) return -1; + + String json = Files.readString(path); + JsonArray array = JsonParser.parseString(json).getAsJsonArray(); + + int added = 0; + for (JsonElement element : array) { + String name = element.getAsString(); // <-- read as string if (get(name) == null) { add(new Friend(name)); added++; @@ -165,4 +193,5 @@ public int importFromMio() throws Exception { return added; } + //to add more just make a new import func and parse the friends file :0 }