From 32e8bb0bcf2fcb14f83d26c5515581c3b055f635 Mon Sep 17 00:00:00 2001 From: ineanto Date: Tue, 28 Mar 2023 20:48:09 +0200 Subject: [PATCH] feat: 1.19.4 support disguise seems broken for others as of late, and I can't seem to figure out the root cause. --- core/pom.xml | 2 +- dist/pom.xml | 5 + pom.xml | 1 + v1_19_R3/pom.xml | 68 +++++++++ .../net/artelnatif/nicko/impl/v1_19_R3.java | 140 ++++++++++++++++++ 5 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 v1_19_R3/pom.xml create mode 100644 v1_19_R3/src/main/java/net/artelnatif/nicko/impl/v1_19_R3.java diff --git a/core/pom.xml b/core/pom.xml index a0a865f..7f78d5d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -53,7 +53,7 @@ org.spigotmc spigot-api - 1.19.3-R0.1-SNAPSHOT + 1.19.4-R0.1-SNAPSHOT provided diff --git a/dist/pom.xml b/dist/pom.xml index 6049122..b1ecb77 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -106,5 +106,10 @@ v1_19_R2 ${project.parent.version} + + net.artelnatif + v1_19_R3 + ${project.parent.version} + \ No newline at end of file diff --git a/pom.xml b/pom.xml index b6d2b56..d62ed02 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ v1_18_R2 v1_19_R1 v1_19_R2 + v1_19_R3 diff --git a/v1_19_R3/pom.xml b/v1_19_R3/pom.xml new file mode 100644 index 0000000..eefd19d --- /dev/null +++ b/v1_19_R3/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + + net.artelnatif + nicko-parent + 1.0-SNAPSHOT + + + v1_19_R3 + 1.0-SNAPSHOT + + + + + net.md-5 + specialsource-maven-plugin + 1.2.4 + + + package + + remap + + remap-obf + + org.spigotmc:minecraft-server:1.19.4-R0.1-SNAPSHOT:txt:maps-mojang + true + org.spigotmc:spigot:1.19.4-R0.1-SNAPSHOT:jar:remapped-mojang + true + remapped-obf + + + + package + + remap + + remap-spigot + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar + org.spigotmc:minecraft-server:1.19.4-R0.1-SNAPSHOT:csrg:maps-spigot + org.spigotmc:spigot:1.19.4-R0.1-SNAPSHOT:jar:remapped-obf + + + + + + + + + + org.spigotmc + spigot + 1.19.4-R0.1-SNAPSHOT + remapped-mojang + provided + + + net.artelnatif + core + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/v1_19_R3/src/main/java/net/artelnatif/nicko/impl/v1_19_R3.java b/v1_19_R3/src/main/java/net/artelnatif/nicko/impl/v1_19_R3.java new file mode 100644 index 0000000..130d207 --- /dev/null +++ b/v1_19_R3/src/main/java/net/artelnatif/nicko/impl/v1_19_R3.java @@ -0,0 +1,140 @@ +package net.artelnatif.nicko.impl; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; +import net.artelnatif.nicko.NickoBukkit; +import net.artelnatif.nicko.disguise.ActionResult; +import net.artelnatif.nicko.disguise.NickoProfile; +import net.artelnatif.nicko.mojang.MojangSkin; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.RemoteChatSession; +import net.minecraft.network.protocol.game.*; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.ProfilePublicKey; +import net.minecraft.world.level.Level; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Optional; +import java.util.UUID; +import java.util.logging.Logger; + +public class v1_19_R3 implements Internals { + final Logger logger = Bukkit.getLogger(); + + @Override + public void updateSelf(Player player) { + final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + final ServerLevel level = serverPlayer.getLevel(); + final ResourceKey levelResourceKey = serverPlayer.getLevel().dimension(); + final ClientboundRespawnPacket respawn = new ClientboundRespawnPacket(serverPlayer.level.dimensionTypeId(), + levelResourceKey, level.getWorld().getSeed(), + serverPlayer.gameMode.getGameModeForPlayer(), serverPlayer.gameMode.getPreviousGameModeForPlayer(), + level.isDebug(), + level.isFlat(), + (byte) 0x00, + Optional.empty()); + + final boolean wasFlying = player.isFlying(); + serverPlayer.connection.send(respawn); + player.setFlying(wasFlying); + player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); + player.updateInventory(); + } + + @Override + public void updateOthers(Player player) { + final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + + final ClientboundRemoveEntitiesPacket remove = new ClientboundRemoveEntitiesPacket(serverPlayer.getBukkitEntity().getEntityId()); + final ClientboundAddEntityPacket add = new ClientboundAddEntityPacket(serverPlayer); + + final SynchedEntityData entityData = serverPlayer.getEntityData(); + final EntityDataAccessor skinPartAccessor = new EntityDataAccessor<>(17, EntityDataSerializers.BYTE); + entityData.set(skinPartAccessor, (byte) 0x7f); + final ClientboundSetEntityDataPacket entityMetadata = new ClientboundSetEntityDataPacket(serverPlayer.getBukkitEntity().getEntityId(), entityData.getNonDefaultValues()); + + Bukkit.getOnlinePlayers().forEach(online -> { + final ServerPlayer onlineServerPlayer = ((CraftPlayer) online).getHandle(); + if (onlineServerPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) { + onlineServerPlayer.connection.send(remove); + onlineServerPlayer.connection.send(add); + } + onlineServerPlayer.connection.send(entityMetadata); + }); + } + + @Override + public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) { + final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName()); + final String profileName = profile.getName() == null ? player.getName() : profile.getName(); + + final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName); + + if (skinChange || changeOnlyName) { + final ActionResult skinFetch = fetchSkinTextures(profile, reset); + if (!skinFetch.isError()) { + final MojangSkin skin = skinFetch.getResult(); + final PropertyMap properties = gameProfile.getProperties(); + properties.removeAll("textures"); + properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature())); + } + } + + final ClientboundPlayerInfoUpdatePacket init = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(Collections.singletonList(serverPlayer)); + final ClientboundPlayerInfoRemovePacket remove = new ClientboundPlayerInfoRemovePacket(Collections.singletonList(player.getUniqueId())); + + RemoteChatSession chatSession; + if (serverPlayer.getChatSession() == null) { + NickoBukkit.getInstance().getLogger().warning("Chat Session of " + serverPlayer.displayName + " is null!"); + NickoBukkit.getInstance().getLogger().warning("If your server is in offline mode/under BungeeCord you can safely ignore this message."); + chatSession = null; + } else { + final UUID uuid = serverPlayer.getChatSession().sessionId(); + final ProfilePublicKey ppk = serverPlayer.getChatSession().profilePublicKey(); + chatSession = new RemoteChatSession(uuid, ppk); + } + + spoofPlayerInfoPacket(init, Collections.singletonList(new ClientboundPlayerInfoUpdatePacket.Entry( + player.getUniqueId(), + gameProfile, + true, + serverPlayer.latency, + serverPlayer.gameMode.getGameModeForPlayer(), + Component.literal(profileName), + chatSession == null ? null : chatSession.asData() + ))); + + + Bukkit.getOnlinePlayers().forEach(online -> { + final ServerPlayer onlinePlayer = ((CraftPlayer) online).getHandle(); + onlinePlayer.connection.send(remove); + onlinePlayer.connection.send(init); + }); + updateSelf(player); + // TODO: 3/17/23 Update signature to avoid duplicate for loop + updateOthers(player); + return new ActionResult<>(); + } + + private void spoofPlayerInfoPacket(Object object, Object newValue) { + try { + final Field field = object.getClass().getDeclaredField("b"); + field.setAccessible(true); + field.set(object, newValue); + } catch (NoSuchFieldException | IllegalAccessException e) { + NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")"); + } + } +}