Advertisement
Guest User

Untitled

a guest
Jan 11th, 2025
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.34 KB | Software | 0 0
  1. #Functioning class PlayerSkinUpdater:
  2. public class PlayerSkinUpdater implements Listener {
  3. private final JavaPlugin plugin;
  4. private final Map<UUID, GameProfile> fakeProfileMap = new HashMap<>();
  5. private final Map<UUID, String> originalNames = new HashMap<>();
  6. private final Map<UUID, Map<UUID, Boolean>> playerVisibilityState = new HashMap<>();
  7. private final SkinFetcher skinFetcher = new SkinFetcher();
  8. private final Map<UUID, Set<UUID>> playersTriggeredSkinUpdate = new HashMap<>();
  9.  
  10.  
  11. private static final String HARDCODED_SKIN_VALUE = "...";
  12. private static final String HARDCODED_SKIN_SIGNATURE = "...";
  13.  
  14. public PlayerSkinUpdater(JavaPlugin plugin) {
  15. this.plugin = plugin;
  16. setupPacketListeners();
  17. startProximityChecker();
  18. }
  19. private void startProximityChecker() {
  20. Bukkit.getScheduler().runTaskTimer(plugin, () -> {
  21. for (Player player : Bukkit.getOnlinePlayers()) {
  22. checkNearbyPlayers(player);
  23. }
  24. }, 10L, 10L); // Check every half second
  25. }
  26.  
  27. private void checkNearbyPlayers(Player player) {
  28. double visibleDistance = 162.0; // Distance within which players see each other's real profile
  29. double checkDistance = 140.0; // Distance within which players see each other's real profile
  30. Location playerLocation = player.getLocation();
  31.  
  32. playerVisibilityState.putIfAbsent(player.getUniqueId(), new HashMap<>());
  33. Map<UUID, Boolean> playerStates = playerVisibilityState.get(player.getUniqueId());
  34.  
  35. for (Player other : Bukkit.getOnlinePlayers()) {
  36. if (player.equals(other)) continue;
  37.  
  38. Location otherLocation = other.getLocation();
  39. boolean isInRange = playerLocation.getWorld().equals(otherLocation.getWorld()) &&
  40. playerLocation.distance(otherLocation) <= visibleDistance;
  41.  
  42. boolean checkRange = playerLocation.getWorld().equals(otherLocation.getWorld()) &&
  43. playerLocation.distance(otherLocation) <= checkDistance;
  44.  
  45. boolean currentlyVisible = playerStates.getOrDefault(other.getUniqueId(), false);
  46.  
  47. if (checkRange) {
  48. // Player is now in range, restore their original profile
  49. playerStates.put(other.getUniqueId(), true);
  50. restoreOriginalSkinAndName(other);
  51. removeFakeProfileFromTablist(other, player);
  52. } else if (isInRange && !currentlyVisible) {
  53. // Player is now in range, restore their original profile
  54. playerStates.put(other.getUniqueId(), true);
  55. restoreOriginalSkinAndName(other);
  56. removeFakeProfileFromTablist(other, player);
  57. } else if (!isInRange && currentlyVisible) {
  58. // Player is now out of range, add their fake profile back
  59. playerStates.put(other.getUniqueId(), false);
  60. updateTablistSkin(other, HARDCODED_SKIN_VALUE, HARDCODED_SKIN_SIGNATURE);
  61. addFakeProfileToTablist(other, player);
  62. }
  63. }
  64. }
  65.  
  66. private void setupPacketListeners() {
  67. ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
  68.  
  69. protocolManager.addPacketListener(new PacketAdapter(plugin,
  70. ListenerPriority.MONITOR,
  71. PacketType.Play.Server.NAMED_ENTITY_SPAWN) {
  72. @Override
  73. public void onPacketSending(PacketEvent event) {
  74. try {
  75. PacketContainer packet = event.getPacket();
  76. Player observer = event.getPlayer();
  77.  
  78. UUID spawnedPlayerUUID = packet.getUUIDs().read(0);
  79.  
  80. if (spawnedPlayerUUID != null) {
  81. Player spawnedPlayer = Bukkit.getPlayer(spawnedPlayerUUID);
  82.  
  83. if (spawnedPlayer != null && observer != null && !observer.equals(spawnedPlayer)) {
  84. Bukkit.getScheduler().runTask(plugin, () -> {
  85. handlePlayerVisibility(observer, spawnedPlayer);
  86.  
  87. playerVisibilityState.computeIfAbsent(observer.getUniqueId(), k -> new HashMap<>())
  88. .put(spawnedPlayer.getUniqueId(), true);
  89. });
  90. }
  91. }
  92. } catch (Exception e) {
  93. plugin.getLogger().warning("Error in NAMED_ENTITY_SPAWN handler: " + e.getMessage());
  94. }
  95. }
  96. });
  97. }
  98.  
  99. private void handlePlayerVisibility(Player observer, Player spawnedPlayer) {
  100. if (observer.equals(spawnedPlayer)) return;
  101.  
  102. playersTriggeredSkinUpdate.putIfAbsent(observer.getUniqueId(), new HashSet<>());
  103. Set<UUID> triggeredSkinUpdates = playersTriggeredSkinUpdate.get(observer.getUniqueId());
  104.  
  105. boolean isNearby = observer.getLocation().distance(spawnedPlayer.getLocation()) <= 16.0;
  106.  
  107. if (!triggeredSkinUpdates.contains(spawnedPlayer.getUniqueId())) {
  108. if (isNearby) {
  109. restoreOriginalSkinAndName(spawnedPlayer);
  110. } else {
  111. updateTablistSkin(spawnedPlayer, HARDCODED_SKIN_VALUE, HARDCODED_SKIN_SIGNATURE);
  112. }
  113. triggeredSkinUpdates.add(spawnedPlayer.getUniqueId());
  114.  
  115. Bukkit.getScheduler().runTaskLater(plugin, () -> triggeredSkinUpdates.remove(spawnedPlayer.getUniqueId()), 2L);
  116. }
  117. }
  118.  
  119. private void addFakeProfileToTablist(Player target, Player viewer) {
  120. GameProfile fakeProfile = fakeProfileMap.get(target.getUniqueId());
  121. if (fakeProfile == null) return;
  122.  
  123. ServerPlayer viewerServerPlayer = ((CraftPlayer) viewer).getHandle();
  124.  
  125. ClientboundPlayerInfoUpdatePacket addPacket = new ClientboundPlayerInfoUpdatePacket(
  126. EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER),
  127. List.of(new ServerPlayer(
  128. ((CraftServer) Bukkit.getServer()).getServer(),
  129. viewerServerPlayer.getLevel(),
  130. fakeProfile
  131. ))
  132. );
  133.  
  134. viewerServerPlayer.connection.send(addPacket);
  135. }
  136.  
  137. private void removeFakeProfileFromTablist(Player target, Player viewer) {
  138. GameProfile fakeProfile = fakeProfileMap.get(target.getUniqueId());
  139. if (fakeProfile == null) return;
  140.  
  141. ServerPlayer viewerServerPlayer = ((CraftPlayer) viewer).getHandle();
  142.  
  143. ClientboundPlayerInfoRemovePacket removePacket = new ClientboundPlayerInfoRemovePacket(
  144. List.of(fakeProfile.getId())
  145. );
  146.  
  147. viewerServerPlayer.connection.send(removePacket);
  148. }
  149. @EventHandler
  150. public void onPlayerTeleport(PlayerTeleportEvent event) {
  151. Player teleportedPlayer = event.getPlayer();
  152. Location destination = event.getTo();
  153.  
  154. if (destination == null) return;
  155.  
  156. Bukkit.getScheduler().runTask(plugin, () -> {
  157. for (Player other : Bukkit.getOnlinePlayers()) {
  158. if (teleportedPlayer.equals(other)) continue;
  159.  
  160. Location otherLocation = other.getLocation();
  161. double renderDistance = 8.1 * 16; // Blocks
  162. double visibleDistance = 6.0 * 16; // Blocks
  163.  
  164. boolean isInRenderDistance = destination.getWorld().equals(otherLocation.getWorld()) &&
  165. destination.distance(otherLocation) <= renderDistance;
  166. boolean isInVisibleDistance = destination.getWorld().equals(otherLocation.getWorld()) &&
  167. destination.distance(otherLocation) <= visibleDistance;
  168.  
  169. if (isInVisibleDistance) {
  170. // Trigger skin update for both players
  171. updateTablistSkin(other, HARDCODED_SKIN_VALUE, HARDCODED_SKIN_SIGNATURE);
  172. }
  173.  
  174. if (isInRenderDistance) {
  175. restoreOriginalSkinAndName(other);
  176. }
  177. }
  178. });
  179. }
  180.  
  181. private void restoreOriginalSkinAndName(Player player) {
  182. String originalName = originalNames.getOrDefault(player.getUniqueId(), player.getName());
  183. GameProfile fakeProfile = fakeProfileMap.get(player.getUniqueId());
  184.  
  185. if (fakeProfile != null) {
  186. String originalSkinValue = getOriginalSkinValue(player);
  187. String originalSkinSignature = getOriginalSkinSignature(player);
  188.  
  189. // Only update if we have valid skin data
  190. if (originalSkinValue != null && originalSkinSignature != null) {
  191. updatePlayerSkin(player, originalSkinValue, originalSkinSignature);
  192. }
  193. }
  194. }
  195.  
  196. public void updatePlayerSkin(Player player, String skinValue, String skinSignature) {
  197. Bukkit.getScheduler().runTask(plugin, () -> {
  198. try {
  199. ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
  200. GameProfile gameProfile = serverPlayer.getGameProfile();
  201.  
  202. // Update the skin texture on the game profile
  203. gameProfile.getProperties().removeAll("textures");
  204. gameProfile.getProperties().put("textures", new Property("textures", skinValue, skinSignature));
  205.  
  206. // Respawn the player to apply the skin change
  207. respawnPlayer(player);
  208. } catch (Exception e) {
  209. plugin.getLogger().severe("Error updating skin for " + player.getName() + ": " + e.getMessage());
  210. e.printStackTrace();
  211. }
  212. });
  213. }
  214.  
  215. private void respawnPlayer(Player player) {
  216. ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
  217.  
  218. // Send a player removal packet to all clients
  219. ClientboundPlayerInfoRemovePacket removePacket = new ClientboundPlayerInfoRemovePacket(
  220. List.of(serverPlayer.getGameProfile().getId())
  221. );
  222.  
  223. // Send a player spawn packet to all clients
  224. ClientboundPlayerInfoUpdatePacket addPacket = new ClientboundPlayerInfoUpdatePacket(
  225. EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER),
  226. List.of(serverPlayer)
  227. );
  228.  
  229. for (Player online : Bukkit.getOnlinePlayers()) {
  230. ServerPlayer onlinePlayer = ((CraftPlayer) online).getHandle();
  231. onlinePlayer.connection.send(removePacket);
  232. onlinePlayer.connection.send(addPacket);
  233. }
  234. }
  235.  
  236. private String getOriginalSkinValue(Player player) {
  237. SkinFetcher.SkinData skinData = skinFetcher.getOriginalSkin(player.getUniqueId());
  238. return skinData != null ? skinData.getValue() : "";
  239. }
  240.  
  241. private String getOriginalSkinSignature(Player player) {
  242. SkinFetcher.SkinData skinData = skinFetcher.getOriginalSkin(player.getUniqueId());
  243. return skinData != null ? skinData.getSignature() : "";
  244. }
  245.  
  246. public void updateTablistSkin(Player player, String skinValue, String skinSignature) {
  247. if (player == null || skinValue == null || skinSignature == null) {
  248. plugin.getLogger().warning("Invalid input parameters for skin update");
  249. return;
  250. }
  251.  
  252. Bukkit.getScheduler().runTask(plugin, () -> {
  253. try {
  254. ServerPlayer originalServerPlayer = ((CraftPlayer) player).getHandle();
  255. GameProfile originalProfile = originalServerPlayer.getGameProfile();
  256.  
  257. // Remove any existing fake profile for this player
  258. removePlayerFromTablist(player);
  259.  
  260. // Create an encrypted name for the fake profile
  261. String encryptedName = createEncryptedName(player);
  262.  
  263. // Create a new fake profile ONLY for tablist
  264. GameProfile fakeProfile = new GameProfile(originalProfile.getId(), encryptedName);
  265.  
  266. // Add the new skin texture
  267. fakeProfile.getProperties().put("textures", new Property("textures", skinValue, skinSignature));
  268.  
  269. // Store the fake profile for later removal
  270. fakeProfileMap.put(player.getUniqueId(), fakeProfile);
  271.  
  272. // Create remove packet for the original profile
  273. ClientboundPlayerInfoRemovePacket removePacket = new ClientboundPlayerInfoRemovePacket(
  274. List.of(originalProfile.getId())
  275. );
  276.  
  277. // Create add packet with the fake profile
  278. ClientboundPlayerInfoUpdatePacket addPacket = new ClientboundPlayerInfoUpdatePacket(
  279. EnumSet.of(
  280. ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER,
  281. ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED
  282. ),
  283. Collections.singletonList(
  284. new ServerPlayer(
  285. ((CraftServer) Bukkit.getServer()).getServer(),
  286. originalServerPlayer.getLevel(),
  287. fakeProfile
  288. )
  289. )
  290. );
  291.  
  292. // Send packets to all online players
  293. for (Player online : Bukkit.getOnlinePlayers()) {
  294. ServerPlayer onlineServerPlayer = ((CraftPlayer) online).getHandle();
  295.  
  296. // Ensure the packet is only sent to OTHER players
  297. if (online.getUniqueId().equals(player.getUniqueId())) {
  298. continue;
  299. }
  300.  
  301. onlineServerPlayer.connection.send(removePacket);
  302. onlineServerPlayer.connection.send(addPacket);
  303. }
  304.  
  305. plugin.getLogger().info("Attempted tablist skin update for " + player.getName());
  306. } catch (Exception e) {
  307. plugin.getLogger().severe("Error updating tablist skin for " + player.getName() + ": " + e.getMessage());
  308. e.printStackTrace();
  309. }
  310. });
  311. }
  312.  
  313. private void removePlayerFromTablist(Player player) {
  314. GameProfile fakeProfile = fakeProfileMap.remove(player.getUniqueId());
  315.  
  316. if (fakeProfile != null) {
  317. ClientboundPlayerInfoRemovePacket removePacket = new ClientboundPlayerInfoRemovePacket(
  318. List.of(fakeProfile.getId())
  319. );
  320.  
  321. // Send remove packet to all online players EXCEPT the player being removed
  322. for (Player online : Bukkit.getOnlinePlayers()) {
  323. if (online.getUniqueId().equals(player.getUniqueId())) {
  324. continue;
  325. }
  326. ServerPlayer onlineServerPlayer = ((CraftPlayer) online).getHandle();
  327. onlineServerPlayer.connection.send(removePacket);
  328. }
  329. }
  330. }
  331.  
  332. private String createEncryptedName(Player player) {
  333. if (!originalNames.containsKey(player)) {
  334. ServerPlayer originalServerPlayer = ((CraftPlayer) player).getHandle();
  335. GameProfile originalProfile = originalServerPlayer.getGameProfile();
  336. originalNames.put(originalProfile.getId(), player.getName());
  337. }
  338.  
  339. // Create an encrypted name using magic color codes
  340. return ChatColor.translateAlternateColorCodes('&', "&k" + player.getName());
  341. }
  342. }
  343.  
  344.  
  345.  
  346. #Skin fetching class SkinFetcher:
  347. public class SkinFetcher {
  348. private static final String MOJANG_API_URL = "https://sessionserver.mojang.com/session/minecraft/profile/";
  349. private final Map<UUID, SkinData> skinCache = new ConcurrentHashMap<>();
  350.  
  351. public static class SkinData {
  352. private final String value;
  353. private final String signature;
  354.  
  355. public SkinData(String value, String signature) {
  356. this.value = value;
  357. this.signature = signature;
  358. }
  359.  
  360. public String getValue() {
  361. return value;
  362. }
  363.  
  364. public String getSignature() {
  365. return signature;
  366. }
  367. }
  368.  
  369. // Fetches the original skin value for a player
  370. public SkinData getOriginalSkin(UUID playerUUID) {
  371. // Check cache first
  372. if (skinCache.containsKey(playerUUID)) {
  373. return skinCache.get(playerUUID);
  374. }
  375.  
  376. try {
  377. // Query Mojang's API
  378. HttpURLConnection connection = (HttpURLConnection) new URL(MOJANG_API_URL + playerUUID.toString().replace("-", "")).openConnection();
  379. connection.setRequestMethod("GET");
  380. connection.setConnectTimeout(5000);
  381. connection.setReadTimeout(5000);
  382.  
  383. try (InputStreamReader reader = new InputStreamReader(connection.getInputStream())) {
  384. JsonObject response = JsonParser.parseReader(reader).getAsJsonObject();
  385.  
  386. // Check if "properties" array exists and has at least one element
  387. if (!response.has("properties") || response.getAsJsonArray("properties").size() == 0) {
  388. throw new IllegalStateException("No properties found for player UUID: " + playerUUID);
  389. }
  390.  
  391. JsonObject properties = response.getAsJsonArray("properties").get(0).getAsJsonObject();
  392.  
  393. // Ensure both "value" and "signature" are present
  394. if (!properties.has("value") || !properties.has("signature")) {
  395. throw new IllegalStateException("Skin data missing for player UUID: " + playerUUID);
  396. }
  397.  
  398. String value = properties.get("value").getAsString();
  399. String signature = properties.get("signature").getAsString();
  400.  
  401. SkinData skinData = new SkinData(value, signature);
  402. skinCache.put(playerUUID, skinData); // Cache the result
  403.  
  404. return null;
  405. }
  406. } catch (Exception e) {
  407. // Log and handle error
  408. return null; // Return null if fetching fails
  409. }
  410. }
  411. }
  412.  
  413.  
  414. #Booting Main class TabListSpigot:
  415. public class TabListSpigot extends JavaPlugin implements Listener {
  416. // Hardcoded skin values - replace these with the actual skin data you want to use
  417. private static final String HARDCODED_SKIN_VALUE = "...";
  418. private static final String HARDCODED_SKIN_SIGNATURE = "...";
  419.  
  420. private PlayerSkinUpdater skinUpdater;
  421.  
  422. @Override
  423. public void onEnable() {
  424. if (getServer().getPluginManager().getPlugin("ProtocolLib") == null) {
  425. getLogger().severe("ProtocolLib not found! Disabling plugin...");
  426. getServer().getPluginManager().disablePlugin(this);
  427. return;
  428. }
  429. // Initialize the PlayerSkinUpdater
  430. skinUpdater = new PlayerSkinUpdater(this);
  431.  
  432. // Register event listener
  433. getServer().getPluginManager().registerEvents(this, this);
  434. getServer().getPluginManager().registerEvents(skinUpdater, this);
  435.  
  436. // Optional: Log that the plugin is enabled
  437. getLogger().info("TabListSpigot plugin has been enabled!");
  438. }
  439.  
  440. @Override
  441. public void onDisable() {
  442. // Optional: Log that the plugin is being disabled
  443. getLogger().info("TabListSpigot plugin is shutting down!");
  444. }
  445.  
  446. @EventHandler
  447. public void onPlayerJoin(PlayerJoinEvent event) {
  448. Player joinedPlayer = event.getPlayer();
  449.  
  450. // Log when a player joins
  451. getLogger().info("Player " + joinedPlayer.getName() + " has joined.");
  452.  
  453. // Update tablist for the joined player
  454. skinUpdater.updateTablistSkin(joinedPlayer, HARDCODED_SKIN_VALUE, HARDCODED_SKIN_SIGNATURE);
  455.  
  456. // Update tablist for ALL existing online players to see the new player
  457. updateTablistForAllPlayers(joinedPlayer);
  458. }
  459.  
  460. private void updateTablistForAllPlayers(Player newPlayer) {
  461. // Update existing online players' tablist to see the new player with encrypted name
  462. for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
  463. if (onlinePlayer.getUniqueId().equals(newPlayer.getUniqueId())) {
  464. continue; // Skip the new player
  465. }
  466.  
  467. // Update the tablist view for each existing player
  468. skinUpdater.updateTablistSkin(onlinePlayer,
  469. HARDCODED_SKIN_VALUE,
  470. HARDCODED_SKIN_SIGNATURE
  471. );
  472. }
  473. }
  474. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement