Spaces:
Build error
Build error
File size: 8,668 Bytes
d46f4a3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
package net.minecraft.client.resources;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.hash.Hashing;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.SignatureState;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import com.mojang.authlib.minecraft.MinecraftProfileTextures;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
import com.mojang.authlib.properties.Property;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import net.minecraft.Optionull;
import net.minecraft.Util;
import net.minecraft.client.renderer.texture.SkinTextureDownloader;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class SkinManager {
static final Logger LOGGER = LogUtils.getLogger();
private final MinecraftSessionService sessionService;
private final LoadingCache<SkinManager.CacheKey, CompletableFuture<Optional<PlayerSkin>>> skinCache;
private final SkinManager.TextureCache skinTextures;
private final SkinManager.TextureCache capeTextures;
private final SkinManager.TextureCache elytraTextures;
public SkinManager(Path p_299617_, final MinecraftSessionService p_118814_, final Executor p_299732_) {
this.sessionService = p_118814_;
this.skinTextures = new SkinManager.TextureCache(p_299617_, Type.SKIN);
this.capeTextures = new SkinManager.TextureCache(p_299617_, Type.CAPE);
this.elytraTextures = new SkinManager.TextureCache(p_299617_, Type.ELYTRA);
this.skinCache = CacheBuilder.newBuilder()
.expireAfterAccess(Duration.ofSeconds(15L))
.build(
new CacheLoader<SkinManager.CacheKey, CompletableFuture<Optional<PlayerSkin>>>() {
public CompletableFuture<Optional<PlayerSkin>> load(SkinManager.CacheKey p_298169_) {
return CompletableFuture.<MinecraftProfileTextures>supplyAsync(() -> {
Property property = p_298169_.packedTextures();
if (property == null) {
return MinecraftProfileTextures.EMPTY;
} else {
MinecraftProfileTextures minecraftprofiletextures = p_118814_.unpackTextures(property);
if (minecraftprofiletextures.signatureState() == SignatureState.INVALID) {
SkinManager.LOGGER
.warn("Profile contained invalid signature for textures property (profile id: {})", p_298169_.profileId());
}
return minecraftprofiletextures;
}
}, Util.backgroundExecutor().forName("unpackSkinTextures"))
.thenComposeAsync(p_308313_ -> SkinManager.this.registerTextures(p_298169_.profileId(), p_308313_), p_299732_)
.handle((p_374684_, p_374685_) -> {
if (p_374685_ != null) {
SkinManager.LOGGER.warn("Failed to load texture for profile {}", p_298169_.profileId, p_374685_);
}
return Optional.ofNullable(p_374684_);
});
}
}
);
}
public Supplier<PlayerSkin> lookupInsecure(GameProfile p_298295_) {
CompletableFuture<Optional<PlayerSkin>> completablefuture = this.getOrLoad(p_298295_);
PlayerSkin playerskin = DefaultPlayerSkin.get(p_298295_);
return () -> completablefuture.getNow(Optional.empty()).orElse(playerskin);
}
public PlayerSkin getInsecureSkin(GameProfile p_298019_) {
PlayerSkin playerskin = this.getOrLoad(p_298019_).getNow(Optional.empty()).orElse(null);
return playerskin != null ? playerskin : DefaultPlayerSkin.get(p_298019_);
}
public CompletableFuture<Optional<PlayerSkin>> getOrLoad(GameProfile p_298661_) {
Property property = this.sessionService.getPackedTextures(p_298661_);
return this.skinCache.getUnchecked(new SkinManager.CacheKey(p_298661_.getId(), property));
}
CompletableFuture<PlayerSkin> registerTextures(UUID p_312099_, MinecraftProfileTextures p_313047_) {
MinecraftProfileTexture minecraftprofiletexture = p_313047_.skin();
CompletableFuture<ResourceLocation> completablefuture;
PlayerSkin.Model playerskin$model;
if (minecraftprofiletexture != null) {
completablefuture = this.skinTextures.getOrLoad(minecraftprofiletexture);
playerskin$model = PlayerSkin.Model.byName(minecraftprofiletexture.getMetadata("model"));
} else {
PlayerSkin playerskin = DefaultPlayerSkin.get(p_312099_);
completablefuture = CompletableFuture.completedFuture(playerskin.texture());
playerskin$model = playerskin.model();
}
String s = Optionull.map(minecraftprofiletexture, MinecraftProfileTexture::getUrl);
MinecraftProfileTexture minecraftprofiletexture1 = p_313047_.cape();
CompletableFuture<ResourceLocation> completablefuture1 = minecraftprofiletexture1 != null
? this.capeTextures.getOrLoad(minecraftprofiletexture1)
: CompletableFuture.completedFuture(null);
MinecraftProfileTexture minecraftprofiletexture2 = p_313047_.elytra();
CompletableFuture<ResourceLocation> completablefuture2 = minecraftprofiletexture2 != null
? this.elytraTextures.getOrLoad(minecraftprofiletexture2)
: CompletableFuture.completedFuture(null);
return CompletableFuture.allOf(completablefuture, completablefuture1, completablefuture2)
.thenApply(
p_308309_ -> new PlayerSkin(
completablefuture.join(),
s,
completablefuture1.join(),
completablefuture2.join(),
playerskin$model,
p_313047_.signatureState() == SignatureState.SIGNED
)
);
}
@OnlyIn(Dist.CLIENT)
static record CacheKey(UUID profileId, @Nullable Property packedTextures) {
}
@OnlyIn(Dist.CLIENT)
static class TextureCache {
private final Path root;
private final Type type;
private final Map<String, CompletableFuture<ResourceLocation>> textures = new Object2ObjectOpenHashMap<>();
TextureCache(Path p_297921_, Type p_298775_) {
this.root = p_297921_;
this.type = p_298775_;
}
public CompletableFuture<ResourceLocation> getOrLoad(MinecraftProfileTexture p_300959_) {
String s = p_300959_.getHash();
CompletableFuture<ResourceLocation> completablefuture = this.textures.get(s);
if (completablefuture == null) {
completablefuture = this.registerTexture(p_300959_);
this.textures.put(s, completablefuture);
}
return completablefuture;
}
private CompletableFuture<ResourceLocation> registerTexture(MinecraftProfileTexture p_300607_) {
String s = Hashing.sha1().hashUnencodedChars(p_300607_.getHash()).toString();
ResourceLocation resourcelocation = this.getTextureLocation(s);
Path path = this.root.resolve(s.length() > 2 ? s.substring(0, 2) : "xx").resolve(s);
return SkinTextureDownloader.downloadAndRegisterSkin(resourcelocation, path, p_300607_.getUrl(), this.type == Type.SKIN);
}
private ResourceLocation getTextureLocation(String p_297392_) {
String s = switch (this.type) {
case SKIN -> "skins";
case CAPE -> "capes";
case ELYTRA -> "elytra";
};
return ResourceLocation.withDefaultNamespace(s + "/" + p_297392_);
}
}
} |