aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcitrons <citrons@mondecitronne.com>2023-11-05 15:53:46 -0600
committercitrons <citrons@mondecitronne.com>2023-11-05 15:53:46 -0600
commitcee1291e98032682220bcb5b72441c64468bd614 (patch)
tree9c82690679cac177ff8ba228df481915658f3d9f
parente399bb6f912bff0be064c096fed81bb7e06879ca (diff)
reimplement skin loading, asynchronously
-rw-r--r--src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java8
-rw-r--r--src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java75
-rw-r--r--src/main/java/com/mondecitronne/homunculus/Homunculus.java25
-rw-r--r--src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java24
-rw-r--r--src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java8
-rw-r--r--src/main/java/com/mondecitronne/homunculus/proxy/ServerProxy.java15
-rw-r--r--src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java2
-rw-r--r--src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java18
-rw-r--r--src/main/resources/assets/homunculus/textures/entity/homunculus_fallback.pngbin0 -> 2700 bytes
9 files changed, 130 insertions, 45 deletions
diff --git a/src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java b/src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java
index d070f08..d74b905 100644
--- a/src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java
+++ b/src/main/java/com/mondecitronne/homunculus/EntityHomunculus.java
@@ -34,10 +34,11 @@ public class EntityHomunculus extends EntityLiving {
}
private boolean isPlayerProfileUpdated(GameProfile a, GameProfile b) {
- if (b == null) {
+ if (b == null || b.getName() == null) {
return a != null;
} else {
- return !a.getName().toLowerCase().equals(b.getName().toLowerCase()) || (a.getId() != null && !b.getId().equals(a.getId()));
+ return !a.getName().toLowerCase().equals(b.getName().toLowerCase()) ||
+ (b.getId() != null && a.getId() != null && !b.getId().equals(a.getId()));
}
}
@@ -55,6 +56,7 @@ public class EntityHomunculus extends EntityLiving {
GameProfile sourceProfile = NBTUtil.readGameProfileFromNBT(sourceNBT);
if (sourceProfile == null || StringUtil.isNullOrEmpty(sourceProfile.getName())) {
skin = null;
+ break;
}
if (!(skin instanceof PlayerSkin) || isPlayerProfileUpdated(((PlayerSkin) skin).getPlayerProfile(), sourceProfile)) {
skin = new PlayerSkin(sourceProfile, getEntityWorld().isRemote);
@@ -73,6 +75,7 @@ public class EntityHomunculus extends EntityLiving {
} else {
skin = null;
}
+ break;
default:
skin = null;
break;
@@ -121,6 +124,7 @@ public class EntityHomunculus extends EntityLiving {
NBTTagCompound sourceCompound = new NBTTagCompound();
sourceCompound.setTag("Name", profileCompound.getTag("Name"));
if (profileCompound.hasKey("Id")) {
+ // save ID so that if a player changes their name, the skin is invalidated rather than pulling the skin of whoever takes the name
sourceCompound.setTag("Id", profileCompound.getTag("Id"));
}
sourceCompound.setString("Type", "player");
diff --git a/src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java b/src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java
index 8591635..0651d34 100644
--- a/src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java
+++ b/src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java
@@ -1,26 +1,87 @@
package com.mondecitronne.homunculus;
+import java.io.File;
+import java.net.Proxy;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
+import com.google.common.collect.Maps;
+import com.mojang.authlib.Agent;
import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.GameProfileRepository;
+import com.mojang.authlib.ProfileLookupCallback;
+import com.mojang.authlib.minecraft.MinecraftSessionService;
+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
public class GameProfileFetcher {
+ private static MinecraftSessionService sessionService;
+ private static GameProfileRepository profileRepo;
+ // there could be contention if thread pool has more than one thread
+ private static final ExecutorService THREAD_POOL = new ThreadPoolExecutor(0, 1, 1L, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
+
+ private static final Map<String, GameProfileFetcher> fetchersByName = Maps.<String, GameProfileFetcher>newHashMap();
+ private static final Map<UUID, GameProfileFetcher> fetchersById = Maps.<UUID, GameProfileFetcher>newHashMap();
+
@Nullable
private GameProfile profile;
- public static void initProfileCache() {
+ public static void init(File dataDir) {
+ YggdrasilAuthenticationService auth = new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString());
+ sessionService = auth.createMinecraftSessionService();
+ profileRepo = auth.createProfileRepository();
}
- public GameProfileFetcher(GameProfile profileIn) {
+ private GameProfileFetcher(GameProfile profileIn) {
dispatchFetchProfile(profileIn);
}
- @Nullable
- public GameProfile getGameProfile() {
- synchronized (this) {
- return profile;
+ public static GameProfileFetcher fetchProfile(GameProfile profile) {
+ if (profile.getId() != null && fetchersById.containsKey(profile.getId())) {
+ // if the profile specifies an ID, ensure that the fetcher with the correct ID returns, as it will reject a profile with the wrong ID
+ return fetchersById.get(profile.getId());
+ } else if (fetchersByName.containsKey(profile.getName())) {
+ return fetchersByName.get(profile.getName());
+ } else {
+ GameProfileFetcher fetcher = new GameProfileFetcher(profile);
+ fetchersByName.put(profile.getName(), fetcher);
+ if (profile.getId() != null) {
+ fetchersById.put(profile.getId(), fetcher);
+ }
+ return fetcher;
}
}
- private static void dispatchFetchProfile(GameProfile profileIn) {
+ @Nullable
+ public synchronized GameProfile getGameProfile() {
+ return profile;
+ }
+
+ private void dispatchFetchProfile(GameProfile profileIn) {
+ THREAD_POOL.submit(new Runnable() {
+ public void run() {
+ class LocalCallback implements ProfileLookupCallback {
+ public GameProfile fetched;
+ public void onProfileLookupSucceeded(GameProfile success) {
+ fetched = success;
+ }
+ public void onProfileLookupFailed(GameProfile failed, Exception exception) {
+ fetched = null;
+ }
+ };
+ LocalCallback callback = new LocalCallback();
+ profileRepo.findProfilesByNames(new String[] {profileIn.getName()}, Agent.MINECRAFT, callback);
+
+ GameProfile fetched = sessionService.fillProfileProperties(callback.fetched, false);
+ if (profileIn.getId() == null || fetched.getId().equals(profileIn.getId())) {
+ synchronized (this) {
+ profile = fetched;
+ }
+ }
+ }
+ });
}
}
diff --git a/src/main/java/com/mondecitronne/homunculus/Homunculus.java b/src/main/java/com/mondecitronne/homunculus/Homunculus.java
index deb97b4..a354e60 100644
--- a/src/main/java/com/mondecitronne/homunculus/Homunculus.java
+++ b/src/main/java/com/mondecitronne/homunculus/Homunculus.java
@@ -1,12 +1,14 @@
package com.mondecitronne.homunculus;
+import java.io.File;
+
+import org.apache.logging.log4j.Logger;
import com.mondecitronne.homunculus.proxy.Proxy;
-import net.minecraftforge.fml.common.event.FMLInitializationEvent;
-import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
-import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.Mod;
-import org.apache.logging.log4j.Logger;
import net.minecraftforge.fml.common.SidedProxy;
+import net.minecraftforge.fml.common.event.FMLInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@Mod(modid = Homunculus.MODID, name = Homunculus.NAME, version = Homunculus.VERSION)
public class Homunculus {
@@ -14,13 +16,14 @@ public class Homunculus {
public static final String NAME = "Homunculus";
public static final String VERSION = "1.0";
- @SidedProxy(clientSide = "com.mondecitronne.homunculus.proxy.ClientProxy", serverSide = "com.mondecitronne.homunculus.proxy.Proxy")
+ @SidedProxy(clientSide = "com.mondecitronne.homunculus.proxy.ClientProxy", serverSide = "com.mondecitronne.homunculus.proxy.ServerProxy")
public static Proxy proxy;
@Mod.Instance
public static Homunculus instance;
- static Logger logger;
+ public Logger logger;
+ File dataDir;
@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
@@ -37,4 +40,14 @@ public class Homunculus {
public void postInit(FMLPostInitializationEvent event) {
proxy.postInit(event);
}
+
+ public File getDataDir() {
+ return dataDir;
+ }
+
+ public void putDataDirIn(File dir) {
+ assert(dataDir == null);
+ dataDir = new File(dir, MODID + "_data");
+ dataDir.mkdir();
+ }
}
diff --git a/src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java b/src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java
index 5523f3d..159602a 100644
--- a/src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java
+++ b/src/main/java/com/mondecitronne/homunculus/client/RenderHomunculus.java
@@ -4,11 +4,9 @@ import java.util.Map;
import javax.annotation.Nonnull;
import com.google.common.collect.Maps;
import com.mondecitronne.homunculus.EntityHomunculus;
-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.minecraft.client.model.ModelPlayer;
import net.minecraft.util.ResourceLocation;
@@ -25,33 +23,17 @@ public class RenderHomunculus extends RenderLivingBase<EntityHomunculus> {
@Nonnull
public String getModelType(EntityHomunculus entity) {
- String modelType = DefaultPlayerSkin.getSkinType(entity.getUniqueID());
- Skin skin = entity.getSkin();
- if (skin != null) {
- String type = skin.getModelType();
- if (type != null) {
- modelType = type;
- }
- }
- return modelType;
+ return "default";
}
@Override
protected ResourceLocation getEntityTexture(@Nonnull EntityHomunculus entity) {
- ResourceLocation texture = DefaultPlayerSkin.getDefaultSkin(entity.getUniqueID());
- Skin skin = entity.getSkin();
- if (skin != null) {
- ResourceLocation tex = skin.getTexture();
- if (tex != null) {
- texture = tex;
- }
- }
- return texture;
+ return entity.getSkin().getTexture();
}
@Override
public void doRender(EntityHomunculus entity, double x, double y, double z, float entityYaw, float partialTicks) {
- mainModel = modelTypes.get(getModelType(entity));
+ mainModel = modelTypes.get(entity.getSkin().getModelType());
super.doRender(entity, x, y, z, entityYaw, partialTicks);
}
diff --git a/src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java b/src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java
index 8fbcbcb..906a08f 100644
--- a/src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java
+++ b/src/main/java/com/mondecitronne/homunculus/proxy/ClientProxy.java
@@ -1,7 +1,10 @@
package com.mondecitronne.homunculus.proxy;
import com.mondecitronne.homunculus.EntityHomunculus;
+import com.mondecitronne.homunculus.GameProfileFetcher;
+import com.mondecitronne.homunculus.Homunculus;
import com.mondecitronne.homunculus.client.RenderHomunculus;
+import net.minecraft.client.Minecraft;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.Mod;
@@ -14,9 +17,10 @@ public class ClientProxy extends Proxy {
@Override
public void preInit(FMLPreInitializationEvent e) {
super.preInit(e);
- //PlayerSkin.initProfileCache();
-
RenderingRegistry.registerEntityRenderingHandler(EntityHomunculus.class, RenderHomunculus.FACTORY);
+
+ Homunculus.instance.putDataDirIn(Minecraft.getMinecraft().gameDir);
+ GameProfileFetcher.init(Homunculus.instance.getDataDir());
}
@SubscribeEvent
diff --git a/src/main/java/com/mondecitronne/homunculus/proxy/ServerProxy.java b/src/main/java/com/mondecitronne/homunculus/proxy/ServerProxy.java
new file mode 100644
index 0000000..f017f03
--- /dev/null
+++ b/src/main/java/com/mondecitronne/homunculus/proxy/ServerProxy.java
@@ -0,0 +1,15 @@
+package com.mondecitronne.homunculus.proxy;
+
+import com.mondecitronne.homunculus.GameProfileFetcher;
+import com.mondecitronne.homunculus.Homunculus;
+import net.minecraftforge.fml.common.FMLCommonHandler;
+import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
+
+public class ServerProxy extends Proxy {
+ @Override
+ public void preInit(FMLPreInitializationEvent e) {
+ super.preInit(e);
+ Homunculus.instance.putDataDirIn(FMLCommonHandler.instance().getMinecraftServerInstance().getDataDirectory());
+ GameProfileFetcher.init(Homunculus.instance.getDataDir());
+ }
+}
diff --git a/src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java b/src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java
index 9baedf4..d36b4d6 100644
--- a/src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java
+++ b/src/main/java/com/mondecitronne/homunculus/skin/FallbackSkin.java
@@ -5,7 +5,7 @@ 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");
+ static final ResourceLocation FALLBACK_TEXTURE = new ResourceLocation(Homunculus.MODID, "textures/entity/homunculus_fallback.png");
@Override
public String getModelType() {
diff --git a/src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java b/src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java
index e460c64..7964411 100644
--- a/src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java
+++ b/src/main/java/com/mondecitronne/homunculus/skin/PlayerSkin.java
@@ -13,17 +13,19 @@ public class PlayerSkin extends Skin {
private final GameProfile profile;
private final GameProfileFetcher profileFetcher;
private final boolean isRemote;
+ boolean profileTexturesLoading;
public PlayerSkin(GameProfile profile, boolean isRemote) {
this.profile = profile;
- profileFetcher = new GameProfileFetcher(this.profile);
+ profileFetcher = GameProfileFetcher.fetchProfile(profile);
this.isRemote = isRemote;
+ profileTexturesLoading = false;
}
@Override
public boolean isLoaded() {
if (this.isRemote) {
- return getTexture() != null;
+ return getTexture() != null && getModelType() != null;
} else {
return profileFetcher.getGameProfile() != null;
}
@@ -32,7 +34,7 @@ public class PlayerSkin extends Skin {
public GameProfile getPlayerProfile() {
GameProfile fetchProfile = profileFetcher.getGameProfile();
if (fetchProfile != null) {
- return profileFetcher.getGameProfile();
+ return fetchProfile;
} else {
return profile;
}
@@ -40,9 +42,13 @@ public class PlayerSkin extends Skin {
protected MinecraftProfileTexture getProfileTexture() {
assert(this.isRemote);
- GameProfile playerProfile = getPlayerProfile();
+ GameProfile playerProfile = profileFetcher.getGameProfile();
if (playerProfile != null) {
Minecraft minecraft = Minecraft.getMinecraft();
+ if (!profileTexturesLoading) {
+ minecraft.getSkinManager().loadProfileTextures(playerProfile, null, false);
+ profileTexturesLoading = true;
+ }
Map<Type, MinecraftProfileTexture> map = minecraft.getSkinManager().loadSkinFromCache(playerProfile);
if (map != null) {
return map.get(Type.SKIN);
@@ -59,8 +65,8 @@ public class PlayerSkin extends Skin {
assert(this.isRemote);
if (getTexture() != null) {
MinecraftProfileTexture tex = getProfileTexture();
- if (tex != null && tex.getMetadata("model") != null) {
- return tex.getMetadata("model");
+ if (tex != null) {
+ return tex.getMetadata("model") != null ? tex.getMetadata("model") : "default";
}
}
return null;
diff --git a/src/main/resources/assets/homunculus/textures/entity/homunculus_fallback.png b/src/main/resources/assets/homunculus/textures/entity/homunculus_fallback.png
new file mode 100644
index 0000000..0bd2fc0
--- /dev/null
+++ b/src/main/resources/assets/homunculus/textures/entity/homunculus_fallback.png
Binary files differ