Fix model updating on NPCs that are not in the player list.

This commit is contained in:
Matthew Messinger 2018-08-29 23:03:50 -04:00
parent f04d67caba
commit 031d1ddd33
3 changed files with 51 additions and 5 deletions

View file

@ -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<NetworkPlayerInfo> 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<String, String> 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);

View file

@ -32,6 +32,8 @@ public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo {
@Shadow private boolean playerTexturesLoaded;
@Shadow private String skinType;
@Shadow private Map<Type, ResourceLocation> 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.

View file

@ -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;
}
}
}