Skip to content

Commit 0446a2a

Browse files
committed
Fix #4, add hat layers on heads
The way #4 was fixed ended up with me discovering that the metadata for slim skins was actually stored in a reverse-compatible way! Why have no skin backport mods ever used it...? Signed-off-by: roadhog360 <[email protected]>
1 parent 8f3516b commit 0446a2a

File tree

5 files changed

+84
-15
lines changed

5 files changed

+84
-15
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ Current Features:
1414
- Extended hat layer support
1515
- Translucent hat layer support
1616
- Fix overlap in hat layer when wearing a head
17+
- Hat layers on head blocks
1718
- New default skins alongside just Steve
1819

1920
Todo:
20-
- Hat layers on head blocks
2121
- Config
2222
- Toggle head block inventory icon render
2323
- Toggle new default skins (Either Steve/Alex or JUST Steve)

src/main/java/roadhog360/simpleskinbackport/core/Utils.java

+25-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package roadhog360.simpleskinbackport.core;
22

3+
import com.google.common.collect.Maps;
34
import com.google.gson.Gson;
45
import com.google.gson.JsonObject;
6+
import com.mojang.authlib.GameProfile;
7+
import com.mojang.authlib.properties.Property;
58
import net.minecraft.util.ResourceLocation;
69

710
import java.nio.charset.StandardCharsets;
811
import java.util.Base64;
12+
import java.util.Map;
913
import java.util.UUID;
1014

1115
public class Utils {
@@ -56,6 +60,23 @@ public static boolean getSlimFromBase64Data(String base64) {
5660
return props.getAsJsonObject("textures").getAsJsonObject("SKIN").getAsJsonObject("metadata").get("model").getAsString().equals("slim");
5761
}
5862

63+
/**
64+
* null == could not get slim state from game profile
65+
* Unused but might be needed in the future
66+
* @param profile
67+
* @return
68+
*/
69+
public static Boolean getSlimFromGameProfile(GameProfile profile) {
70+
if(profile.getProperties().containsKey("textures")) {
71+
for(Property property : profile.getProperties().get("textures")) {
72+
if(property.getName().equals("textures")) {
73+
return Utils.getSlimFromBase64Data(property.getValue());
74+
}
75+
}
76+
}
77+
return null;
78+
}
79+
5980
public static String getCallerClassName() {
6081
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
6182
String callerClassName = null;
@@ -72,9 +93,8 @@ public static String getCallerClassName() {
7293
return null;
7394
}
7495

75-
private static final ThreadLocal<Boolean> isDownloadingPlayerSkin = ThreadLocal.withInitial(() -> false);
76-
77-
public static boolean getIsDownloadingPlayerSkin() {
78-
return isDownloadingPlayerSkin.get();
79-
}
96+
/**
97+
* null == not cached
98+
*/
99+
public static final Map<String, Boolean> HASH_CACHE = Maps.newHashMap();
80100
}

src/main/java/roadhog360/simpleskinbackport/mixinplugin/SimpleSkinBackportEarlyMixins.java

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public List<String> getMixins(Set<String> loadedCoreMods) {
2626
mixins.add("MixinAbstractClientPlayer");
2727
mixins.add("MixinModelBiped");
2828
mixins.add("MixinSkinManager");
29+
mixins.add("MixinModelSkull");
2930
}
3031
return mixins;
3132
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package roadhog360.simpleskinbackport.mixins.early;
2+
3+
import net.minecraft.client.model.ModelBase;
4+
import net.minecraft.client.model.ModelRenderer;
5+
import net.minecraft.client.model.ModelSkeletonHead;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.Shadow;
8+
import org.spongepowered.asm.mixin.Unique;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
import org.spongepowered.asm.mixin.injection.Inject;
11+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12+
import roadhog360.simpleskinbackport.client.models.ModelHatLayer;
13+
14+
@Mixin(ModelSkeletonHead.class)
15+
public abstract class MixinModelSkull extends ModelBase {
16+
17+
@Shadow
18+
public ModelRenderer skeletonHead;
19+
@Unique
20+
ModelHatLayer simpleSkinBackport$bipedHeadwear;
21+
22+
@Inject(method = "<init>(IIII)V", at = @At(value = "TAIL"))
23+
private void addHeadwear(int p_i1155_1_, int p_i1155_2_, int p_i1155_3_, int p_i1155_4_, CallbackInfo ci) {
24+
simpleSkinBackport$bipedHeadwear = new ModelHatLayer(this, 32, 0);
25+
simpleSkinBackport$bipedHeadwear.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, p_i1155_1_ + 0.5F);
26+
simpleSkinBackport$bipedHeadwear.setRotationPoint(0.0F, 0.0F + p_i1155_2_, 0.0F);
27+
skeletonHead.addChild(simpleSkinBackport$bipedHeadwear);
28+
}
29+
}

