Fix race issue related to skin parsing.

This commit is contained in:
Matthew Messinger 2018-09-03 11:52:51 -04:00
parent aa8ba2b3a6
commit e6b6a61176
3 changed files with 21 additions and 16 deletions

View file

@ -288,6 +288,12 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
public void parseSkin(GameProfile profile, Type type, ResourceLocation resource, MinecraftProfileTexture texture) { public void parseSkin(GameProfile profile, Type type, ResourceLocation resource, MinecraftProfileTexture texture) {
// The texture needs to be loaded in order to be parsed.
ITextureObject ito = null;
while (ito == null) {
ito = Minecraft.getMinecraft().getTextureManager().getTexture(resource);
}
// 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);
boolean wasNull = metadata == null; boolean wasNull = metadata == null;
@ -295,11 +301,16 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
metadata = new HashMap<>(); metadata = new HashMap<>();
} }
for (ISkinParser parser : skinParsers) { for (ISkinParser parser : skinParsers) {
try {
parser.parse(profile, type, resource, metadata); parser.parse(profile, type, resource, metadata);
} catch (Throwable t) {
logger.error("Exception thrown while parsing skin: ", t);
}
} }
if (wasNull && !metadata.isEmpty()) { if (wasNull && !metadata.isEmpty()) {
ProfileTextureUtil.setMetadata(texture, metadata); ProfileTextureUtil.setMetadata(texture, metadata);
} }
} }
@Override @Override

View file

@ -1,10 +1,8 @@
package com.voxelmodpack.hdskins.mixin; package com.voxelmodpack.hdskins.mixin;
import com.google.common.util.concurrent.Runnables;
import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.voxelmodpack.hdskins.HDSkinManager; import com.voxelmodpack.hdskins.HDSkinManager;
import com.voxelmodpack.hdskins.INetworkPlayerInfo; import com.voxelmodpack.hdskins.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;
@ -30,8 +28,7 @@ public abstract class MixinNetworkPlayerInfo$1 implements SkinManager.SkinAvaila
at = @At(value = "HEAD")) at = @At(value = "HEAD"))
private void skinAvailable(MinecraftProfileTexture.Type typeIn, ResourceLocation location, MinecraftProfileTexture profileTexture, private void skinAvailable(MinecraftProfileTexture.Type typeIn, ResourceLocation location, MinecraftProfileTexture profileTexture,
CallbackInfo ci) { CallbackInfo ci) {
CompletableFuture.runAsync(Runnables.doNothing()) CompletableFuture.runAsync(() -> {
.thenAcceptAsync((v) -> {
// schedule parsing next tick, texture may not be uploaded at this point // schedule parsing next tick, texture may not be uploaded at this point
HDSkinManager.INSTANCE.parseSkin(player.getGameProfile(), typeIn, location, profileTexture); HDSkinManager.INSTANCE.parseSkin(player.getGameProfile(), typeIn, location, profileTexture);
@ -39,6 +36,6 @@ public abstract class MixinNetworkPlayerInfo$1 implements SkinManager.SkinAvaila
String model = profileTexture.getMetadata("model"); String model = profileTexture.getMetadata("model");
((INetworkPlayerInfo) player).setSkinType(model != null ? model : "default"); ((INetworkPlayerInfo) player).setSkinType(model != null ? model : "default");
}, Minecraft.getMinecraft()::addScheduledTask); });
} }
} }

View file

@ -1,6 +1,5 @@
package com.voxelmodpack.hdskins.mixin; package com.voxelmodpack.hdskins.mixin;
import com.google.common.util.concurrent.Runnables;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
@ -73,11 +72,9 @@ public abstract class MixinNetworkPlayerInfo implements INetworkPlayerInfo {
HDSkinManager.INSTANCE.loadProfileTextures(this.gameProfile) HDSkinManager.INSTANCE.loadProfileTextures(this.gameProfile)
.thenAcceptAsync(m -> m.forEach((type, profile) -> { .thenAcceptAsync(m -> m.forEach((type, profile) -> {
HDSkinManager.INSTANCE.loadTexture(type, profile, (typeIn, location, profileTexture) -> { HDSkinManager.INSTANCE.loadTexture(type, profile, (typeIn, location, profileTexture) -> {
CompletableFuture.runAsync(Runnables.doNothing()) CompletableFuture.runAsync(() -> {
// schedule parsing next tick
.thenAcceptAsync((v) -> {
HDSkinManager.INSTANCE.parseSkin(gameProfile, typeIn, location, profileTexture); HDSkinManager.INSTANCE.parseSkin(gameProfile, typeIn, location, profileTexture);
}, Minecraft.getMinecraft()::addScheduledTask); });
customTextures.put(type, location); customTextures.put(type, location);
customProfiles.put(type, profileTexture); customProfiles.put(type, profileTexture);
}); });