diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java index feecd37..6a506ac 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java @@ -23,7 +23,7 @@ import java.util.UUID; import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor; public class UsernameCommand { - private static final Session ORIGINAL_SESSION = ((MinecraftClientAccessor) MinecraftClient.getInstance()).session(); + private static final Session ORIGINAL_SESSION = MinecraftClient.getInstance().getSession(); private static final SimpleCommandExceptionType USERNAME_TOO_LONG = new SimpleCommandExceptionType(Text.translatable("The specified username is longer than 16 characters")); public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) { diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java index 04f2cb8..dad746f 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java @@ -1,15 +1,13 @@ package land.chipmunk.chipmunkmod.mixin; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.session.Session; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(net.minecraft.client.MinecraftClient.class) +@Mixin(MinecraftClient.class) public interface MinecraftClientAccessor { - @Accessor("session") - Session session (); - @Mutable @Accessor("session") void session (Session session); diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/StringHelperMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/StringHelperMixin.java index df42151..cc5a76a 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/StringHelperMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/StringHelperMixin.java @@ -8,16 +8,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(StringHelper.class) public class StringHelperMixin { - @Inject(method = "truncateChat", at = @At("HEAD"), cancellable = true) - private static void truncateChat (String text, CallbackInfoReturnable<String> cir) { - cir.setReturnValue(text); - } - - @Inject(method = "stripTextFormat", at = @At("HEAD"), cancellable = true) - private static void stripTextFormat(String text, CallbackInfoReturnable<String> cir) { - cir.setReturnValue(text); - } - @Inject(method = "isValidChar", at = @At("HEAD"), cancellable = true) private static void isValidChar (char chr, CallbackInfoReturnable<Boolean> cir) { cir.setReturnValue(chr >= ' ' && chr != '\u007f'); diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/TextMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/TextMixin.java deleted file mode 100644 index c5e1d08..0000000 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/TextMixin.java +++ /dev/null @@ -1,26 +0,0 @@ -package land.chipmunk.chipmunkmod.mixin; - -import net.minecraft.text.StringVisitable; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.Iterator; -import java.util.Optional; - -@Mixin(Text.class) -public interface TextMixin { - @Inject(method = "visit(Lnet/minecraft/text/StringVisitable$StyledVisitor;Lnet/minecraft/text/Style;)Ljava/util/Optional;", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Text;visit(Lnet/minecraft/text/StringVisitable$StyledVisitor;Lnet/minecraft/text/Style;)Ljava/util/Optional;"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) - private <T> void visit (StringVisitable.StyledVisitor<T> styledVisitor, Style style, CallbackInfoReturnable<Optional<T>> cir, Style style2, Optional optional, Iterator var5, Text text) { - if (text == null) cir.setReturnValue(Optional.empty()); - } - - @Inject(method = "visit(Lnet/minecraft/text/StringVisitable$Visitor;)Ljava/util/Optional;", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Text;visit(Lnet/minecraft/text/StringVisitable$Visitor;)Ljava/util/Optional;"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) - private <T> void visit (StringVisitable.Visitor<T> visitor, CallbackInfoReturnable<Optional<T>> cir, Optional optional, Iterator var3, Text text) { - if (text == null) cir.setReturnValue(Optional.empty()); - } -} diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/TextSerializerMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/TextSerializerMixin.java deleted file mode 100644 index 0dd85e0..0000000 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/TextSerializerMixin.java +++ /dev/null @@ -1,62 +0,0 @@ -package land.chipmunk.chipmunkmod.mixin; - -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.lang.reflect.Type; - -@Mixin(Text.Serializer.class) -public class TextSerializerMixin { - @Unique private static final int LIMIT = 8; - - @Unique private int i; - - @Unique - private boolean checkDepth (JsonElement element) { - if (element.isJsonPrimitive()) return false; - else if (i >= LIMIT) return true; - - if (element.isJsonArray()) { - i++; - - for (JsonElement item : element.getAsJsonArray()) if (checkDepth(item)) return true; - } else if (element.isJsonObject()) { - final JsonObject object = element.getAsJsonObject(); - - JsonArray array; - - if (object.has("extra")) array = object.get("extra").getAsJsonArray(); - else if (object.has("with")) array = object.get("with").getAsJsonArray(); - else return false; - - i++; - - for (JsonElement member : array) if (checkDepth(member)) return true; - } - - return false; - } - - @Inject(method = "deserialize(Lcom/google/gson/JsonElement;Ljava/lang/reflect/Type;Lcom/google/gson/JsonDeserializationContext;)Lnet/minecraft/text/MutableText;", at = @At("HEAD"), cancellable = true) - private void deserialize (JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext, CallbackInfoReturnable<MutableText> cir) { - i = 0; // better way to do this? - - final boolean overLimit = checkDepth(jsonElement); - - if (!overLimit) return; - - cir.setReturnValue(Text.empty()); // just ignores it - - cir.cancel(); - } -} diff --git a/src/main/java/land/chipmunk/chipmunkmod/modules/RainbowName.java b/src/main/java/land/chipmunk/chipmunkmod/modules/RainbowName.java index 25a2c1b..ac4bba9 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/modules/RainbowName.java +++ b/src/main/java/land/chipmunk/chipmunkmod/modules/RainbowName.java @@ -1,8 +1,11 @@ package land.chipmunk.chipmunkmod.modules; +import com.mojang.authlib.GameProfile; import land.chipmunk.chipmunkmod.util.ColorUtilities; +import land.chipmunk.chipmunkmod.util.RandomUtilities; +import land.chipmunk.chipmunkmod.util.UUIDUtilities; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; @@ -18,17 +21,13 @@ public class RainbowName { public static final RainbowName INSTANCE = new RainbowName(MinecraftClient.getInstance()); - private static final String BUKKIT_COLOR_CODES = "123456789abcdefklmorx"; - private static final String TEAM_NAME_CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.+"; - - private Timer timer = null; + private final Random random = new Random(); public boolean enabled = false; + private Timer timer = null; - private String[] team; - + private String team; public String displayName; - private int startHue = 0; public void init () { @@ -44,72 +43,28 @@ public class RainbowName { timer.schedule(task, 0, 50); } - private String[] generateColorCodes(int length) { - String SALTCHARS = BUKKIT_COLOR_CODES; - StringBuilder salt = new StringBuilder(); - Random rnd = new Random(); - while (salt.length() < length) { // length of the random string. - int index = (int) (rnd.nextFloat() * SALTCHARS.length()); - salt.append(SALTCHARS.charAt(index)); - } - String saltStr = salt.toString(); - return saltStr.split(""); - } - - private String generateUsername (String[] codes) { - StringBuilder string = new StringBuilder(); - for (String code : codes) string.append("&").append(code); - return string.toString(); - } - - private String generateUsername (int _codes) { - StringBuilder string = new StringBuilder(); - - final String[] codes = generateColorCodes(_codes); - - for (String code : codes) string.append("&").append(code); - return string.toString(); - } - - private String generateUsername (char[] codes, char character) { - StringBuilder string = new StringBuilder(); - for (char code : codes) string.append(character + code); - return string.toString(); - } - - private String[] generateTeamName () { - String SALTCHARS = TEAM_NAME_CHARACTERS; - StringBuilder salt = new StringBuilder(); - Random rnd = new Random(); - while (salt.length() < TEAM_NAME_CHARACTERS.length()) { // length of the random string. - int index = (int) (rnd.nextFloat() * SALTCHARS.length()); - salt.append(SALTCHARS.charAt(index)); - } - String saltStr = salt.toString(); - return saltStr.split(""); - } - public void enable () { - final String[] colorCodes = generateColorCodes(8); - client.getNetworkHandler().sendChatCommand("extras:username " + generateUsername(colorCodes)); + final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); + final GameProfile profile = networkHandler.getProfile(); - team = generateTeamName(); + final String username = RandomUtilities.emptyUsername(random); + team = RandomUtilities.randomString(random, RandomUtilities.TEAM_ALLOWED_CHARS, 16); + final String selfSelector = UUIDUtilities.selector(profile.getId()); - CommandCore.INSTANCE.run("minecraft:team add " + String.join("", team)); - - CommandCore.INSTANCE.run("minecraft:execute as " + client.getNetworkHandler().getProfile().getId() + " run team join " + String.join("", team)); + networkHandler.sendChatCommand("extras:username " + username); + CommandCore.INSTANCE.run("minecraft:team add " + team); + CommandCore.INSTANCE.run("minecraft:team join " + team + " " + selfSelector); enabled = true; } public void disable () { - client.getNetworkHandler().sendChatCommand("extras:username " + client.getSession().getUsername()); - - CommandCore.INSTANCE.run("minecraft:team remove " + String.join("", team)); - team = null; - - CommandCore.INSTANCE.run("essentials:nick " + client.getSession().getUsername() + " off"); + final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); + final GameProfile profile = networkHandler.getProfile(); + CommandCore.INSTANCE.run("essentials:nick " + profile.getId() + " off"); + CommandCore.INSTANCE.run("minecraft:team remove " + team); + networkHandler.sendChatCommand("extras:username " + profile.getName()); enabled = false; } @@ -129,6 +84,7 @@ public class RainbowName { if (!enabled) return; + final GameProfile profile = networkHandler.getProfile(); int hue = startHue; int increment = (int) (360.0 / Math.max(displayName.length(), 20)); @@ -142,8 +98,8 @@ public class RainbowName { hue = (hue + increment) % 360; } - CommandCore.INSTANCE.run("minecraft:team modify " + String.join("", team) + " prefix " + GsonComponentSerializer.gson().serialize(component)); - CommandCore.INSTANCE.run("essentials:nick " + client.getSession().getUsername() + " " + essentialsNickname); + CommandCore.INSTANCE.run("minecraft:team modify " + team + " prefix " + GsonComponentSerializer.gson().serialize(component)); + CommandCore.INSTANCE.run("essentials:nick " + profile.getId() + " " + essentialsNickname); startHue = (startHue + increment) % 360; } catch (Exception e) { diff --git a/src/main/java/land/chipmunk/chipmunkmod/util/BotValidationUtilities.java b/src/main/java/land/chipmunk/chipmunkmod/util/BotValidationUtilities.java index d3ba6dc..1d518da 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/util/BotValidationUtilities.java +++ b/src/main/java/land/chipmunk/chipmunkmod/util/BotValidationUtilities.java @@ -8,6 +8,7 @@ import land.chipmunk.chipmunkmod.modules.custom_chat.CustomChat; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; +import org.apache.commons.codec.binary.Hex; import java.math.BigInteger; import java.nio.ByteBuffer; @@ -85,7 +86,7 @@ public class BotValidationUtilities { String time = String.valueOf(System.currentTimeMillis() / 5_000); String input = client.player.getUuidAsString() + arguments[0] + time + key; byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8)); - String stringHash = Hexadecimal.encode(hash).substring(0, 16); + String stringHash = new String(Hex.encodeHex(hash)).substring(0, 16); final boolean shouldSectionSign = CustomChat.INSTANCE.enabled && player.hasPermissionLevel(2) && player.isCreative(); diff --git a/src/main/java/land/chipmunk/chipmunkmod/util/Hexadecimal.java b/src/main/java/land/chipmunk/chipmunkmod/util/Hexadecimal.java deleted file mode 100644 index e71c25b..0000000 --- a/src/main/java/land/chipmunk/chipmunkmod/util/Hexadecimal.java +++ /dev/null @@ -1,15 +0,0 @@ -package land.chipmunk.chipmunkmod.util; - -public interface Hexadecimal { - static String encode (byte b) { - return "" + Character.forDigit((b >> 4) & 0xF, 16) + Character.forDigit((b & 0xF), 16); - } - - static String encode (byte[] array) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < array.length; i++) sb.append(encode(array[i])); - return sb.toString(); - } - - // TODO: Decode -} diff --git a/src/main/java/land/chipmunk/chipmunkmod/util/RandomUtilities.java b/src/main/java/land/chipmunk/chipmunkmod/util/RandomUtilities.java new file mode 100644 index 0000000..06fd06b --- /dev/null +++ b/src/main/java/land/chipmunk/chipmunkmod/util/RandomUtilities.java @@ -0,0 +1,34 @@ +package land.chipmunk.chipmunkmod.util; + +import java.util.Random; + +public final class RandomUtilities { + // https://github.com/kaboomserver/extras/blob/master/src/main/java/pw/kaboom/extras/util/Utility.java#L32 + public static final char[] LEGACY_STYLE_CODES = "0123456789abcdefklmnorx".toCharArray(); + public static final char[] TEAM_ALLOWED_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.+" + .toCharArray(); + + public static String emptyUsername(final Random random) { + final char[] buf = new char[16]; + + for (int i = 0; i < 16; i += 2) { + final int j = random.nextInt(LEGACY_STYLE_CODES.length); + + buf[i] = '&'; + buf[i + 1] = LEGACY_STYLE_CODES[j]; + } + + return new String(buf); + } + + public static String randomString(final Random random, final char[] charset, final int length) { + final char[] buf = new char[length]; + + for (int i = 0; i < length; i++) { + final int j = random.nextInt(charset.length); + buf[i] = charset[j]; + } + + return new String(buf); + } +} diff --git a/src/main/resources/chipmunkmod.mixins.json b/src/main/resources/chipmunkmod.mixins.json index 56ea828..6a09716 100644 --- a/src/main/resources/chipmunkmod.mixins.json +++ b/src/main/resources/chipmunkmod.mixins.json @@ -12,8 +12,6 @@ "MinecraftClientAccessor", "StringHelperMixin", "ElderGuardianAppearanceParticleMixin", - "TextMixin", - "TextSerializerMixin", "SoundSystemMixin", "TextFieldWidgetMixin" ],