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) {
// 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.
Map<String, String> metadata = ProfileTextureUtil.getMetadata(texture);
boolean wasNull = metadata == null;
@ -295,11 +301,16 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
metadata = new HashMap<>();
}
for (ISkinParser parser : skinParsers) {
parser.parse(profile, type, resource, metadata);
try {
parser.parse(profile, type, resource, metadata);
} catch (Throwable t) {
logger.error("Exception thrown while parsing skin: ", t);
}
}
if (wasNull && !metadata.isEmpty()) {
ProfileTextureUtil.setMetadata(texture, metadata);
}
}
@Override

View file

@ -1,10 +1,8 @@
package com.voxelmodpack.hdskins.mixin;
import com.google.common.util.concurrent.Runnables;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.voxelmodpack.hdskins.HDSkinManager;
import com.voxelmodpack.hdskins.INetworkPlayerInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.client.resources.SkinManager;
import net.minecraft.util.ResourceLocation;
@ -30,15 +28,14 @@ public abstract class MixinNetworkPlayerInfo$1 implements SkinManager.SkinAvaila
at = @At(value = "HEAD"))
private void skinAvailable(MinecraftProfileTexture.Type typeIn, ResourceLocation location, MinecraftProfileTexture profileTexture,
CallbackInfo ci) {
CompletableFuture.runAsync(Runnables.doNothing())
.thenAcceptAsync((v) -> {
// schedule parsing next tick, texture may not be uploaded at this point
HDSkinManager.INSTANCE.parseSkin(player.getGameProfile(), typeIn, location, profileTexture);
CompletableFuture.runAsync(() -> {
// schedule parsing next tick, texture may not be uploaded at this point
HDSkinManager.INSTANCE.parseSkin(player.getGameProfile(), typeIn, location, profileTexture);
// re-set the skin-type because vanilla has already set it
String model = profileTexture.getMetadata("model");
((INetworkPlayerInfo) player).setSkinType(model != null ? model : "default");
// re-set the skin-type because vanilla has already set it
String model = profileTexture.getMetadata("model");
((INetworkPlayerInfo) player).setSkinType(model != null ? model : "default");
}, Minecraft.getMinecraft()::addScheduledTask);
});
}
}

View file

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