diff --git a/build.gradle b/build.gradle index 4dbcff2..aaf211a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,8 @@ import net.fabricmc.loom.task.RemapJarTask plugins { - id 'io.github.ladysnake.chenille' version '0.7.0' + id 'fabric-loom' version '0.12-SNAPSHOT' + id 'io.github.ladysnake.chenille' version '0.9.0' id 'io.github.juuxel.loom-quiltflower' version "1.6.0" } @@ -38,8 +39,8 @@ dependencies { modIncludeApi libs.cca.base modIncludeImplementation libs.cca.entity modCompileOnly compatLibs.illuminations -// modRuntimeOnly compatLibs.illuminations - modTestImplementation libs.elmendorf + modRuntimeOnly compatLibs.illuminations + modLocalImplementation libs.elmendorf api "org.jetbrains:annotations:${jb_annotations_version}" api "org.apiguardian:apiguardian-api:${apiguardian_version}" @@ -98,7 +99,7 @@ assemble.dependsOn(remapStandaloneJar) chenille { configurePublishing { - mainArtifact = remapStandaloneJar + mainArtifact = remapStandaloneJar.archiveFile withArtifactory() withCurseforgeRelease() withGithubRelease() diff --git a/changelog.md b/changelog.md index 3adc7f2..2aea74f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +------------------------------------------------------ +Version 2.6.0 +------------------------------------------------------ +Updated to MC 1.19 + ------------------------------------------------------ Version 2.5.0 ------------------------------------------------------ diff --git a/gradle.properties b/gradle.properties index 56cc469..cd40bcf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,17 +3,17 @@ org.gradle.jvmargs=-Xmx2G # Fabric Properties # check these on https://fabricmc.net/use -minecraft_version=1.18.2 -yarn_mappings=1.18.2+build.2 -loader_version=0.13.3 -fabric_version=0.50.0+1.18.2 +minecraft_version=1.19 +yarn_mappings=1.19+build.4 +loader_version=0.14.8 +fabric_version=0.57.0+1.19 # Other Dependencies jb_annotations_version = 23.0.0 apiguardian_version = 1.1.2 # Mod Properties -mod_version = 2.5.0 +mod_version = 2.6.0 maven_group = io.github.ladysnake archives_base_name = impersonate @@ -24,8 +24,7 @@ license_header = LGPL gpl_version = 3 modrinth_id = xBZuWXoj curseforge_id = 360333 -curseforge_versions = 1.18.2 +curseforge_versions = 1.19 cf_requirements = fabric-api cf_embeddeds = cardinal-components release_type = release -changelog_url = https://github.com/Ladysnake/Impersonate/blob/1.17/changelog.md diff --git a/gradle/compat-libs.versions.toml b/gradle/compat-libs.versions.toml index 3bd4310..11e2d26 100644 --- a/gradle/compat-libs.versions.toml +++ b/gradle/compat-libs.versions.toml @@ -1,5 +1,5 @@ [versions] -illuminations = "3401926" +illuminations = "3846131" [libraries] illuminations = { module = "curse.maven:illuminations-292908", version.ref = "illuminations" } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4a3852f..0eed590 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] -cca = "4.1.4" +cca = "5.0.1" fpa = "0.1-SNAPSHOT" -elmendorf = "0.5.2" +elmendorf = "0.6.0" [libraries] cca-base = { module = "dev.onyxstudios.cardinal-components-api:cardinal-components-base", version.ref = "cca" } diff --git a/settings.gradle b/settings.gradle index 93f917d..cd370d3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,6 +4,10 @@ pluginManagement { name = 'Fabric' url = 'https://maven.fabricmc.net/' } + maven { + name "Quilt" + url "https://maven.quiltmc.org/repository/release" + } maven { name = 'Cotton' url = 'https://server.bbkr.space/artifactory/libs-release/' diff --git a/src/main/java/io/github/ladysnake/impersonate/Impersonate.java b/src/main/java/io/github/ladysnake/impersonate/Impersonate.java index 77af11c..2330436 100644 --- a/src/main/java/io/github/ladysnake/impersonate/Impersonate.java +++ b/src/main/java/io/github/ladysnake/impersonate/Impersonate.java @@ -26,7 +26,7 @@ import io.github.ladysnake.impersonate.impl.ImpersonateGamerules; import io.github.ladysnake.impersonate.impl.PlayerImpersonator; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.minecraft.util.Identifier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -45,7 +45,7 @@ public final class Impersonate implements ModInitializer, EntityComponentInitial @Override public void onInitialize() { - CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> ImpersonateCommand.register(dispatcher)); + CommandRegistrationCallback.EVENT.register((dispatcher, acc, dedicated) -> ImpersonateCommand.register(dispatcher)); ImpersonateGamerules.init(); } diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/ImpersonateCommand.java b/src/main/java/io/github/ladysnake/impersonate/impl/ImpersonateCommand.java index d9f6da8..1cae530 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/ImpersonateCommand.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/ImpersonateCommand.java @@ -27,7 +27,7 @@ import net.minecraft.command.argument.IdentifierArgumentType; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.TranslatableText; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; @@ -99,9 +99,9 @@ private static int stopImpersonation(ServerCommandSource source, Collection Optional visit(StringVisitable.StyledVisitor visitor, Style style) { + return visitor.accept(style, this.getString()); } @Override - public String getRawString() { - return this.revealed ? this.trueText : this.fakedText; + public Optional visit(StringVisitable.Visitor visitor) { + return visitor.accept(this.getString()); } - @Override - public ImpersonateText copy() { - return new ImpersonateText(this.trueText, this.fakedText, this.revealed); + public String getString() { + return this.revealed ? this.trueText : this.fakedText; } } diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/PacketMeddling.java b/src/main/java/io/github/ladysnake/impersonate/impl/PacketMeddling.java index 31d2094..7150abc 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/PacketMeddling.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/PacketMeddling.java @@ -26,13 +26,14 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.MutableText; import java.util.function.Function; public final class PacketMeddling { public static void resolvePlayerListEntries(PlayerListS2CPacket packet, ServerPlayerEntity player) { - boolean reveal = ImpersonateText.shouldBeRevealedBy(player); + boolean reveal = ImpersonateTextContent.shouldBeRevealedBy(player); for (PlayerListS2CPacket.Entry entry : packet.getEntries()) { PlayerEntity playerEntry = player.server.getPlayerManager().getPlayer(entry.getProfile().getId()); if (playerEntry != null) { @@ -40,7 +41,7 @@ public static void resolvePlayerListEntries(PlayerListS2CPacket packet, ServerPl if (impersonator.isImpersonating()) { // OPs get the true profile with semi-fake display name, others get a complete lie if (reveal) { - ((PlayerListS2CPacketEntryAccessor) entry).setDisplayName(ImpersonateText.get(playerEntry, true)); + ((PlayerListS2CPacketEntryAccessor) entry).setDisplayName(MutableText.of(ImpersonateTextContent.get(playerEntry, true))); } else { ((PlayerListS2CPacketEntryAccessor) entry).setProfile(impersonator.getEditedProfile()); } diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/ServerPlayerSkins.java b/src/main/java/io/github/ladysnake/impersonate/impl/ServerPlayerSkins.java index 34a6a59..227f4d5 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/ServerPlayerSkins.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/ServerPlayerSkins.java @@ -53,6 +53,7 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -106,8 +107,9 @@ public static synchronized void setSkin(@NotNull ServerPlayerEntity player, Game /** * Sets the skin to the specified player and reloads it with {@link #reloadSkin(ServerPlayerEntity)} - * @param player player whose skin needs to be changed - * @param value skin texture value + * + * @param player player whose skin needs to be changed + * @param value skin texture value * @param signature skin texture signature */ private static void setPlayerSkin(ServerPlayerEntity player, @Nullable String value, @Nullable String signature) { @@ -127,10 +129,11 @@ private static void setPlayerSkin(ServerPlayerEntity player, @Nullable String va /** * Reloads player's skin for all the players (including the one that has changed the skin) + * * @param player player that wants to have the skin reloaded */ private static void reloadSkin(ServerPlayerEntity player) { - for(ServerPlayerEntity other : Objects.requireNonNull(player.getServer()).getPlayerManager().getPlayerList()) { + for (ServerPlayerEntity other : Objects.requireNonNull(player.getServer()).getPlayerManager().getPlayerList()) { // Refreshing tablist for each player other.networkHandler.sendPacket(new PlayerListS2CPacket(PlayerListS2CPacket.Action.REMOVE_PLAYER, player)); other.networkHandler.sendPacket(new PlayerListS2CPacket(PlayerListS2CPacket.Action.ADD_PLAYER, player)); @@ -138,7 +141,7 @@ private static void reloadSkin(ServerPlayerEntity player) { ChunkManager manager = player.world.getChunkManager(); assert manager instanceof ServerChunkManager; - ThreadedAnvilChunkStorage storage = ((ServerChunkManager)manager).threadedAnvilChunkStorage; + ThreadedAnvilChunkStorage storage = ((ServerChunkManager) manager).threadedAnvilChunkStorage; EntityTrackerAccessor trackerEntry = ((ThreadedAnvilChunkStorageAccessor) storage).getEntityTrackers().get(player.getId()); for (ServerPlayerEntity tracking : PlayerLookup.tracking(player)) { @@ -155,7 +158,17 @@ private static void reloadSkin(ServerPlayerEntity player) { private static void reloadSkinVanilla(ServerPlayerEntity player) { // need to change the player entity on the client ServerWorld targetWorld = (ServerWorld) player.world; - player.networkHandler.sendPacket(new PlayerRespawnS2CPacket(targetWorld.method_40134(), targetWorld.getRegistryKey(), BiomeAccess.hashSeed(targetWorld.getSeed()), player.interactionManager.getGameMode(), player.interactionManager.getPreviousGameMode(), targetWorld.isDebugWorld(), targetWorld.isFlat(), true)); + player.networkHandler.sendPacket(new PlayerRespawnS2CPacket( + targetWorld.getDimensionKey(), + targetWorld.getRegistryKey(), + BiomeAccess.hashSeed(targetWorld.getSeed()), + player.interactionManager.getGameMode(), + player.interactionManager.getPreviousGameMode(), + targetWorld.isDebugWorld(), + targetWorld.isFlat(), + true, + player.getLastDeathPos() + )); player.networkHandler.requestTeleport(player.getX(), player.getY(), player.getZ(), player.getYaw(), player.getPitch()); player.server.getPlayerManager().sendCommandTree(player); player.networkHandler.sendPacket(new ExperienceBarUpdateS2CPacket(player.experienceProgress, player.totalExperience, player.experienceLevel)); diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ListCommandMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ListCommandMixin.java index 006e1d3..e50029d 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ListCommandMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ListCommandMixin.java @@ -22,7 +22,7 @@ import net.minecraft.server.command.ListCommand; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; +import net.minecraft.text.TranslatableTextContent; import org.spongepowered.asm.mixin.Dynamic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -38,8 +38,8 @@ public abstract class ListCommandMixin { private static void fakeNameAndUuid(ServerPlayerEntity player, CallbackInfoReturnable cir) { Text text = cir.getReturnValue(); - if (text instanceof TranslatableText) { - Object[] args = ((TranslatableText) text).getArgs(); + if (text instanceof TranslatableTextContent cnt) { + Object[] args = cnt.getArgs(); // Defend against other mods changing the text if (args.length == 2 && args[0] instanceof Text && args[1] instanceof UUID) { GameProfile impersonatedProfile = Impersonate.IMPERSONATION.get(player).getImpersonatedProfile(); diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/MinecraftServerMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/MinecraftServerMixin.java index c1cf5ab..6e25436 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/MinecraftServerMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/MinecraftServerMixin.java @@ -37,7 +37,7 @@ public abstract class MinecraftServerMixin implements CommandOutput { @Shadow public abstract ServerWorld getOverworld(); - @ModifyVariable(method = "sendSystemMessage", at = @At("HEAD"), argsOnly = true) + @ModifyVariable(method = "sendMessage", at = @At("HEAD"), argsOnly = true) private Text revealImpersonatorsInMessages(Text message) { if (this.getOverworld() == null || this.getGameRules().getBoolean(ImpersonateGamerules.LOG_REVEAL_IMPERSONATIONS)) { return ((RecipientAwareText) message).impersonateResolveAll(this); diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/MutableTextMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/MutableTextMixin.java index 4121d00..6d202a0 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/MutableTextMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/MutableTextMixin.java @@ -23,18 +23,12 @@ import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; -import java.util.List; - @Mixin(MutableText.class) -public interface MutableTextMixin extends Text, RecipientAwareText { +public abstract class MutableTextMixin implements Text, RecipientAwareText { @Override - default Text impersonateResolveAll(CommandOutput recipient) { + public Text impersonateResolveAll(CommandOutput recipient) { this.impersonateResolve(recipient); - List siblings = this.getSiblings(); - for (int i = 0; i < siblings.size(); i++) { - Text sibling = siblings.get(i); - siblings.set(i, ((RecipientAwareText) sibling).impersonateResolveAll(recipient)); - } + this.getSiblings().replaceAll(text -> ((RecipientAwareText) text).impersonateResolveAll(recipient)); return this; } } diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/PlayerEntityMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/PlayerEntityMixin.java index ba9b8e9..22c33fd 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/PlayerEntityMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/PlayerEntityMixin.java @@ -19,13 +19,14 @@ import com.mojang.authlib.GameProfile; import io.github.ladysnake.impersonate.Impersonator; -import io.github.ladysnake.impersonate.impl.ImpersonateText; +import io.github.ladysnake.impersonate.impl.ImpersonateTextContent; import io.github.ladysnake.impersonate.impl.PlayerEntityExtensions; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.data.DataTracker; import net.minecraft.entity.data.TrackedData; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Final; @@ -82,7 +83,7 @@ private void fakeName(CallbackInfoReturnable cir) { PlayerEntity self = ((PlayerEntity) (Object) this); if (Impersonator.get(self).isImpersonating()) { // if the client is aware that there is an impersonation, they should display it - cir.setReturnValue(ImpersonateText.get(self, world.isClient)); + cir.setReturnValue(MutableText.of(ImpersonateTextContent.get(self, world.isClient))); } } } diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/PlayerManagerMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/PlayerManagerMixin.java index 6c89fb9..abcafe8 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/PlayerManagerMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/PlayerManagerMixin.java @@ -17,11 +17,11 @@ */ package io.github.ladysnake.impersonate.impl.mixin; +import com.mojang.authlib.GameProfile; import io.github.ladysnake.impersonate.Impersonator; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -29,12 +29,12 @@ @Mixin(PlayerManager.class) public class PlayerManagerMixin { - @Redirect(method = "loadPlayerData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;getName()Lnet/minecraft/text/Text;")) - private Text resolvePlayerName(ServerPlayerEntity player) { - return new LiteralText(Impersonator.get(player).getActualProfile().getName()); + @Redirect(method = "loadPlayerData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;getGameProfile()Lcom/mojang/authlib/GameProfile;")) + private GameProfile resolvePlayerName(ServerPlayerEntity player) { + return Impersonator.get(player).getActualProfile(); } @Redirect(method = "createStatHandler", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;getName()Lnet/minecraft/text/Text;")) private Text resolvePlayerStatsName(PlayerEntity player) { - return new LiteralText(Impersonator.get(player).getActualProfile().getName()); + return Text.literal(Impersonator.get(player).getActualProfile().getName()); } } diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ServerPlayNetworkHandlerMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ServerPlayNetworkHandlerMixin.java index 13d31f0..636661e 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ServerPlayNetworkHandlerMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ServerPlayNetworkHandlerMixin.java @@ -41,8 +41,8 @@ public abstract class ServerPlayNetworkHandlerMixin { private Packet resolveFakeTextsInPackets(Packet packet) { if (packet instanceof GameMessageS2CPacket gamePacket) { if (this.existsImpersonator()) { - Text resolvedText = ((RecipientAwareText) gamePacket.getMessage()).impersonateResolveAll(player); - return new GameMessageS2CPacket(resolvedText, gamePacket.getType(), gamePacket.getSender()); + Text resolvedText = ((RecipientAwareText) gamePacket.content()).impersonateResolveAll(player); + return new GameMessageS2CPacket(resolvedText, gamePacket.typeId()); } } else if (packet instanceof PlayerListS2CPacket listPacket) { if (this.existsImpersonator()) { diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ServerPlayerEntityMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ServerPlayerEntityMixin.java index a1ae55b..1959246 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ServerPlayerEntityMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/ServerPlayerEntityMixin.java @@ -22,6 +22,7 @@ import io.github.ladysnake.impersonate.impl.ImpersonateGamerules; import io.github.ladysnake.impersonate.impl.PlayerEntityExtensions; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.encryption.PlayerPublicKey; import net.minecraft.network.packet.c2s.play.ClientSettingsC2SPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.BlockPos; @@ -34,8 +35,8 @@ @Mixin(ServerPlayerEntity.class) public abstract class ServerPlayerEntityMixin extends PlayerEntity implements PlayerEntityExtensions { - public ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile profile) { - super(world, pos, yaw, profile); + public ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile profile, PlayerPublicKey key) { + super(world, pos, yaw, profile, key); } @Inject(method = "setClientSettings", at = @At("RETURN")) diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TextMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TextMixin.java index 0f46673..7a26a1d 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TextMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TextMixin.java @@ -17,11 +17,13 @@ */ package io.github.ladysnake.impersonate.impl.mixin; +import io.github.ladysnake.impersonate.impl.ImpersonateTextContent; import io.github.ladysnake.impersonate.impl.RecipientAwareText; import net.minecraft.server.command.CommandOutput; import net.minecraft.text.MutableText; import net.minecraft.text.Style; import net.minecraft.text.Text; +import net.minecraft.text.TextContent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -39,9 +41,14 @@ public interface TextMixin extends RecipientAwareText { @Shadow Style getStyle(); + @Shadow + TextContent getContent(); + @Override default void impersonateResolve(CommandOutput recipient) { - // NO-OP + if (this.getContent() instanceof ImpersonateTextContent txt) { + txt.impersonateResolve(recipient); + } } @Override diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TextSerializerMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TextSerializerMixin.java new file mode 100644 index 0000000..c04c786 --- /dev/null +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TextSerializerMixin.java @@ -0,0 +1,48 @@ +/* + * Impersonate + * Copyright (C) 2020-2022 Ladysnake + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; If not, see . + */ +package io.github.ladysnake.impersonate.impl.mixin; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import io.github.ladysnake.impersonate.impl.ImpersonateTextContent; +import net.minecraft.text.Text; +import net.minecraft.text.TextContent; +import org.objectweb.asm.Opcodes; +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.lang.reflect.Type; + +@Mixin(Text.Serializer.class) +public class TextSerializerMixin { + @Inject(method = "serialize(Lnet/minecraft/text/Text;Ljava/lang/reflect/Type;Lcom/google/gson/JsonSerializationContext;)Lcom/google/gson/JsonElement;", + at = @At(value = "FIELD", target = "Lnet/minecraft/text/TextContent;EMPTY:Lnet/minecraft/text/TextContent;", opcode = Opcodes.GETSTATIC), + locals = LocalCapture.CAPTURE_FAILSOFT, + cancellable = true + ) + private void serializeImpersonateTexts(Text text, Type type, JsonSerializationContext jsonSerializationContext, CallbackInfoReturnable cir, JsonObject jsonObject, TextContent textContent) { + if (text instanceof ImpersonateTextContent cnt) { + jsonObject.addProperty("text", cnt.getString()); + cir.setReturnValue(jsonObject); + } + } +} diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TranslatableTextMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TranslatableTextMixin.java index 843d5a6..63a3edb 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TranslatableTextMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/TranslatableTextMixin.java @@ -19,12 +19,12 @@ import io.github.ladysnake.impersonate.impl.RecipientAwareText; import net.minecraft.server.command.CommandOutput; -import net.minecraft.text.TranslatableText; +import net.minecraft.text.TranslatableTextContent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -@Mixin(TranslatableText.class) +@Mixin(TranslatableTextContent.class) public abstract class TranslatableTextMixin implements RecipientAwareText { @Shadow @Final diff --git a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/client/IntegratedPlayerManagerMixin.java b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/client/IntegratedPlayerManagerMixin.java index 2701399..60ae238 100644 --- a/src/main/java/io/github/ladysnake/impersonate/impl/mixin/client/IntegratedPlayerManagerMixin.java +++ b/src/main/java/io/github/ladysnake/impersonate/impl/mixin/client/IntegratedPlayerManagerMixin.java @@ -17,19 +17,18 @@ */ package io.github.ladysnake.impersonate.impl.mixin.client; +import com.mojang.authlib.GameProfile; import io.github.ladysnake.impersonate.Impersonator; import net.minecraft.server.integrated.IntegratedPlayerManager; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(IntegratedPlayerManager.class) public abstract class IntegratedPlayerManagerMixin { - @Redirect(method = "savePlayerData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;getName()Lnet/minecraft/text/Text;")) - private Text resolveText(ServerPlayerEntity player) { - return new LiteralText(Impersonator.get(player).getActualProfile().getName()); + @Redirect(method = "savePlayerData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;getGameProfile()Lcom/mojang/authlib/GameProfile;")) + private GameProfile resolveText(ServerPlayerEntity player) { + return Impersonator.get(player).getActualProfile(); } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e12c8a5..7ccfce5 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -40,10 +40,10 @@ } ], "depends": { - "minecraft": ">=1.18-", + "minecraft": ">=1.19-", "fabric": "*", - "cardinal-components-base": "^4.0.0-", - "cardinal-components-entity": "^4.0.0-", + "cardinal-components-base": "^5.0.0-", + "cardinal-components-entity": "^5.0.0-", "fabric-permissions-api-v0": "*" }, "custom": { diff --git a/src/main/resources/mixins.impersonate.common.json b/src/main/resources/mixins.impersonate.common.json index 27f25d8..d67d9ca 100644 --- a/src/main/resources/mixins.impersonate.common.json +++ b/src/main/resources/mixins.impersonate.common.json @@ -16,6 +16,7 @@ "ServerPlayerEntityMixin", "ServerPlayNetworkHandlerMixin", "TextMixin", + "TextSerializerMixin", "ThreadedAnvilChunkStorageAccessor", "TranslatableTextMixin" ], diff --git a/src/testmod/java/io/github/ladysnake/impersonatest/ImpersonateTestSuite.java b/src/testmod/java/io/github/ladysnake/impersonatest/ImpersonateTestSuite.java index 7214965..bcea168 100644 --- a/src/testmod/java/io/github/ladysnake/impersonatest/ImpersonateTestSuite.java +++ b/src/testmod/java/io/github/ladysnake/impersonatest/ImpersonateTestSuite.java @@ -31,7 +31,7 @@ import java.util.UUID; public class ImpersonateTestSuite implements FabricGameTest { - @GameTest(structureName = EMPTY_STRUCTURE) + @GameTest(templateName = EMPTY_STRUCTURE) public void nameChanges(TestContext ctx) { Identifier key = new Identifier("impersonatest", "key"); GameProfile profile = new GameProfile(UUID.randomUUID(), "impersonator"); @@ -39,7 +39,7 @@ public void nameChanges(TestContext ctx) { Text formerName = player.getDisplayName(); Impersonator impersonator = player.getComponent(Impersonate.IMPERSONATION); impersonator.impersonate(key, profile); - GameTestUtil.assertTrue("Expected player to have name \"impersonator\", was %s".formatted(player.getDisplayName()), "impersonator".equals(player.getDisplayName().asString())); + GameTestUtil.assertTrue("Expected player to have name \"impersonator\", was %s".formatted(player.getDisplayName()), "impersonator".equals(player.getDisplayName().getString())); impersonator.stopImpersonation(key); GameTestUtil.assertTrue("Expected player to have name %s, was %s".formatted(formerName, player.getDisplayName()), formerName.equals(player.getDisplayName())); ctx.complete();