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; + } + } + +} diff --git a/src/main/java/com/minelittlepony/PonyManager.java b/src/main/java/com/minelittlepony/PonyManager.java index 9ea6ec97..bc91dcc2 100644 --- a/src/main/java/com/minelittlepony/PonyManager.java +++ b/src/main/java/com/minelittlepony/PonyManager.java @@ -164,7 +164,7 @@ public class PonyManager implements IResourceManagerReloadListener, ISkinCacheCl MineLittlePony.logger.info("Detected {} background ponies installed.", getNumberOfPonies()); } - private ResourceLocation getDefaultSkin(UUID uuid) { + public static ResourceLocation getDefaultSkin(UUID uuid) { return isSlimSkin(uuid) ? ALEX : STEVE; } diff --git a/src/main/java/com/minelittlepony/mixin/MixinDefaultPlayerSkin.java b/src/main/java/com/minelittlepony/mixin/MixinDefaultPlayerSkin.java new file mode 100644 index 00000000..30e97ac0 --- /dev/null +++ b/src/main/java/com/minelittlepony/mixin/MixinDefaultPlayerSkin.java @@ -0,0 +1,44 @@ +package com.minelittlepony.mixin; + +import com.minelittlepony.MineLittlePony; +import com.minelittlepony.PonyManager; +import com.minelittlepony.pony.data.PonyLevel; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.util.ResourceLocation; +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 java.util.UUID; + +@Mixin(DefaultPlayerSkin.class) +public abstract class MixinDefaultPlayerSkin { + + @Inject(method = "getDefaultSkinLegacy", at = @At("HEAD"), cancellable = true) + private static void legacySkin(CallbackInfoReturnable cir) { + if (MineLittlePony.getConfig().getPonyLevel() == PonyLevel.PONIES) { + cir.setReturnValue(PonyManager.STEVE); + } + } + + @Inject(method = "getDefaultSkin", at = @At("HEAD"), cancellable = true) + private static void defaultSkin(UUID uuid, CallbackInfoReturnable cir) { + if (MineLittlePony.getConfig().getPonyLevel() == PonyLevel.PONIES) { + cir.setReturnValue(PonyManager.getDefaultSkin(uuid)); + } + } + + @Inject(method = "getSkinType", at = @At("HEAD"), cancellable = true) + private static void skinType(UUID uuid, CallbackInfoReturnable cir) { + if (MineLittlePony.getConfig().getPonyLevel() == PonyLevel.PONIES) { + + cir.setReturnValue(MineLittlePony.getInstance().getManager() + .getPony(PonyManager.getDefaultSkin(uuid), uuid) + .getRace(false) + .getModel() + .getId(PonyManager.isSlimSkin(uuid))); + } + } + +} diff --git a/src/main/resources/minelp.mixin.json b/src/main/resources/minelp.mixin.json index b9626380..690c59c4 100644 --- a/src/main/resources/minelp.mixin.json +++ b/src/main/resources/minelp.mixin.json @@ -5,10 +5,11 @@ "refmap": "minelp.mixin.refmap.json", "compatibilityLevel": "JAVA_8", "mixins": [ - "MixinThreadDownloadImageData", - "MixinRenderItem", + "MixinDefaultPlayerSkin", + "MixinGlStateManager", "MixinItemRenderer", + "MixinRenderItem", "MixinRenderManager", - "MixinGlStateManager" + "MixinThreadDownloadImageData" ] }