Changing pony level is now instant.

This commit is contained in:
Matthew Messinger 2018-10-06 13:43:56 -04:00
parent c6be9e5088
commit 882d1c5c7c
3 changed files with 35 additions and 34 deletions

View file

@ -41,7 +41,6 @@ import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.client.resources.SkinManager; import net.minecraft.client.resources.SkinManager;
import net.minecraft.client.resources.SkinManager.SkinAvailableCallback;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
@ -173,7 +172,8 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
public void fetchAndLoadSkins(GameProfile profile, SkinManager.SkinAvailableCallback callback) { public void fetchAndLoadSkins(GameProfile profile, SkinManager.SkinAvailableCallback callback) {
loadProfileTextures(profile).thenAcceptAsync(m -> m.forEach((type, pp) -> { loadProfileTextures(profile).thenAcceptAsync(m -> m.forEach((type, pp) -> {
loadTexture(type, pp, (typeIn, location, profileTexture) -> { loadTexture(type, pp, (typeIn, location, profileTexture) -> {
parseSkin(profile, typeIn, location, profileTexture, callback); parseSkin(profile, typeIn, location, profileTexture)
.thenRun(() -> callback.skinAvailable(typeIn, location, profileTexture));
}); });
}), Minecraft.getMinecraft()::addScheduledTask); }), Minecraft.getMinecraft()::addScheduledTask);
} }
@ -307,10 +307,9 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
.flatMap(a -> a.getPlayerInfoMap().stream()); .flatMap(a -> a.getPlayerInfoMap().stream());
} }
public void parseSkin(GameProfile profile, Type type, ResourceLocation resource, MinecraftProfileTexture texture, public CompletableFuture<Void> parseSkin(GameProfile profile, Type type, ResourceLocation resource, MinecraftProfileTexture texture) {
SkinAvailableCallback callback) {
CallableFutures.scheduleTask(() -> { return CallableFutures.scheduleTask(() -> {
// grab the metadata object via reflection. Object is live. // grab the metadata object via reflection. Object is live.
Map<String, String> metadata = ProfileTextureUtil.getMetadata(texture); Map<String, String> metadata = ProfileTextureUtil.getMetadata(texture);
@ -319,6 +318,9 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
if (wasNull) { if (wasNull) {
metadata = new HashMap<>(); metadata = new HashMap<>();
} else if (metadata.containsKey("model")) {
// try to reset the model.
metadata.put("model", metadata.get("model").contains("slim") ? "slim" : "default");
} }
for (ISkinParser parser : skinParsers) { for (ISkinParser parser : skinParsers) {
@ -333,7 +335,6 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
ProfileTextureUtil.setMetadata(texture, metadata); ProfileTextureUtil.setMetadata(texture, metadata);
} }
callback.skinAvailable(type, resource, texture);
}); });
} }

View file

@ -3,6 +3,4 @@ package com.voxelmodpack.hdskins.ducks;
public interface INetworkPlayerInfo { public interface INetworkPlayerInfo {
void reloadTextures(); void reloadTextures();
void setSkinType(String type);
} }

View file

