aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcitrons <citrons@mondecitronne.com>2023-11-03 15:52:47 -0500
committercitrons <citrons@mondecitronne.com>2023-11-03 15:52:47 -0500
commite399bb6f912bff0be064c096fed81bb7e06879ca (patch)
tree0f217a644d7c4090ff627a00c3096938341060da
parent13c2fb7482d45a74ca460f6192a16dc8c956923f (diff)
refactor to support multiple types of skin source
-rw-r--r--src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java127
-rw-r--r--src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java26
-rw-r--r--src/main/java/com/mondecitronne/homunculus/PlayerSkin.java124
-rw-r--r--src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java26
-rw-r--r--src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java10
-rw-r--r--src/main/java/com/mondecitronne/homunculus/proxy/Proxy.java2
-rw-r--r--src/main/java/com/mondecitronne/homunculus/proxy/SkinHandlerClientProxy.java42
-rw-r--r--src/main/java/com/mondecitronne/homunculus/proxy/SkinHandlerProxy.java24
-rw-r--r--src/main/java/com/mondecitronne/homunculus/skin/DefaultSkin.java24
-rw-r--r--src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java20
-rw-r--r--src/main/java/com/mondecitronne/homunculus/skin/HTTPSkin.java35
-rw-r--r--src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java82
-rw-r--r--src/main/java/com/mondecitronne/homunculus/skin/Skin.java19
13 files changed, 303 insertions, 258 deletions
diff --git a/src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java b/src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java
index 1193014..d070f08 100644
--- a/src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java
+++ b/src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java
@@ -1,10 +1,11 @@
package com.mondecitronne.homunculus;
-import javax.annotation.Nullable;
-
import com.mojang.authlib.GameProfile;
-import com.mondecitronne.homunculus.proxy.SkinHandlerProxy;
-
+import com.mondecitronne.homunculus.skin.DefaultSkin;
+import com.mondecitronne.homunculus.skin.FallbackSkin;
+import com.mondecitronne.homunculus.skin.HTTPSkin;
+import com.mondecitronne.homunculus.skin.PlayerSkin;
+import com.mondecitronne.homunculus.skin.Skin;
import io.netty.util.internal.StringUtil;
import net.minecraft.entity.EntityLiving;
import net.minecraft.nbt.NBTTagCompound;
@@ -13,54 +14,99 @@ import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.world.World;
-import net.minecraftforge.fml.common.SidedProxy;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
public class EntityHomunculus extends EntityLiving {
- @SidedProxy(clientSide = "com.mondecitronne.homunculus.proxy.SkinHandlerClientProxy", serverSide = "com.mondecitronne.homunculus.proxy.SkinHandlerProxy", modId = "homunculus")
- private static SkinHandlerProxy skinProxy;
+ private static final DataParameter<NBTTagCompound> SKIN_SOURCE = EntityDataManager.createKey(EntityHomunculus.class, DataSerializers.COMPOUND_TAG);
- private SkinHandlerProxy.SkinOwner skinOwner;
- private static final DataParameter<NBTTagCompound> SKIN_OWNER = EntityDataManager.createKey(EntityHomunculus.class, DataSerializers.COMPOUND_TAG);
+ private final Skin defaultSkin;
+ private static final Skin FALLBACK_SKIN = new FallbackSkin();
+ private Skin skin;
public EntityHomunculus(World world) {
super(world);
+ getDataManager().register(SKIN_SOURCE, new NBTTagCompound());
+ defaultSkin = new DefaultSkin(getUniqueID());
}
@Override
protected void entityInit() {
super.entityInit();
- this.getDataManager().register(SKIN_OWNER, new NBTTagCompound());
}
- private boolean isPlayerProfileUpdated(GameProfile input) {
- if (skinOwner == null) {
- return input != null;
+ private boolean isPlayerProfileUpdated(GameProfile a, GameProfile b) {
+ if (b == null) {
+ return a != null;
} else {
- GameProfile skinOwnerProfile = skinOwner.getPlayerProfile();
- return !skinOwnerProfile.getName().toLowerCase().equals(input.getName().toLowerCase()) || (input.getId() != null && !input.getId().equals(skinOwnerProfile.getId()));
+ return !a.getName().toLowerCase().equals(b.getName().toLowerCase()) || (a.getId() != null && !b.getId().equals(a.getId()));
}
}
- @Nullable
- public SkinHandlerProxy.SkinOwner getSkinOwner() {
- GameProfile ownerProfile = NBTUtil.readGameProfileFromNBT(this.getDataManager().get(SKIN_OWNER));
- if (isPlayerProfileUpdated(ownerProfile) && !StringUtil.isNullOrEmpty(ownerProfile.getName())) {
- skinOwner = skinProxy.createSkinOwner(ownerProfile);
- } else if (ownerProfile == null) {
- skinOwner = null;
+ private void dispatchFetchSkin() {
+ if (this.getEntityWorld().isRemote && skin != null) {
+ skin.dispatchFetch();
+ }
+ }
+
+ private void updateSkin() {
+ NBTTagCompound sourceNBT = getDataManager().get(SKIN_SOURCE);
+ if (sourceNBT.hasKey("Type")) {
+ switch (sourceNBT.getString("Type")) {
+ case "player":
+ GameProfile sourceProfile = NBTUtil.readGameProfileFromNBT(sourceNBT);
+ if (sourceProfile == null || StringUtil.isNullOrEmpty(sourceProfile.getName())) {
+ skin = null;
+ }
+ if (!(skin instanceof PlayerSkin) || isPlayerProfileUpdated(((PlayerSkin) skin).getPlayerProfile(), sourceProfile)) {
+ skin = new PlayerSkin(sourceProfile, getEntityWorld().isRemote);
+ dispatchFetchSkin();
+ }
+ break;
+ case "http":
+ String url = sourceNBT.getString("URL");
+ String modelType = sourceNBT.getString("Model");
+ if (!StringUtil.isNullOrEmpty(url)) {
+ if (modelType == null || !modelType.equals("default") && !modelType.equals("slim")) {
+ modelType = "default";
+ }
+ skin = new HTTPSkin(url, modelType);
+ dispatchFetchSkin();
+ } else {
+ skin = null;
+ }
+ default:
+ skin = null;
+ break;
+ }
+ } else {
+ skin = null;
+ }
+ }
+
+ public Skin getSkin() {
+ updateSkin();
+ if (skin != null) {
+ if (skin.isLoaded()) {
+ return skin;
+ } else {
+ return FALLBACK_SKIN;
+ }
+ } else {
+ return defaultSkin;
}
- return skinOwner;
}
@Override
public void readFromNBT(NBTTagCompound compound) {
super.readFromNBT(compound);
- if (compound.hasKey("SkinOwner")) {
- NBTTagCompound ownerCompound = compound.getCompoundTag("SkinOwner");
+ if (compound.hasKey("SkinSource")) {
+ NBTTagCompound sourceCompound = compound.getCompoundTag("SkinSource");
+ this.getDataManager().set(SKIN_SOURCE, sourceCompound);
+ } else if (compound.hasKey("SkinOwner")) {
+ // backwards compatibility with old NBT
+ NBTTagCompound ownerCompound = compound.getCompoundTag("SkinOwner").copy();
if (ownerCompound.hasKey("Name")) {
- this.getDataManager().set(SKIN_OWNER, ownerCompound);
+ ownerCompound.setString("Type", "player");
+ this.getDataManager().set(SKIN_SOURCE, ownerCompound);
}
}
}
@@ -68,17 +114,26 @@ public class EntityHomunculus extends EntityLiving {
@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound) {
super.writeToNBT(compound);
- SkinHandlerProxy.SkinOwner owner = getSkinOwner();
- if (owner != null) {
+ updateSkin();
+ if (skin instanceof PlayerSkin) {
NBTTagCompound profileCompound = new NBTTagCompound();
- NBTUtil.writeGameProfile(profileCompound, owner.getPlayerProfile());
- NBTTagCompound ownerCompound = new NBTTagCompound();
- ownerCompound.setTag("Name", profileCompound.getTag("Name"));
+ NBTUtil.writeGameProfile(profileCompound, ((PlayerSkin) skin).getPlayerProfile());
+ NBTTagCompound sourceCompound = new NBTTagCompound();
+ sourceCompound.setTag("Name", profileCompound.getTag("Name"));
if (profileCompound.hasKey("Id")) {
- ownerCompound.setTag("Id", profileCompound.getTag("Id"));
+ sourceCompound.setTag("Id", profileCompound.getTag("Id"));
}
- compound.setTag("SkinOwner", ownerCompound);
- }
+ sourceCompound.setString("Type", "player");
+ compound.setTag("SkinSource", sourceCompound);
+ } else if (skin instanceof HTTPSkin) {
+ NBTTagCompound sourceCompound = new NBTTagCompound();
+ sourceCompound.setString("URL", ((HTTPSkin) skin).getUrl());
+ sourceCompound.setString("Model", skin.getModelType());
+ sourceCompound.setString("Type", "http");
+ compound.setTag("SkinSource", sourceCompound);
+ } else if (compound.hasKey("SkinSource")) {
+ compound.removeTag("SkinSource");
+ }
return compound;
}
}
diff --git a/src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java b/src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java
new file mode 100644
index 0000000..8591635
--- /dev/null
+++ b/src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java
@@ -0,0 +1,26 @@
+package com.mondecitronne.homunculus;
+
+import javax.annotation.Nullable;
+import com.mojang.authlib.GameProfile;
+
+public class GameProfileFetcher {
+ @Nullable
+ private GameProfile profile;
+
+ public static void initProfileCache() {
+ }
+
+ public GameProfileFetcher(GameProfile profileIn) {
+ dispatchFetchProfile(profileIn);
+ }
+
+ @Nullable
+ public GameProfile getGameProfile() {
+ synchronized (this) {
+ return profile;
+ }
+ }
+
+ private static void dispatchFetchProfile(GameProfile profileIn) {
+ }
+}
diff --git a/src/main/java/com/mondecitronne/homunculus/PlayerSkin.java b/src/main/java/com/mondecitronne/homunculus/PlayerSkin.java
deleted file mode 100644
index 9649790..0000000
--- a/src/main/java/com/mondecitronne/homunculus/PlayerSkin.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package com.mondecitronne.homunculus;
-
-import java.io.File;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.annotation.Nullable;
-
-import com.google.common.collect.Iterables;
-import com.mojang.authlib.AuthenticationService;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.GameProfileRepository;
-import com.mojang.authlib.minecraft.MinecraftProfileTexture;
-import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
-import com.mojang.authlib.minecraft.MinecraftSessionService;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
-
-import net.minecraft.client.Minecraft;
-import net.minecraft.server.MinecraftServer;
-import net.minecraft.server.management.PlayerProfileCache;
-import net.minecraft.util.ResourceLocation;
-import net.minecraft.util.StringUtils;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
-
-@SideOnly(Side.CLIENT)
-public class PlayerSkin {
- private GameProfile playerProfile;
- private boolean skinLoaded;
- private static PlayerProfileCache profileCache;
- private static MinecraftSessionService sessionService;
-
- public static void initProfileCache() {
- AuthenticationService authenticationService = new YggdrasilAuthenticationService(Minecraft.getMinecraft().getProxy(), UUID.randomUUID().toString());
- sessionService = authenticationService.createMinecraftSessionService();
- GameProfileRepository profileRepository = authenticationService.createProfileRepository();
- profileCache = new PlayerProfileCache(profileRepository, new File(Minecraft.getMinecraft().gameDir, MinecraftServer.USER_CACHE_FILE.getName()));
- }
-
- public PlayerSkin(GameProfile profile) {
- playerProfile = profile;
- }
-
- public void loadSkin() {
- if (!skinLoaded) {
- playerProfile = populateGameProfile(playerProfile);
- skinLoaded = true;
- }
- }
-
- public GameProfile getPlayerProfile() {
- assert(playerProfile != null);
- return playerProfile;
- }
-
- protected MinecraftProfileTexture getProfileTexture() {
- Minecraft minecraft = Minecraft.getMinecraft();
- Map<Type, MinecraftProfileTexture> map = minecraft.getSkinManager().loadSkinFromCache(playerProfile);
- if (map != null) {
- return map.get(Type.SKIN);
- } else {
- return null;
- }
- }
-
- @Nullable
- public String getModelType() {
- if (getTexture() != null) {
- MinecraftProfileTexture tex = getProfileTexture();
- if (tex != null && tex.getMetadata("model") != null) {
- return tex.getMetadata("model");
- }
- }
- return null;
- }
-
- @Nullable
- public ResourceLocation getTexture() {
- MinecraftProfileTexture tex = getProfileTexture();
- if (tex != null) {
- ResourceLocation location = Minecraft.getMinecraft().getSkinManager().loadSkin(tex, Type.SKIN);
- if (location != null) {
- return location;
- }
- }
- return null;
- }
-
- private static GameProfile populateGameProfile(GameProfile input) {
- if (input != null) {
- if (input.isComplete() && input.getProperties().containsKey("textures")) {
- return input;
- } else if (profileCache != null && sessionService != null) {
- GameProfile gameProfile = null;
- if (!StringUtils.isNullOrEmpty(input.getName())) {
- gameProfile = profileCache.getGameProfileForUsername(input.getName());
- if (input.getId() != null && !input.getId().equals(gameProfile.getId())) {
- return input;
- }
- }
-
- if (gameProfile == null) {
- return input;
- } else {
- Property property = (Property)Iterables.getFirst(gameProfile.getProperties().get("textures"), (Object)null);
-
- if (property == null) {
- gameProfile = sessionService.fillProfileProperties(gameProfile, true);
- if (gameProfile == null) {
- return input;
- }
- }
-
- return gameProfile;
- }
- } else {
- return input;
- }
- } else {
- return input;
- }
- }
-}
diff --git a/src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java b/src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java
index 16ade41..5523f3d 100644
--- a/src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java
+++ b/src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java
@@ -2,25 +2,17 @@ package com.mondecitronne.homunculus.client;
import java.util.Map;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
import com.google.common.collect.Maps;
import com.mondecitronne.homunculus.EntityHomunculus;
-import com.mondecitronne.homunculus.PlayerSkin;
-import com.mondecitronne.homunculus.proxy.SkinHandlerClientProxy;
-import com.mondecitronne.homunculus.proxy.SkinHandlerProxy;
-
+import com.mondecitronne.homunculus.skin.Skin;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraftforge.fml.client.registry.IRenderFactory;
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraft.client.model.ModelPlayer;
import net.minecraft.util.ResourceLocation;
-@SideOnly(Side.CLIENT)
public class RenderHomunculus extends RenderLivingBase<EntityHomunculus> {
public static final Factory FACTORY = new Factory();
private final Map<String, ModelPlayer> modelTypes = Maps.<String, ModelPlayer>newHashMap();
@@ -31,22 +23,10 @@ public class RenderHomunculus extends RenderLivingBase<EntityHomunculus> {
modelTypes.put("slim", new ModelPlayer(0.0F, true));
}
- @Nullable
- protected static PlayerSkin getSkin(EntityHomunculus entity) {
- SkinHandlerProxy.SkinOwner owner = entity.getSkinOwner();
- if (owner != null) {
- PlayerSkin skin = ((SkinHandlerClientProxy.SkinOwner) entity.getSkinOwner()).getPlayerSkin();
- skin.loadSkin();
- return skin;
- } else {
- return null;
- }
- }
-
@Nonnull
public String getModelType(EntityHomunculus entity) {
String modelType = DefaultPlayerSkin.getSkinType(entity.getUniqueID());
- PlayerSkin skin = getSkin(entity);
+ Skin skin = entity.getSkin();
if (skin != null) {
String type = skin.getModelType();
if (type != null) {
@@ -59,7 +39,7 @@ public class RenderHomunculus extends RenderLivingBase<EntityHomunculus> {
@Override
protected ResourceLocation getEntityTexture(@Nonnull EntityHomunculus entity) {
ResourceLocation texture = DefaultPlayerSkin.getDefaultSkin(entity.getUniqueID());
- PlayerSkin skin = getSkin(entity);
+ Skin skin = entity.getSkin();
if (skin != null) {
ResourceLocation tex = skin.getTexture();
if (tex != null) {
diff --git a/src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java b/src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java
index 58d86ae..8fbcbcb 100644
--- a/src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java
+++ b/src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java
@@ -1,24 +1,20 @@
package com.mondecitronne.homunculus.proxy;
import com.mondecitronne.homunculus.EntityHomunculus;
-import com.mondecitronne.homunculus.PlayerSkin;
import com.mondecitronne.homunculus.client.RenderHomunculus;
-
import net.minecraftforge.client.event.ModelRegistryEvent;
-import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
@Mod.EventBusSubscriber(Side.CLIENT)
-@SideOnly(Side.CLIENT)
public class ClientProxy extends Proxy {
@Override
public void preInit(FMLPreInitializationEvent e) {
super.preInit(e);
- PlayerSkin.initProfileCache();
+ //PlayerSkin.initProfileCache();
RenderingRegistry.registerEntityRenderingHandler(EntityHomunculus.class, RenderHomunculus.FACTORY);
}
diff --git a/src/main/java/com/mondecitronne/homunculus/proxy/Proxy.java b/src/main/java/com/mondecitronne/homunculus/proxy/Proxy.java
index d32f489..a243838 100644
--- a/src/main/java/com/mondecitronne/homunculus/proxy/Proxy.java
+++ b/src/main/java/com/mondecitronne/homunculus/proxy/Proxy.java
@@ -8,10 +8,8 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.registry.EntityRegistry;
-import net.minecraftforge.fml.relauncher.Side;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
-
import com.mondecitronne.homunculus.EntityHomunculus;
import com.mondecitronne.homunculus.Homunculus;
diff --git a/src/main/java/com/mondecitronne/homunculus/proxy/SkinHandlerClientProxy.java b/src/main/java/com/mondecitronne/homunculus/proxy/SkinHandlerClientProxy.java
deleted file mode 100644
index 8c7a122..0000000
--- a/src/main/java/com/mondecitronne/homunculus/proxy/SkinHandlerClientProxy.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.mondecitronne.homunculus.proxy;
-
-import com.mojang.authlib.GameProfile;
-import com.mondecitronne.homunculus.PlayerSkin;
-
-import net.minecraftforge.fml.relauncher.Side;
-import net.minecraftforge.fml.relauncher.SideOnly;
-
-@SideOnly(Side.CLIENT)
-public class SkinHandlerClientProxy extends SkinHandlerProxy {
- public class SkinOwner extends SkinHandlerProxy.SkinOwner {
- private PlayerSkin skin;
-
- SkinOwner(GameProfile playerProfileIn) {
- super(playerProfileIn);
- skin = new PlayerSkin(playerProfileIn);
- }
-
- @Override
- public GameProfile getPlayerProfile() {
- if (skin != null) {
- return skin.getPlayerProfile();
- } else {
- return super.getPlayerProfile();
- }
- }
-
- public PlayerSkin getPlayerSkin() {
- return skin;
- }
-
- @Override
- public void loadSkin() {
- skin.loadSkin();
- }
- }
-
- @Override
- public SkinOwner createSkinOwner(GameProfile playerProfile) {
- return new SkinOwner(playerProfile);
- }
-}
diff --git a/src/main/java/com/mondecitronne/homunculus/proxy/SkinHandlerProxy.java b/src/main/java/com/mondecitronne/homunculus/proxy/SkinHandlerProxy.java
deleted file mode 100644
index b56ba53..0000000
--- a/src/main/java/com/mondecitronne/homunculus/proxy/SkinHandlerProxy.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.mondecitronne.homunculus.proxy;
-
-import com.mojang.authlib.GameProfile;
-
-public class SkinHandlerProxy {
- public class SkinOwner {
- private GameProfile playerProfile;
-
- SkinOwner(GameProfile playerProfileIn) {
- playerProfile = playerProfileIn;
- }
-
- public GameProfile getPlayerProfile() {
- return playerProfile;
- }
-
- public void loadSkin() {
- }
- }
-
- public SkinOwner createSkinOwner(GameProfile playerProfile) {
- return new SkinOwner(playerProfile);
- }
-} \ No newline at end of file
diff --git a/src/main/java/com/mondecitronne/homunculus/skin/DefaultSkin.java b/src/main/java/com/mondecitronne/homunculus/skin/DefaultSkin.java
new file mode 100644
index 0000000..0dbab38
--- /dev/null
+++ b/src/main/java/com/mondecitronne/homunculus/skin/DefaultSkin.java
@@ -0,0 +1,24 @@
+package com.mondecitronne.homunculus.skin;
+
+import java.util.UUID;
+
+import net.minecraft.client.resources.DefaultPlayerSkin;
+import net.minecraft.util.ResourceLocation;
+
+public class DefaultSkin extends Skin {
+ private final UUID id;
+
+ public DefaultSkin(UUID id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getModelType() {
+ return DefaultPlayerSkin.getSkinType(id);
+ }
+
+ @Override
+ public ResourceLocation getTexture() {
+ return DefaultPlayerSkin.getDefaultSkin(id);
+ }
+}
diff --git a/src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java b/src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java
new file mode 100644
index 0000000..9baedf4
--- /dev/null
+++ b/src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java
@@ -0,0 +1,20 @@
+package com.mondecitronne.homunculus.skin;
+
+import com.mondecitronne.homunculus.Homunculus;
+
+import net.minecraft.util.ResourceLocation;
+
+public class FallbackSkin extends Skin {
+ static final ResourceLocation FALLBACK_TEXTURE = new ResourceLocation(Homunculus.MODID, "entities/homunculus_fallback");
+
+ @Override
+ public String getModelType() {
+ return "default";
+ }
+
+ @Override
+ public ResourceLocation getTexture() {
+ return FALLBACK_TEXTURE;
+ }
+
+}
diff --git a/src/main/java/com/mondecitronne/homunculus/skin/HTTPSkin.java b/src/main/java/com/mondecitronne/homunculus/skin/HTTPSkin.java
new file mode 100644
index 0000000..65fd895
--- /dev/null
+++ b/src/main/java/com/mondecitronne/homunculus/skin/HTTPSkin.java
@@ -0,0 +1,35 @@
+package com.mondecitronne.homunculus.skin;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.util.ResourceLocation;
+
+public class HTTPSkin extends Skin {
+ private final String url;
+ private final String modelType;
+ public HTTPSkin(String skin_url, String modelType) {
+ url = skin_url;
+ this.modelType = modelType;
+ }
+
+ @Override
+ public boolean isLoaded() {
+ return false;
+ }
+
+ @Override
+ @Nullable
+ public String getModelType() {
+ return modelType;
+ }
+
+ @Override
+ @Nullable
+ public ResourceLocation getTexture() {
+ return null;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+}
diff --git a/src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java b/src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java
new file mode 100644
index 0000000..e460c64
--- /dev/null
+++ b/src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java
@@ -0,0 +1,82 @@
+package com.mondecitronne.homunculus.skin;
+
+import java.util.Map;
+import javax.annotation.Nullable;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.minecraft.MinecraftProfileTexture;
+import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
+import com.mondecitronne.homunculus.GameProfileFetcher;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.ResourceLocation;
+
+public class PlayerSkin extends Skin {
+ private final GameProfile profile;
+ private final GameProfileFetcher profileFetcher;
+ private final boolean isRemote;
+
+ public PlayerSkin(GameProfile profile, boolean isRemote) {
+ this.profile = profile;
+ profileFetcher = new GameProfileFetcher(this.profile);
+ this.isRemote = isRemote;
+ }
+
+ @Override
+ public boolean isLoaded() {
+ if (this.isRemote) {
+ return getTexture() != null;
+ } else {
+ return profileFetcher.getGameProfile() != null;
+ }
+ }
+
+ public GameProfile getPlayerProfile() {
+ GameProfile fetchProfile = profileFetcher.getGameProfile();
+ if (fetchProfile != null) {
+ return profileFetcher.getGameProfile();
+ } else {
+ return profile;
+ }
+ }
+
+ protected MinecraftProfileTexture getProfileTexture() {
+ assert(this.isRemote);
+ GameProfile playerProfile = getPlayerProfile();
+ if (playerProfile != null) {
+ Minecraft minecraft = Minecraft.getMinecraft();
+ Map<Type, MinecraftProfileTexture> map = minecraft.getSkinManager().loadSkinFromCache(playerProfile);
+ if (map != null) {
+ return map.get(Type.SKIN);
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getModelType() {
+ assert(this.isRemote);
+ if (getTexture() != null) {
+ MinecraftProfileTexture tex = getProfileTexture();
+ if (tex != null && tex.getMetadata("model") != null) {
+ return tex.getMetadata("model");
+ }
+ }
+ return null;
+ }
+
+ @Override
+ @Nullable
+ public ResourceLocation getTexture() {
+ assert(this.isRemote);
+ MinecraftProfileTexture tex = getProfileTexture();
+ if (tex != null) {
+ ResourceLocation location = Minecraft.getMinecraft().getSkinManager().loadSkin(tex, Type.SKIN);
+ if (location != null) {
+ return location;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/mondecitronne/homunculus/skin/Skin.java b/src/main/java/com/mondecitronne/homunculus/skin/Skin.java
new file mode 100644
index 0000000..da798fa
--- /dev/null
+++ b/src/main/java/com/mondecitronne/homunculus/skin/Skin.java
@@ -0,0 +1,19 @@
+package com.mondecitronne.homunculus.skin;
+
+import javax.annotation.Nullable;
+import net.minecraft.util.ResourceLocation;
+
+public abstract class Skin {
+ public boolean isLoaded() {
+ return true;
+ }
+
+ public void dispatchFetch() {
+ }
+
+ @Nullable
+ abstract public String getModelType();
+
+ @Nullable
+ abstract public ResourceLocation getTexture();
+}