src/main/java/roadhog360/simpleskinbackport/mixins/early/MixinSkinManager.java

+28-9
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,51 @@
33
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
44
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
55
import com.llamalad7.mixinextras.sugar.Local;
6-
import net.minecraft.client.entity.AbstractClientPlayer;
6+
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
77
import net.minecraft.client.renderer.ImageBufferDownload;
88
import net.minecraft.client.resources.SkinManager;
99
import net.minecraft.util.ResourceLocation;
1010
import org.spongepowered.asm.mixin.Mixin;
1111
import org.spongepowered.asm.mixin.injection.At;
12+
import org.spongepowered.asm.mixin.injection.Inject;
13+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
14+
import roadhog360.simpleskinbackport.SimpleSkinBackport;
1215
import roadhog360.simpleskinbackport.client.ImageBufferDownloadPlayerSkin;
16+
import roadhog360.simpleskinbackport.ducks.INewModelData;
17+
18+
import java.util.Objects;
1319

1420
@Mixin(value = SkinManager.class, priority = 1100)
1521
public class MixinSkinManager {
1622
@WrapOperation(method = "func_152789_a", at = @At(value = "NEW", target = "(Ljava/lang/String;)Lnet/minecraft/util/ResourceLocation;"))
17-
private ResourceLocation changeDownloadLocation(String p_i1293_1_, Operation<ResourceLocation> original, @Local SkinManager.SkinAvailableCallback p_152789_3_) {
18-
if(p_152789_3_ instanceof AbstractClientPlayer) {
19-
String[] string = p_i1293_1_.split("/");
20-
if(string.length == 2) {
21-
return original.call(string[0] + "/64/" + string[1]);
22-
}
23+
private ResourceLocation changeDownloadLocation(String p_i1293_1_, Operation<ResourceLocation> original,
24+
@Local(argsOnly = true) final MinecraftProfileTexture.Type p_152789_2_,
25+
@Local(argsOnly = true) final SkinManager.SkinAvailableCallback p_152789_3_
26+
) {
27+
if(p_152789_2_ == MinecraftProfileTexture.Type.SKIN) {
28+
return new ResourceLocation(SimpleSkinBackport.MODID, p_i1293_1_);
2329
}
2430
return original.call(p_i1293_1_);
2531
}
2632

2733
@WrapOperation(method = "func_152789_a", at = @At(value = "NEW", target = "()Lnet/minecraft/client/renderer/ImageBufferDownload;"))
28-
private ImageBufferDownload changeDownloadBufferManager(Operation<ImageBufferDownload> original, @Local SkinManager.SkinAvailableCallback p_152789_3_) {
29-
if(p_152789_3_ instanceof AbstractClientPlayer) {
34+
private ImageBufferDownload changeDownloadBufferManager(Operation<ImageBufferDownload> original,
35+
@Local(argsOnly = true) final MinecraftProfileTexture.Type p_152789_2_,
36+
@Local(argsOnly = true) SkinManager.SkinAvailableCallback p_152789_3_) {
37+
if(p_152789_2_ == MinecraftProfileTexture.Type.SKIN) {
3038
return new ImageBufferDownloadPlayerSkin();
3139
}
3240
return original.call();
3341
}
42+
43+
@Inject(method = "func_152789_a",
44+
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/SkinManager$SkinAvailableCallback;func_152121_a(Lcom/mojang/authlib/minecraft/MinecraftProfileTexture$Type;Lnet/minecraft/util/ResourceLocation;)V",
45+
shift = At.Shift.AFTER))
46+
private void injectCallbackSkinCheck(MinecraftProfileTexture p_152789_1_, MinecraftProfileTexture.Type p_152789_2_, SkinManager.SkinAvailableCallback p_152789_3_, CallbackInfoReturnable<ResourceLocation> cir) {
47+
if(p_152789_2_ == MinecraftProfileTexture.Type.SKIN && p_152789_3_ instanceof INewModelData playerData) {
48+
if(Objects.equals(p_152789_1_.getMetadata("model"), "slim")) {
49+
playerData.simpleSkinBackport$setSlim(true);
50+
}
51+
}
52+
}
3453
}

0 commit comments

Comments
 (0)