@ -5,8 +5,6 @@ import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
import com.voxelmodpack.hdskins.HDSkinManager; import com.voxelmodpack.hdskins.HDSkinManager;
import com.voxelmodpack.hdskins.ducks.INetworkPlayerInfo; import com.voxelmodpack.hdskins.ducks.INetworkPlayerInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.client.resources.SkinManager; import net.minecraft.client.resources.SkinManager;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -20,6 +18,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
@Mixin(NetworkPlayerInfo.class) @Mixin(NetworkPlayerInfo.class)
public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo { public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo {
@ -27,20 +26,15 @@ public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo {
private Map<Type, ResourceLocation> customTextures = new HashMap<>(); private Map<Type, ResourceLocation> customTextures = new HashMap<>();
private Map<Type, MinecraftProfileTexture> customProfiles = new HashMap<>(); private Map<Type, MinecraftProfileTexture> customProfiles = new HashMap<>();
private Map<Type, MinecraftProfileTexture> vanillaProfiles = new HashMap<>();
@Shadow @Final @Shadow @Final
private GameProfile gameProfile; private GameProfile gameProfile;
@Shadow @Shadow Map<Type, ResourceLocation> playerTextures;
private boolean playerTexturesLoaded;
@Shadow
private String skinType;
@Shadow
private Map<Type, ResourceLocation> playerTextures;
@SuppressWarnings("InvalidMemberReference") // mc-dev bug? @SuppressWarnings("InvalidMemberReference") // mc-dev bug?
@Redirect(method = { "getLocationSkin", "getLocationCape", "getLocationElytra" }, @Redirect(method = {"getLocationSkin", "getLocationCape", "getLocationElytra"},
at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;", remap = false)) at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;", remap = false))
// synthetic // synthetic
private Object getSkin(Map<Type, ResourceLocation> playerTextures, Object key) { private Object getSkin(Map<Type, ResourceLocation> playerTextures, Object key) {
@ -56,16 +50,25 @@ public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo {
return playerTextures.get(type); return playerTextures.get(type);
} }
@Nullable
@Redirect(method = "getSkinType", @Redirect(method = "getSkinType",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/NetworkPlayerInfo;skinType:Ljava/lang/String;")) at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/NetworkPlayerInfo;skinType:Ljava/lang/String;"))
private String getTextureModel(NetworkPlayerInfo self) { private String getTextureModel(NetworkPlayerInfo self) {
if (customProfiles.containsKey(Type.SKIN)) { String model = getModelFrom(customProfiles);
String model = customProfiles.get(Type.SKIN).getMetadata("model"); if (model != null) {
return model;
}
return getModelFrom(vanillaProfiles);
}
@Nullable
private static String getModelFrom(Map<Type, MinecraftProfileTexture> texture) {
if (texture.containsKey(Type.SKIN)) {
String model = texture.get(Type.SKIN).getMetadata("model");
return model != null ? model : "default"; return model != null ? model : "default";
} }
return null;
return skinType;
} }
@Inject(method = "loadPlayerTextures", @Inject(method = "loadPlayerTextures",
@ -91,24 +94,23 @@ public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo {
private void redirectLoadPlayerTextures(SkinManager skinManager, GameProfile profile, SkinManager.SkinAvailableCallback callback, private void redirectLoadPlayerTextures(SkinManager skinManager, GameProfile profile, SkinManager.SkinAvailableCallback callback,
boolean requireSecure) { boolean requireSecure) {
skinManager.loadProfileTextures(profile, (typeIn, location, profileTexture) -> { skinManager.loadProfileTextures(profile, (typeIn, location, profileTexture) -> {
HDSkinManager.INSTANCE.parseSkin(profile, typeIn, location, profileTexture, callback); HDSkinManager.INSTANCE.parseSkin(profile, typeIn, location, profileTexture)
.thenAccept(v -> {
playerTextures.put(typeIn, location);
vanillaProfiles.put(typeIn, profileTexture);
});
}, requireSecure); }, requireSecure);
} }
@Override @Override
public void reloadTextures() { public void reloadTextures() {
synchronized (this) { synchronized (this) {
this.playerTexturesLoaded = false; for (Map.Entry<Type, MinecraftProfileTexture> entry : customProfiles.entrySet()) {
if (this.gameProfile.getId().equals(Minecraft.getMinecraft().getSession().getProfile().getId())) { HDSkinManager.INSTANCE.parseSkin(gameProfile, entry.getKey(), customTextures.get(entry.getKey()), entry.getValue());
// local client skin doesn't have a signature. }
this.gameProfile.getProperties().removeAll("textures"); for (Map.Entry<Type, MinecraftProfileTexture> entry : vanillaProfiles.entrySet()) {
HDSkinManager.INSTANCE.parseSkin(gameProfile, entry.getKey(), playerTextures.get(entry.getKey()), entry.getValue());
} }
} }
} }
@Override
public void setSkinType(String skinType) {
this.skinType = skinType;
}
} }