Advertisement
Guest User

Untitled

a guest
Dec 19th, 2014
353
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.05 KB | None | 0 0
  1. package pl.fgstef.skin;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.net.URL;
  6. import java.net.URLConnection;
  7. import java.util.Map;
  8. import java.util.UUID;
  9. import java.util.concurrent.ConcurrentMap;
  10. import java.util.concurrent.TimeUnit;
  11.  
  12. // For ProtocolLib 3.3.1 and lower
  13. //import net.minecraft.util.com.mojang.authlib.GameProfile;
  14. //import net.minecraft.util.com.mojang.authlib.properties.Property;
  15.  
  16.  
  17.  
  18. // For ProtocolLib 3.4.0
  19. import com.comphenix.protocol.wrappers.WrappedSignedProperty;
  20.  
  21.  
  22.  
  23. import net.minecraft.util.com.mojang.authlib.GameProfile;
  24. import net.minecraft.util.com.mojang.authlib.properties.Property;
  25.  
  26. import org.bukkit.Bukkit;
  27. import org.bukkit.entity.Player;
  28. import org.bukkit.plugin.Plugin;
  29. import org.json.simple.JSONArray;
  30. import org.json.simple.JSONObject;
  31. import org.json.simple.parser.JSONParser;
  32.  
  33.  
  34.  
  35. import com.comphenix.protocol.PacketType;
  36. import com.comphenix.protocol.ProtocolLibrary;
  37. import com.comphenix.protocol.ProtocolManager;
  38. import com.comphenix.protocol.events.ListenerPriority;
  39. import com.comphenix.protocol.events.PacketAdapter;
  40. import com.comphenix.protocol.events.PacketEvent;
  41. import com.comphenix.protocol.reflect.StructureModifier;
  42. import com.comphenix.protocol.wrappers.WrappedGameProfile;
  43.  
  44. import com.google.common.base.Charsets;
  45. import com.google.common.base.Objects;
  46. import com.google.common.cache.Cache;
  47. import com.google.common.cache.CacheBuilder;
  48. import com.google.common.cache.CacheLoader;
  49. import com.google.common.collect.Maps;
  50. import com.google.common.io.CharStreams;
  51. import com.google.common.io.InputSupplier;
  52.  
  53. public class PlayerDisplayModifier {
  54. private static final String PROFILE_URL = "https://sessionserver.mojang.com/session/minecraft/profile/";
  55. private static final int WORKER_THREADS = 4;
  56.  
  57. private ProtocolManager protocolManager;
  58. private ConcurrentMap<String, String> skinNames = Maps.newConcurrentMap();
  59. private ConcurrentMap<String, String> displayNames = Maps.newConcurrentMap();
  60.  
  61. private Cache<String, String> profileCache = CacheBuilder.newBuilder().
  62. maximumSize(500).
  63. expireAfterWrite(4, TimeUnit.HOURS).
  64. build(new CacheLoader<String, String>() {
  65. public String load(String name) throws Exception {
  66. return getProfileJson(name);
  67. };
  68. });
  69.  
  70. public PlayerDisplayModifier(Plugin plugin) {
  71. protocolManager = ProtocolLibrary.getProtocolManager();
  72. protocolManager.getAsynchronousManager().registerAsyncHandler(
  73. new PacketAdapter(plugin, ListenerPriority.NORMAL,
  74. // Packet we are modifying
  75. PacketType.Play.Server.NAMED_ENTITY_SPAWN,
  76.  
  77. // Packets that must be sent AFTER the entity spawn packet
  78. PacketType.Play.Server.ENTITY_EFFECT,
  79. PacketType.Play.Server.ENTITY_EQUIPMENT,
  80. PacketType.Play.Server.ENTITY_METADATA,
  81. PacketType.Play.Server.UPDATE_ATTRIBUTES,
  82. PacketType.Play.Server.ATTACH_ENTITY,
  83. PacketType.Play.Server.BED) {
  84.  
  85. // This will be executed on an asynchronous thread
  86. @Override
  87. public void onPacketSending(PacketEvent event) {
  88. // We only care about the entity spawn packet
  89. if (event.getPacketType() != PacketType.Play.Server.NAMED_ENTITY_SPAWN) {
  90. return;
  91. }
  92.  
  93. Player toDisplay = (Player) event.getPacket().getEntityModifier(event).read(0);
  94. String skinName = skinNames.get(toDisplay.getName());
  95. String displayName = displayNames.get(toDisplay.getName());
  96.  
  97. if (skinName == null && displayName == null) {
  98. return;
  99. }
  100. StructureModifier<WrappedGameProfile> profiles = event.getPacket().getGameProfiles();
  101. WrappedGameProfile original = profiles.read(0);
  102. WrappedGameProfile result = new WrappedGameProfile(
  103. extractUUID(original.getName()),
  104. displayName != null ? displayName : original.getName()
  105. );
  106.  
  107. updateSkin(result, skinName != null ? skinName : result.getName());
  108. profiles.write(0, result);
  109. }
  110. }).start(WORKER_THREADS);
  111. }
  112.  
  113. @SuppressWarnings("deprecation")
  114. private UUID extractUUID(final String playerName) {
  115. return Bukkit.getOfflinePlayer(playerName).getUniqueId();
  116. }
  117.  
  118. // This will be cached by Guava
  119. private String getProfileJson(String name) throws IOException {
  120. final URL url = new URL(PROFILE_URL + extractUUID(name).toString().replace("-", ""));
  121. final URLConnection uc = url.openConnection();
  122.  
  123. return CharStreams.toString(new InputSupplier<InputStreamReader>() {
  124. @Override
  125. public InputStreamReader getInput() throws IOException {
  126. return new InputStreamReader(uc.getInputStream(), Charsets.UTF_8);
  127. }
  128. });
  129. }
  130.  
  131. private void updateSkin(WrappedGameProfile profile, String skinOwner) {
  132. try {
  133. JSONObject json = (JSONObject) new JSONParser().parse(profileCache.get(skinOwner));
  134. JSONArray properties = (JSONArray) json.get("properties");
  135.  
  136. for (int i = 0; i < properties.size(); i++) {
  137. JSONObject property = (JSONObject) properties.get(i);
  138. String name = (String) property.get("name");
  139. String value = (String) property.get("value");
  140. String signature = (String) property.get("signature"); // May be NULL
  141.  
  142. // Uncomment for ProtocolLib 3.4.0
  143. //profile.getProperties().put(name, new WrappedSignedProperty(name, value, signature));
  144. ((GameProfile)profile.getHandle()).getProperties().put(name, new Property(name, value, signature));
  145. }
  146. } catch (Exception e) {
  147. // ProtocolLib will throttle the number of exceptions printed to the console log
  148. throw new RuntimeException("Cannot fetch profile for " + skinOwner, e);
  149. }
  150. }
  151.  
  152. public void changeDisplay(String string, String toSkin) {
  153. changeDisplay(string, toSkin, null);
  154. }
  155.  
  156. public void changeDisplay(Player player, String toSkin, String toName) {
  157. if (updateMap(skinNames, player.getName(), toSkin) |
  158. updateMap(displayNames, player.getName(), toName)) {
  159. refreshPlayer(player);
  160. }
  161. }
  162.  
  163. public void changeDisplay(String playerName, String toSkin, String toName) {
  164. if (updateMap(skinNames, playerName, toSkin) |
  165. updateMap(displayNames, playerName, toName)) {
  166. refreshPlayer(playerName);
  167. }
  168. }
  169.  
  170. public void removeChanges(Player player) {
  171. changeDisplay(player.getName(), null, null);
  172. }
  173.  
  174. public void removeChanges(String playerName) {
  175. changeDisplay(playerName, null, null);
  176. }
  177.  
  178. /**
  179. * Update the map with the new key-value pair.
  180. * @param map - the map.
  181. * @param key - the key of the pair.
  182. * @param value - the new value, or NULL to remove the pair.
  183. * @return TRUE if the map was updated, FALSE otherwise.
  184. */
  185. private <T, U> boolean updateMap(Map<T, U> map, T key, U value) {
  186. if (value == null) {
  187. return map.remove(key) != null;
  188. } else {
  189. return !Objects.equal(value, map.put(key, value));
  190. }
  191. }
  192.  
  193. @SuppressWarnings("deprecation")
  194. private void refreshPlayer(String name) {
  195. Player player = Bukkit.getPlayer(name);
  196.  
  197. if (player != null) {
  198. refreshPlayer(player);
  199. }
  200. }
  201.  
  202. private void refreshPlayer(Player player) {
  203. // Refresh the displayed entity
  204. protocolManager.updateEntity(player, protocolManager.getEntityTrackers(player));
  205. }
  206.  
  207. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement