aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/mondecitronne/homunculus/GameProfileFetcher.java
blob: 0651d342d6511bd0dc44666ccdd37a595d059c89 (plain)
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
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 init(File dataDir) {
    	YggdrasilAuthenticationService auth = new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString());
    	sessionService = auth.createMinecraftSessionService();
    	profileRepo = auth.createProfileRepository();
    }
	
	private GameProfileFetcher(GameProfile profileIn) {
		dispatchFetchProfile(profileIn);
	}
	
	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;
		}
	}
	
	@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;
            		}
            	}
            }
        });
    }
}