/
ProfileFetcher.java
169 lines (135 loc) · 5.42 KB
/
ProfileFetcher.java
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package net.citizensnpcs.npc.profile;
import java.util.Collection;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;
import com.google.common.base.Preconditions;
import com.mojang.authlib.Agent;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.ProfileLookupCallback;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.util.NMS;
/**
* Fetches game profiles that include skin data from Mojang servers.
*
* @see ProfileFetchThread
*/
public class ProfileFetcher {
ProfileFetcher() {
}
/**
* Fetch one or more profiles.
*
* @param requests
* The profile requests.
*/
void fetchRequests(final Collection<ProfileRequest> requests) {
Preconditions.checkNotNull(requests);
final GameProfileRepository repo = NMS.getGameProfileRepository();
String[] playerNames = new String[requests.size()];
int i = 0;
for (ProfileRequest request : requests) {
playerNames[i] = request.getPlayerName();
i++;
}
repo.findProfilesByNames(playerNames, Agent.MINECRAFT, new ProfileLookupCallback() {
@Override
public void onProfileLookupFailed(GameProfile profile, Exception e) {
if (Messaging.isDebugging()) {
Messaging.debug(
"Profile lookup for player '" + profile.getName() + "' failed: " + getExceptionMsg(e));
}
ProfileRequest request = findRequest(profile.getName(), requests);
if (request == null)
return;
if (isProfileNotFound(e)) {
request.setResult(null, ProfileFetchResult.NOT_FOUND);
} else if (isTooManyRequests(e)) {
request.setResult(null, ProfileFetchResult.TOO_MANY_REQUESTS);
} else {
request.setResult(null, ProfileFetchResult.FAILED);
}
}
@Override
public void onProfileLookupSucceeded(final GameProfile profile) {
if (Messaging.isDebugging()) {
Messaging.debug("Fetched profile " + profile.getId() + " for player " + profile.getName());
}
ProfileRequest request = findRequest(profile.getName(), requests);
if (request == null)
return;
try {
request.setResult(NMS.fillProfileProperties(profile, true), ProfileFetchResult.SUCCESS);
} catch (Exception e) {
if (Messaging.isDebugging()) {
Messaging.debug(
"Profile lookup for player '" + profile.getName() + "' failed: " + getExceptionMsg(e));
}
if (isTooManyRequests(e)) {
request.setResult(null, ProfileFetchResult.TOO_MANY_REQUESTS);
} else {
request.setResult(null, ProfileFetchResult.FAILED);
}
}
}
});
}
/**
* Fetch a profile.
*
* @param name
* The name of the player the profile belongs to.
* @param handler
* Optional handler to handle the result. Handler always invoked from the main thread.
*/
public static void fetch(String name, @Nullable ProfileFetchHandler handler) {
Preconditions.checkNotNull(name);
if (PROFILE_THREAD == null) {
initThread();
}
PROFILE_THREAD.fetch(name, handler);
}
/**
* Clear all queued and cached requests.
*/
public static void reset() {
initThread();
}
@Nullable
private static ProfileRequest findRequest(String name, Collection<ProfileRequest> requests) {
name = name.toLowerCase();
for (ProfileRequest request : requests) {
if (request.getPlayerName().equals(name))
return request;
}
return null;
}
private static String getExceptionMsg(Exception e) {
String message = e.getMessage();
String cause = e.getCause() != null ? e.getCause().getMessage() : null;
return cause != null ? cause : message;
}
private static boolean isProfileNotFound(Exception e) {
String message = e.getMessage();
String cause = e.getCause() != null ? e.getCause().getMessage() : null;
return (message != null && message.contains("did not find"))
|| (cause != null && cause.contains("did not find"));
}
private static boolean isTooManyRequests(Exception e) {
String message = e.getMessage();
String cause = e.getCause() != null ? e.getCause().getMessage() : null;
return (message != null && message.contains("too many requests"))
|| (cause != null && cause.contains("too many requests"));
}
private static void initThread() {
if (THREAD_TASK != null)
THREAD_TASK.cancel();
PROFILE_THREAD = new ProfileFetchThread();
THREAD_TASK = Bukkit.getScheduler().runTaskTimerAsynchronously(
CitizensAPI.getPlugin(), PROFILE_THREAD, 21, 20);
}
private static ProfileFetchThread PROFILE_THREAD;
private static BukkitTask THREAD_TASK;
}