Awkward code is awkward

This commit is contained in:
Sollace 2018-08-08 14:53:05 +02:00
parent a815d13912
commit e808245f72
13 changed files with 183 additions and 202 deletions

View file

@ -11,14 +11,11 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
import com.mojang.util.UUIDTypeAdapter;
import com.mumfrey.liteloader.core.LiteLoader;
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
import com.voxelmodpack.hdskins.gui.GuiSkins;
@ -31,7 +28,6 @@ import com.voxelmodpack.hdskins.skins.SkinServer;
import com.voxelmodpack.hdskins.skins.ValhallaSkinServer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IImageBuffer;
import net.minecraft.client.renderer.texture.ITextureObject;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.IResourceManager;
@ -63,9 +59,6 @@ import javax.annotation.Nonnull;
public final class HDSkinManager implements IResourceManagerReloadListener {
private static final ResourceLocation LOADING = new ResourceLocation("LOADING");
private static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(UUID.class, new UUIDTypeAdapter())
.create();
private static final ExecutorService skinDownloadExecutor = Executors.newFixedThreadPool(8);
public static final ListeningExecutorService skinUploadExecutor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
@ -90,12 +83,14 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
private List<ISkinModifier> skinModifiers = Lists.newArrayList();
private SkinResourceManager resources = new SkinResourceManager();
// private ExecutorService executor = Executors.newCachedThreadPool();
private Class<? extends GuiSkins> skinsClass = null;
private HDSkinManager() {
public static PreviewTextureManager getPreviewTextureManager(GameProfile profile) {
return new PreviewTextureManager(INSTANCE.getGatewayServer().getPreviewTextures(profile));
}
private HDSkinManager() {
// register default skin server types
addSkinServerType(LegacySkinServer.class);
addSkinServerType(ValhallaSkinServer.class);
@ -133,7 +128,7 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
Property textures = Iterables.getFirst(profile1.getProperties().get("textures"), null);
if (textures != null) {
String json = new String(Base64.getDecoder().decode(textures.getValue()), StandardCharsets.UTF_8);
MinecraftTexturesPayload texturePayload = GSON.fromJson(json, MinecraftTexturesPayload.class);
MinecraftTexturesPayload texturePayload = SkinServer.gson.fromJson(json, MinecraftTexturesPayload.class);
if (texturePayload != null) {
// name is optional
String name = texturePayload.getProfileName();
@ -175,125 +170,114 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
return url + (url.indexOf('?') > -1 ? '&' : '?') + Long.toString(new Date().getTime() / 1000);
}
private void loadTexture(GameProfile profile, final Type type, final SkinAvailableCallback callback) {
if (profile.getId() != null) {
Map<Type, MinecraftProfileTexture> data = getProfileData(profile);
final MinecraftProfileTexture texture = data.get(type);
String skinDir = type.toString().toLowerCase() + "s/";
final ResourceLocation skin = new ResourceLocation("hdskins", skinDir + texture.getHash());
File file2 = new File(LiteLoader.getAssetsDirectory(), "hd/" + skinDir + texture.getHash().substring(0, 2) + "/" + texture.getHash());
final IImageBuffer imagebufferdownload = type == Type.SKIN ? new ImageBufferDownloadHD() : null;
ITextureObject texObject = new ThreadDownloadImageETag(file2, bustCache(texture.getUrl()),
DefaultPlayerSkin.getDefaultSkinLegacy(),
new IImageBuffer() {
@Nonnull
@Override
public BufferedImage parseUserSkin(@Nonnull BufferedImage image) {
BufferedImage image1 = image;
if (imagebufferdownload != null) {
image1 = imagebufferdownload.parseUserSkin(image);
}
return image1 == null ? image : image1;
}
@Override
public void skinAvailable() {
if (imagebufferdownload != null) {
imagebufferdownload.skinAvailable();
}
callback.skinAvailable(type, skin, texture);
}
});
// schedule texture loading on the main thread.
TextureLoader.loadTexture(skin, texObject);
private void loadTexture(GameProfile profile, Type type, SkinAvailableCallback callback) {
if (profile.getId() == null) {
return;
}
MinecraftProfileTexture texture = getProfileData(profile).get(type);
String skinDir = type.toString().toLowerCase() + "s/";
ResourceLocation skin = new ResourceLocation("hdskins", skinDir + texture.getHash());
File etag = new File(LiteLoader.getAssetsDirectory(), "hd/" + skinDir + texture.getHash().substring(0, 2) + "/" + texture.getHash());
IImageBuffer buffer = new ImageBufferDownloadHD() {
@Nonnull
@Override
public BufferedImage parseUserSkin(@Nonnull BufferedImage image) {
if (type != Type.SKIN) {
return image;
}
BufferedImage converted = super.parseUserSkin(image);
return converted == null ? image : converted;
}
}.withCallback(() -> callback.skinAvailable(type, skin, texture));
// schedule texture loading on the main thread.
TextureLoader.loadTexture(skin, new ThreadDownloadImageETag(etag, bustCache(texture.getUrl()), DefaultPlayerSkin.getDefaultSkinLegacy(), buffer));
}
private Map<Type, MinecraftProfileTexture> loadProfileData(GameProfile profile) {
Map<Type, MinecraftProfileTexture> textures = Maps.newEnumMap(Type.class);
for (SkinServer server : skinServers) {
Optional<MinecraftTexturesPayload> profileData = server.loadProfileData(profile);
profileData.map(MinecraftTexturesPayload::getTextures).ifPresent(it -> it.forEach(textures::putIfAbsent));
if (textures.size() == Type.values().length) {
break;
}
}
skinServers.forEach(server -> server
.loadProfileData(profile)
.map(MinecraftTexturesPayload::getTextures)
.ifPresent(a -> a.forEach(textures::putIfAbsent)));
return textures;
}
public Map<Type, MinecraftProfileTexture> getProfileData(GameProfile profile) {
boolean was = !skins.asMap().containsKey(profile);
Map<Type, MinecraftProfileTexture> textures = skins.getUnchecked(profile);
// This is the initial value. Refreshing will load it asynchronously.
if (was) {
skins.refresh(profile);
}
return textures;
}
public void addSkinServerType(Class<? extends SkinServer> type) {
Preconditions.checkArgument(!type.isInterface(), "type cannot be an interface");
Preconditions.checkArgument(!Modifier.isAbstract(type.getModifiers()), "type cannot be abstract");
ServerType st = type.getAnnotation(ServerType.class);
if (st == null) {
throw new IllegalArgumentException("class is not annotated with @ServerType");
}
this.skinServerTypes.put(st.value(), type);
Preconditions.checkArgument(st != null, "class is not annotated with @ServerType");
skinServerTypes.put(st.value(), type);
}
public Class<? extends SkinServer> getSkinServerClass(String type) {
return this.skinServerTypes.get(type);
return skinServerTypes.get(type);
}
public void addSkinServer(SkinServer skinServer) {
this.skinServers.add(skinServer);
skinServers.add(skinServer);
}
// TODO: Why is this deprecated?
@Deprecated
public SkinServer getGatewayServer() {
return this.skinServers.get(0);
return skinServers.get(0);
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public static PreviewTextureManager getPreviewTextureManager(GameProfile profile) {
return new PreviewTextureManager(INSTANCE.getGatewayServer().getPreviewTextures(profile));
}
public void addClearListener(ISkinCacheClearListener listener) {
clearListeners.add(listener);
}
public static void clearSkinCache() {
public void clearSkinCache() {
LiteLoaderLogger.info("Clearing local player skin cache");
try {
FileUtils.deleteDirectory(new File(LiteLoader.getAssetsDirectory(), "skins"));
FileUtils.deleteDirectory(new File(LiteLoader.getAssetsDirectory(), "hd"));
TextureManager textures = Minecraft.getMinecraft().getTextureManager();
INSTANCE.skinCache.values().stream()
.flatMap(m -> m.values().stream())
.forEach(textures::deleteTexture);
INSTANCE.skinCache.clear();
INSTANCE.skins.invalidateAll();
skinCache.values().stream().flatMap(m -> m.values().stream()).forEach(textures::deleteTexture);
skinCache.clear();
skins.invalidateAll();
} catch (IOException var1) {
var1.printStackTrace();
}
INSTANCE.clearListeners = INSTANCE.clearListeners.stream()
.filter(HDSkinManager::onSkinCacheCleared)
.collect(Collectors.toList());
clearListeners = clearListeners.stream().filter(this::onSkinCacheCleared).collect(Collectors.toList());
}
private static boolean onSkinCacheCleared(ISkinCacheClearListener callback) {
private boolean onSkinCacheCleared(ISkinCacheClearListener callback) {
try {
return callback.onSkinCacheCleared();
} catch (Exception e) {
@ -312,14 +296,18 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
return loc == null ? res : loc;
}
public void convertSkin(BufferedImage image) {
Graphics graphics = image.getGraphics();
convertSkin(image, graphics);
graphics.dispose();
}
public void convertSkin(BufferedImage image, Graphics dest) {
for (ISkinModifier skin : skinModifiers) {
skin.convertSkin(image, dest);
}
skinModifiers.forEach(a -> a.convertSkin(image, dest));
}
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
this.resources.onResourceManagerReload(resourceManager);
resources.onResourceManagerReload(resourceManager);
}
}

View file

@ -3,6 +3,7 @@ package com.voxelmodpack.hdskins;
import net.minecraft.client.renderer.IImageBuffer;
import javax.annotation.Nullable;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
@ -12,6 +13,13 @@ public class ImageBufferDownloadHD implements IImageBuffer {
private Graphics graphics;
private BufferedImage image;
private Runnable callback;
public ImageBufferDownloadHD withCallback(Runnable callback) {
this.callback = callback;
return this;
}
@Override
@Nullable
@SuppressWarnings({"SuspiciousNameCombination", "NullableProblems"})
@ -19,6 +27,7 @@ public class ImageBufferDownloadHD implements IImageBuffer {
if (downloadedImage == null) {
return null;
}
int imageWidth = downloadedImage.getWidth();
int imageHeight = downloadedImage.getHeight();
if (imageHeight == imageWidth) {
@ -61,5 +70,8 @@ public class ImageBufferDownloadHD implements IImageBuffer {
@Override
public void skinAvailable() {
if (callback != null) {
callback.run();
}
}
}

View file

@ -55,7 +55,7 @@ public class LiteModHDSkins implements InitCompleteListener, ViewportListener, C
@Override
public void upgradeSettings(String version, File configPath, File oldConfigPath) {
HDSkinManager.clearSkinCache();
HDSkinManager.INSTANCE.clearSkinCache();
}
@Override

View file

@ -6,26 +6,31 @@ import net.minecraft.util.ResourceLocation;
import javax.annotation.Nullable;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
public class PreviewTexture extends ThreadDownloadImageData {
private boolean uploaded;
private String model;
public PreviewTexture(@Nullable String model, String url, ResourceLocation fallbackTexture, @Nullable IImageBuffer imageBuffer) {
super(null, url, fallbackTexture, imageBuffer);
public PreviewTexture(MinecraftProfileTexture texture, ResourceLocation fallbackTexture, @Nullable IImageBuffer imageBuffer) {
super(null, texture.getUrl(), fallbackTexture, imageBuffer);
this.model = model == null ? "default" : model;
model = texture.getMetadata("model");
if (model == null) {
model = "default";
}
}
public boolean isTextureUploaded() {
return uploaded && this.getGlTextureId() > -1;
return uploaded && getGlTextureId() > -1;
}
@Override
public void deleteGlTexture() {
super.deleteGlTexture();
this.uploaded = true;
uploaded = true;
}
public boolean hasModel() {
@ -35,4 +40,8 @@ public class PreviewTexture extends ThreadDownloadImageData {
public boolean usesThinArms() {
return "thin".equals(model);
}
public String getModel() {
return model;
}
}

View file

@ -2,12 +2,13 @@ package com.voxelmodpack.hdskins;
import com.google.common.collect.Maps;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IImageBuffer;
import net.minecraft.client.resources.SkinManager;
import net.minecraft.client.resources.SkinManager.SkinAvailableCallback;
import net.minecraft.util.ResourceLocation;
import java.awt.image.BufferedImage;
import java.util.Map;
import javax.annotation.Nullable;
@ -18,35 +19,28 @@ import javax.annotation.Nullable;
*/
public class PreviewTextureManager {
private final Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures;
private final Map<Type, MinecraftProfileTexture> textures;
PreviewTextureManager(Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures) {
PreviewTextureManager(Map<Type, MinecraftProfileTexture> textures) {
this.textures = textures;
}
@Nullable
public PreviewTexture getPreviewTexture(ResourceLocation location, MinecraftProfileTexture.Type type, ResourceLocation def,
@Nullable SkinManager.SkinAvailableCallback callback) {
public PreviewTexture getPreviewTexture(ResourceLocation location, Type type, ResourceLocation def, @Nullable SkinAvailableCallback callback) {
if (!textures.containsKey(type)) {
return null;
}
MinecraftProfileTexture texture = textures.get(type);
IImageBuffer buffer = new ImageBufferDownloadHD();
PreviewTexture skinTexture = new PreviewTexture(texture.getMetadata("model"), texture.getUrl(), def,
type == MinecraftProfileTexture.Type.SKIN ? new IImageBuffer() {
@Override
@Nullable
public BufferedImage parseUserSkin(BufferedImage image) {
return buffer.parseUserSkin(image);
}
@Override
public void skinAvailable() {
if (callback != null) {
callback.skinAvailable(type, location, new MinecraftProfileTexture(texture.getUrl(), Maps.newHashMap()));
}
}
} : null);
MinecraftProfileTexture texture = textures.get(type);
IImageBuffer buffer = type != Type.SKIN ? null : new ImageBufferDownloadHD().withCallback(() -> {
if (callback != null) {
callback.skinAvailable(type, location, new MinecraftProfileTexture(texture.getUrl(), Maps.newHashMap()));
}
});
PreviewTexture skinTexture = new PreviewTexture(texture, def, buffer);
Minecraft.getMinecraft().getTextureManager().loadTexture(location, skinTexture);
return skinTexture;

View file

@ -12,9 +12,9 @@ import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
import com.voxelmodpack.hdskins.HDSkinManager;
import com.voxelmodpack.hdskins.skins.SkinServer;
import com.voxelmodpack.hdskins.skins.SkinUploadResponse;
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiButton;
@ -93,20 +93,23 @@ public class GuiSkins extends GuiScreen {
private boolean thinArmType = false;
public GuiSkins() {
instance = this;
Minecraft minecraft = Minecraft.getMinecraft();
GameProfile profile = minecraft.getSession().getProfile();
localPlayer = getModel(profile);
remotePlayer = getModel(profile);
RenderManager rm = Minecraft.getMinecraft().getRenderManager();
RenderManager rm = minecraft.getRenderManager();
rm.renderEngine = minecraft.getTextureManager();
rm.options = minecraft.gameSettings;
rm.renderViewEntity = localPlayer;
reloadRemoteSkin();
fetchingSkin = true;
instance = this;
reloadRemoteSkin();
fetchingSkin = true;
panorama = new CubeMap(this);
initPanorama();
@ -126,6 +129,7 @@ public class GuiSkins extends GuiScreen {
if (!(Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT))) {
updateCounter++;
}
panorama.update();
localPlayer.updateModel();
@ -186,7 +190,9 @@ public class GuiSkins extends GuiScreen {
@Override
public void initGui() {
enableDnd();
GLWindow.current().setDropTargetListener((FileDropListener) files -> {
files.stream().findFirst().ifPresent(instance::loadLocalFile);
});
panorama.init();
@ -215,18 +221,12 @@ public class GuiSkins extends GuiScreen {
}
private void enableDnd() {
GLWindow.current().setDropTargetListener((FileDropListener) files -> {
files.stream().findFirst().ifPresent(instance::loadLocalFile);
});
}
@Override
public void onGuiClosed() {
super.onGuiClosed();
localPlayer.releaseTextures();
remotePlayer.releaseTextures();
HDSkinManager.clearSkinCache();
HDSkinManager.INSTANCE.clearSkinCache();
GLWindow.current().clearDropTargetListener();
}
@ -438,8 +438,7 @@ public class GuiSkins extends GuiScreen {
drawHoveringText(I18n.format(text), mouseX, y);
}
if (btnAbout.isMouseOver()) {
SkinServer gateway = HDSkinManager.INSTANCE.getGatewayServer();
drawHoveringText(Splitter.on("\r\n").splitToList(gateway.toString()), mouseX, mouseY);
drawHoveringText(Splitter.on("\r\n").splitToList(HDSkinManager.INSTANCE.getGatewayServer().toString()), mouseX, mouseY);
}
if (fetchingSkin) {

View file

@ -41,7 +41,7 @@ public class HDSkinsConfigPanel implements ConfigPanel {
Minecraft mc = Minecraft.getMinecraft();
if (button.mousePressed(mc, mouseX, mouseY)) {
HDSkinManager.clearSkinCache();
HDSkinManager.INSTANCE.clearSkinCache();
} else if (checkbox.mousePressed(mc, mouseX, mouseY)) {
checkbox.checked = !checkbox.checked;
mod.experimentalSkinDrop = checkbox.checked;

View file

@ -8,25 +8,18 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
@Mixin(ImageBufferDownload.class)
public abstract class MixinImageBufferDownload implements IImageBuffer {
@Inject(
method = "parseUserSkin(Ljava/awt/image/BufferedImage;)Ljava/awt/image/BufferedImage;",
@Inject(method = "parseUserSkin(Ljava/awt/image/BufferedImage;)Ljava/awt/image/BufferedImage;",
at = @At("RETURN"),
cancellable = true)
private void update(BufferedImage image, CallbackInfoReturnable<BufferedImage> ci) {
// convert skins from mojang server
BufferedImage image2 = ci.getReturnValue();
boolean isLegacy = image.getHeight() == 32;
if (isLegacy) {
Graphics graphics = image2.getGraphics();
HDSkinManager.INSTANCE.convertSkin(image2, graphics);
graphics.dispose();
if (image.getHeight() == 32) {
HDSkinManager.INSTANCE.convertSkin(ci.getReturnValue());
}
}
}

View file

@ -12,32 +12,27 @@ 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.Optional;
@Mixin(NetworkPlayerInfo.class)
public abstract class MixinPlayerInfo {
@Shadow
public abstract GameProfile getGameProfile();
@Inject(
method = "getLocationSkin",
@Inject(method = "getLocationSkin",
cancellable = true,
at = @At("RETURN"))
private void getLocationSkin(CallbackInfoReturnable<ResourceLocation> ci) {
getTextureLocation(ci, Type.SKIN);
}
@Inject(
method = "getLocationCape",
@Inject(method = "getLocationCape",
cancellable = true,
at = @At("RETURN"))
private void getLocationCape(CallbackInfoReturnable<ResourceLocation> ci) {
getTextureLocation(ci, Type.CAPE);
}
@Inject(
method = "getLocationElytra",
@Inject(method = "getLocationElytra",
cancellable = true,
at = @At("RETURN"))
private void getLocationElytra(CallbackInfoReturnable<ResourceLocation> ci) {
@ -45,24 +40,20 @@ public abstract class MixinPlayerInfo {
}
private void getTextureLocation(CallbackInfoReturnable<ResourceLocation> ci, Type type) {
Optional<ResourceLocation> texture = HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), type, true);
texture.ifPresent(ci::setReturnValue);
HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), type, true).ifPresent(ci::setReturnValue);
}
@Inject(
method = "getSkinType",
@Inject(method = "getSkinType",
cancellable = true,
at = @At("RETURN"))
private void getSkinType(CallbackInfoReturnable<String> ci) {
MinecraftProfileTexture skin = HDSkinManager.INSTANCE.getProfileData(getGameProfile()).get(Type.SKIN);
if (skin != null) {
String type = skin.getMetadata("model");
if (type == null)
type = "default";
String type1 = type;
Optional<ResourceLocation> texture = HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), Type.SKIN, false);
HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), Type.SKIN, false).ifPresent(res -> {
String type = skin.getMetadata("model");
texture.ifPresent((res) -> ci.setReturnValue(type1));
ci.setReturnValue(type == null ? "default" : type);
});
}
}
}

View file

@ -3,6 +3,7 @@ package com.voxelmodpack.hdskins.mixin;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
import com.voxelmodpack.hdskins.HDSkinManager;
import net.minecraft.client.renderer.tileentity.TileEntitySkullRenderer;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.tileentity.TileEntitySkull;
@ -13,27 +14,20 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import javax.annotation.Nullable;
import java.util.Optional;
@Mixin(TileEntitySkullRenderer.class)
public abstract class MixinSkullRenderer extends TileEntitySpecialRenderer<TileEntitySkull> {
@Redirect(
method = "renderSkull",
at = @At(
value = "INVOKE",
@Redirect(method = "renderSkull",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/tileentity/TileEntitySkullRenderer;bindTexture(Lnet/minecraft/util/ResourceLocation;)V",
ordinal = 4))
private void onBindTexture(TileEntitySkullRenderer tesr, ResourceLocation rl, float x, float y, float z, EnumFacing facing, float rotation, int meta,
@Nullable GameProfile profile, int p_180543_8_, float ticks) {
private void onBindTexture(TileEntitySkullRenderer tesr, ResourceLocation rl, float x, float y, float z, // ow my back
EnumFacing facing, float rotation, int meta, @Nullable GameProfile profile, int a, float ticks) {
if (profile != null) {
Optional<ResourceLocation> skin = HDSkinManager.INSTANCE.getSkinLocation(profile, Type.SKIN, true);
if (skin.isPresent())
// rebind
bindTexture(skin.get());
else
bindTexture(rl);
} else
bindTexture(HDSkinManager.INSTANCE.getSkinLocation(profile, Type.SKIN, true).orElse(rl));
} else {
bindTexture(rl);
}
}
}

View file

@ -21,7 +21,7 @@ public class ImageLoader implements Supplier<ResourceLocation> {
private final ResourceLocation original;
public ImageLoader(ResourceLocation loc) {
this.original = loc;
original = loc;
}
@Override
@ -49,7 +49,6 @@ public class ImageLoader implements Supplier<ResourceLocation> {
@Nullable
private static BufferedImage getImage(ResourceLocation res) {
try (InputStream in = mc.getResourceManager().getResource(res).getInputStream()) {
return TextureUtil.readBufferedImage(in);
} catch (IOException e) {
@ -59,9 +58,9 @@ public class ImageLoader implements Supplier<ResourceLocation> {
@Nullable
private ResourceLocation loadSkin(BufferedImage image) {
ResourceLocation conv = new ResourceLocation(original.getResourceDomain() + "-converted", original.getResourcePath());
boolean success = mc.getTextureManager().loadTexture(conv, new DynamicTextureImage(image));
return success ? conv : null;
}

View file

@ -17,6 +17,7 @@ import javax.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@ -25,6 +26,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class SkinResourceManager implements IResourceManagerReloadListener {
private final Gson GSON = new Gson();
private ExecutorService executor = Executors.newSingleThreadExecutor();
@ -41,15 +43,16 @@ public class SkinResourceManager implements IResourceManagerReloadListener {
executor = Executors.newSingleThreadExecutor();
inProgress.clear();
converted.clear();
for (String domain : resourceManager.getResourceDomains()) {
try {
for (IResource res : resourceManager.getAllResources(new ResourceLocation(domain, "textures/skins/skins.json"))) {
try {
SkinData data = getSkinData(res.getInputStream());
for (Skin s : data.skins) {
for (Skin s : getSkinData(res.getInputStream())) {
if (s.uuid != null) {
uuidSkins.put(s.uuid, s);
}
if (s.name != null) {
namedSkins.put(s.name, s);
}
@ -58,16 +61,13 @@ public class SkinResourceManager implements IResourceManagerReloadListener {
LiteLoaderLogger.warning(je, "Invalid skins.json in %s", res.getResourcePackName());
}
}
} catch (IOException e) {
// ignore
}
} catch (IOException ignored) { }
}
}
private SkinData getSkinData(InputStream stream) {
private List<Skin> getSkinData(InputStream stream) {
try {
return new Gson().fromJson(new InputStreamReader(stream), SkinData.class);
return GSON.fromJson(new InputStreamReader(stream), SkinData.class).skins;
} finally {
IOUtils.closeQuietly(stream);
}
@ -75,16 +75,14 @@ public class SkinResourceManager implements IResourceManagerReloadListener {
@Nullable
public ResourceLocation getPlayerTexture(GameProfile profile, Type type) {
if (type != Type.SKIN)
// not supported
return null;
Skin skin = getSkin(profile);
if (skin != null) {
final ResourceLocation res = skin.getTexture();
return getConvertedResource(res);
if (type == Type.SKIN) {
Skin skin = getSkin(profile);
if (skin != null) {
return getConvertedResource(skin.getTexture());
}
}
return null;
return null; // not supported
}
/**
@ -99,31 +97,35 @@ public class SkinResourceManager implements IResourceManagerReloadListener {
return converted.get(res);
}
private void loadSkinResource(@Nullable final ResourceLocation res) {
/**
* read and convert in a new thread
*/
private void loadSkinResource(@Nullable ResourceLocation res) {
if (res != null) {
// read and convert in a new thread
this.inProgress.computeIfAbsent(res, r -> CompletableFuture.supplyAsync(new ImageLoader(r), executor)
.whenComplete((loc, t) -> {
if (loc != null)
converted.put(res, loc);
else {
LogManager.getLogger().warn("Errored while processing {}. Using original.", res, t);
converted.put(res, res);
}
}));
if (!inProgress.containsKey(res)) {
inProgress.put(res, scheduleConvertion(res));
}
}
}
private Future<ResourceLocation> scheduleConvertion(ResourceLocation res) {
return CompletableFuture.supplyAsync(new ImageLoader(res), executor).whenComplete((result, error) -> {
if (result == null) {
result = res;
LogManager.getLogger().warn("Errored while processing {}. Using original.", res, error);
}
converted.put(res, result);
});
}
@Nullable
private Skin getSkin(GameProfile profile) {
Skin skin = this.uuidSkins.get(profile.getId());
if (skin == null) {
skin = this.namedSkins.get(profile.getName());
Skin skin = uuidSkins.get(profile.getId());
if (skin != null) {
return skin;
}
return skin;
}
return namedSkins.get(profile.getName());
}
}

View file

@ -25,7 +25,7 @@ import javax.annotation.Nullable;
public interface SkinServer extends Exposable {
static final Gson gson = new GsonBuilder()
Gson gson = new GsonBuilder()
.registerTypeAdapter(UUID.class, new UUIDTypeAdapter())
.create();