From 031d1ddd338c5d61f819d933b1769b05332a34a9 Mon Sep 17 00:00:00 2001 From: Matthew Messinger Date: Wed, 29 Aug 2018 23:03:50 -0400 Subject: [PATCH] Fix model updating on NPCs that are not in the player list. --- .../voxelmodpack/hdskins/HDSkinManager.java | 25 +++++++++++++++---- .../hdskins/mixin/MixinNetworkPlayerInfo.java | 6 +++++ .../voxelmodpack/hdskins/util/PlayerUtil.java | 25 +++++++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/util/PlayerUtil.java diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java index 528321eb..8208b363 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java @@ -24,8 +24,11 @@ import com.voxelmodpack.hdskins.skins.LegacySkinServer; import com.voxelmodpack.hdskins.skins.ServerType; import com.voxelmodpack.hdskins.skins.SkinServer; import com.voxelmodpack.hdskins.skins.ValhallaSkinServer; +import com.voxelmodpack.hdskins.util.PlayerUtil; import com.voxelmodpack.hdskins.util.ProfileTextureUtil; import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.client.renderer.texture.ITextureObject; @@ -33,6 +36,7 @@ import net.minecraft.client.resources.DefaultPlayerSkin; import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.client.resources.SkinManager; +import net.minecraft.util.EntitySelectors; import net.minecraft.util.ResourceLocation; import org.apache.commons.io.FileUtils; import org.apache.http.impl.client.CloseableHttpClient; @@ -57,6 +61,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.stream.Stream; import javax.annotation.Nullable; public final class HDSkinManager implements IResourceManagerReloadListener { @@ -230,10 +235,10 @@ public final class HDSkinManager implements IResourceManagerReloadListener { private boolean onSkinCacheCleared(ISkinCacheClearListener callback) { try { - return callback.onSkinCacheCleared(); + return !callback.onSkinCacheCleared(); } catch (Exception e) { logger.warn("Exception encountered calling skin listener '{}'. It will be removed.", callback.getClass().getName(), e); - return false; + return true; } } @@ -258,14 +263,25 @@ public final class HDSkinManager implements IResourceManagerReloadListener { public void reloadSkins() { - NetHandlerPlayClient playClient = Minecraft.getMinecraft().getConnection(); + Stream stream = Stream.empty(); + + Minecraft mc = Minecraft.getMinecraft(); + NetHandlerPlayClient playClient = mc.getConnection(); if (playClient != null) { - playClient.getPlayerInfoMap().forEach(this::clearNetworkSkin); + stream = playClient.getPlayerInfoMap().stream(); } + // NPCs might not be in the player list + WorldClient world = mc.world; + if (world != null) { + stream = Stream.concat(stream, world.getPlayers(AbstractClientPlayer.class, EntitySelectors.IS_ALIVE).stream().map(PlayerUtil::getInfo)); + } + stream.distinct().forEach(this::clearNetworkSkin); + clearListeners.removeIf(this::onSkinCacheCleared); } public void parseSkin(GameProfile profile, Type type, ResourceLocation resource, MinecraftProfileTexture texture) { + // grab the metadata object via reflection. Object is live. Map metadata = ProfileTextureUtil.getMetadata(texture); boolean wasNull = metadata == null; @@ -280,7 +296,6 @@ public final class HDSkinManager implements IResourceManagerReloadListener { } } - @Override public void onResourceManagerReload(IResourceManager resourceManager) { this.resources.onResourceManagerReload(resourceManager); diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinNetworkPlayerInfo.java b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinNetworkPlayerInfo.java index 3948599d..b48501ac 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinNetworkPlayerInfo.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinNetworkPlayerInfo.java @@ -32,6 +32,8 @@ public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo { @Shadow private boolean playerTexturesLoaded; @Shadow private String skinType; + @Shadow private Map playerTextures; + @SuppressWarnings("InvalidMemberReference") // mc-dev bug? @Redirect(method = { "getLocationSkin", @@ -95,6 +97,10 @@ public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo { @Override public void reloadTextures() { synchronized (this) { + this.playerTextures.clear(); + this.customProfiles.clear(); + this.customTextures.clear(); + this.skinType = null; this.playerTexturesLoaded = false; if (this.gameProfile.getId().equals(Minecraft.getMinecraft().getSession().getProfile().getId())) { // local client skin doesn't have a signature. diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/util/PlayerUtil.java b/src/hdskins/java/com/voxelmodpack/hdskins/util/PlayerUtil.java new file mode 100644 index 00000000..99324fad --- /dev/null +++ b/src/hdskins/java/com/voxelmodpack/hdskins/util/PlayerUtil.java @@ -0,0 +1,25 @@ +package com.voxelmodpack.hdskins.util; + +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.network.NetworkPlayerInfo; +import org.apache.commons.lang3.reflect.FieldUtils; + +import java.lang.reflect.Field; + +public class PlayerUtil { + + private static final Field playerInfo = FieldUtils.getAllFields(AbstractClientPlayer.class)[0]; + + public static NetworkPlayerInfo getInfo(AbstractClientPlayer player) { + try { + if (!playerInfo.isAccessible()) { + playerInfo.setAccessible(true); + } + return (NetworkPlayerInfo) FieldUtils.readField(playerInfo, player); + } catch (IllegalAccessException e) { + e.printStackTrace(); + return null; + } + } + +}