diff options
Diffstat (limited to 'src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java')
-rw-r--r-- | src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java | 75 |
1 files changed, 68 insertions, 7 deletions
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; + } + } + } + }); } } |