From 9d565ffdcd5bd54908ac3c2539db24ba25c29fd8 Mon Sep 17 00:00:00 2001 From: Morphan1 Date: Fri, 27 Feb 2015 02:18:44 -0500 Subject: [PATCH] Add dPlayer.name and dPlayer.skin mechanisms ..So yeah, you can make players have different names above their heads now... And show different skins... Oh, and even the player sees the new skin... WEEEEEEE ONCE-THOUGHT-IMPOSSIBLE THINGS! Example: /ex adjust name:Morphan1 /ex adjust skin:Morphan1 YOU ARE NOW MY CLONE! --- .../aufdemrand/denizen/objects/dPlayer.java | 40 ++++- .../utilities/PlayerProfileEditor.java | 142 ++++++++++++++++++ .../utilities/entity/CraftFakePlayer.java | 28 +--- 3 files changed, 182 insertions(+), 28 deletions(-) create mode 100644 src/main/java/net/aufdemrand/denizen/utilities/PlayerProfileEditor.java diff --git a/src/main/java/net/aufdemrand/denizen/objects/dPlayer.java b/src/main/java/net/aufdemrand/denizen/objects/dPlayer.java index a84d28f666..a2b170793e 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/dPlayer.java +++ b/src/main/java/net/aufdemrand/denizen/objects/dPlayer.java @@ -1,18 +1,19 @@ package net.aufdemrand.denizen.objects; import net.aufdemrand.denizen.flags.FlagManager; -import net.aufdemrand.denizencore.objects.*; -import net.aufdemrand.denizencore.objects.properties.Property; -import net.aufdemrand.denizencore.objects.properties.PropertyParser; import net.aufdemrand.denizen.scripts.commands.core.FailCommand; import net.aufdemrand.denizen.scripts.commands.core.FinishCommand; -import net.aufdemrand.denizencore.tags.Attribute; import net.aufdemrand.denizen.tags.core.PlayerTags; import net.aufdemrand.denizen.utilities.DenizenAPI; +import net.aufdemrand.denizen.utilities.PlayerProfileEditor; import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizen.utilities.depends.Depends; import net.aufdemrand.denizen.utilities.nbt.ImprovedOfflinePlayer; import net.aufdemrand.denizen.utilities.packets.*; +import net.aufdemrand.denizencore.objects.*; +import net.aufdemrand.denizencore.objects.properties.Property; +import net.aufdemrand.denizencore.objects.properties.PropertyParser; +import net.aufdemrand.denizencore.tags.Attribute; import net.aufdemrand.denizencore.tags.TagContext; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.npc.NPC; @@ -2326,6 +2327,37 @@ else if (split.length > 1) { ActionBar.sendActionBarMessage(getPlayerEntity(), value.asString()); } + // <--[mechanism] + // @object dPlayer + // @name name + // @input Element + // @description + // Changes the name of this player to the entire server. + // --> + if (mechanism.matches("name")) { + String name = value.asString(); + if (name.length() > 16) + dB.echoError("Must specify a name with no more than 16 characters."); + else + PlayerProfileEditor.setPlayerName(getPlayerEntity(), value.asString()); + } + + // <--[mechanism] + // @object dPlayer + // @name skin + // @input Element + // @description + // Changes the skin of the player to the skin of the given + // player name. + // --> + if (mechanism.matches("skin")) { + String name = value.asString(); + if (name.length() > 16) + dB.echoError("Must specify a name with no more than 16 characters."); + else + PlayerProfileEditor.setPlayerSkin(getPlayerEntity(), value.asString()); + } + // Iterate through this object's properties' mechanisms for (Property property : PropertyParser.getProperties(this)) { property.adjust(mechanism); diff --git a/src/main/java/net/aufdemrand/denizen/utilities/PlayerProfileEditor.java b/src/main/java/net/aufdemrand/denizen/utilities/PlayerProfileEditor.java new file mode 100644 index 0000000000..391c733308 --- /dev/null +++ b/src/main/java/net/aufdemrand/denizen/utilities/PlayerProfileEditor.java @@ -0,0 +1,142 @@ +package net.aufdemrand.denizen.utilities; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import net.aufdemrand.denizen.objects.properties.item.ItemSkullskin; +import net.aufdemrand.denizen.utilities.packets.PacketHelper; +import net.aufdemrand.denizencore.utilities.debugging.dB; +import net.minecraft.server.v1_8_R1.*; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class PlayerProfileEditor { + + private static final Map fakeProfiles = new HashMap(); + private static final Field playerGameProfile; + private static final Field gameProfileId; + private static final Field gameProfileName; + + static { + Field profileField = null; + Field profileIdField = null; + Field profileNameField = null; + try { + profileField = EntityHuman.class.getDeclaredField("bF"); + profileField.setAccessible(true); + profileIdField = GameProfile.class.getDeclaredField("id"); + profileIdField.setAccessible(true); + profileNameField = GameProfile.class.getDeclaredField("name"); + profileNameField.setAccessible(true); + } catch (Exception e) { + dB.echoError(e); + } + playerGameProfile = profileField; + gameProfileId = profileIdField; + gameProfileName = profileNameField; + } + + public static void setPlayerName(Player player, String name) { + GameProfile gameProfile = getFakeProfile(player); + setProfileName(gameProfile, name); + setPlayerProfile(player, gameProfile); + updatePlayer(player, false); + } + + public static void setPlayerSkin(Player player, String name) { + GameProfile gameProfile = getFakeProfile(player); + gameProfile.getProperties().get("textures").clear(); + GameProfile skinProfile = ItemSkullskin.fillGameProfile(new GameProfile(null, name)); + for (Property texture : skinProfile.getProperties().get("textures")) + gameProfile.getProperties().put("textures", texture); + setPlayerProfile(player, gameProfile); + updatePlayer(player, true); + } + + private static void updatePlayer(Player player, final boolean isSkinChanging) { + final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); + final UUID uuid = player.getUniqueId(); + PacketPlayOutEntityDestroy destroyPacket = new PacketPlayOutEntityDestroy(entityPlayer.getId()); + for (Player p : Bukkit.getServer().getOnlinePlayers()) { + if (!p.getUniqueId().equals(uuid)) + PacketHelper.sendPacket(p, destroyPacket); + } + new BukkitRunnable() { + @Override + public void run() { + PacketPlayOutPlayerInfo playerInfo = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, entityPlayer); + PacketPlayOutNamedEntitySpawn spawnPacket = new PacketPlayOutNamedEntitySpawn(entityPlayer); + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + PacketHelper.sendPacket(player, playerInfo); + if (!player.getUniqueId().equals(uuid)) { + PacketHelper.sendPacket(player, spawnPacket); + } + else if (isSkinChanging) { + boolean isFlying = player.isFlying(); + PacketHelper.sendPacket(player, new PacketPlayOutRespawn( + player.getWorld().getEnvironment().getId(), + entityPlayer.getWorld().getDifficulty(), + entityPlayer.getWorld().worldData.getType(), + entityPlayer.playerInteractManager.getGameMode())); + player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); + player.setFlying(isFlying); + } + } + } + }.runTaskLater(DenizenAPI.getCurrentInstance(), 5); + } + + private static GameProfile getFakeProfile(Player player) { + UUID uuid = player.getUniqueId(); + if (fakeProfiles.containsKey(uuid)) { + return fakeProfiles.get(uuid); + } + else { + GameProfile fakeProfile = new GameProfile(player.getUniqueId(), player.getName()); + for (Property texture : getPlayerProfile(player).getProperties().get("textures")) + fakeProfile.getProperties().put("textures", texture); + fakeProfiles.put(uuid, fakeProfile); + return fakeProfile; + } + } + + private static GameProfile getPlayerProfile(Player player) { + try { + return (GameProfile) playerGameProfile.get(((CraftPlayer) player).getHandle()); + } catch (Exception e) { + dB.echoError(e); + return null; + } + } + + private static void setPlayerProfile(Player player, GameProfile gameProfile) { + try { + playerGameProfile.set(((CraftPlayer) player).getHandle(), gameProfile); + } catch (Exception e) { + dB.echoError(e); + } + } + + public static void setProfileId(GameProfile gameProfile, UUID uuid) { + try { + gameProfileId.set(gameProfile, uuid); + } catch (Exception e) { + dB.echoError(e); + } + } + + public static void setProfileName(GameProfile gameProfile, String name) { + try { + gameProfileName.set(gameProfile, name); + } catch (Exception e) { + dB.echoError(e); + } + } +} diff --git a/src/main/java/net/aufdemrand/denizen/utilities/entity/CraftFakePlayer.java b/src/main/java/net/aufdemrand/denizen/utilities/entity/CraftFakePlayer.java index 9c8bb67c0b..81a0c240da 100644 --- a/src/main/java/net/aufdemrand/denizen/utilities/entity/CraftFakePlayer.java +++ b/src/main/java/net/aufdemrand/denizen/utilities/entity/CraftFakePlayer.java @@ -4,6 +4,7 @@ import com.mojang.authlib.properties.Property; import net.aufdemrand.denizen.objects.properties.item.ItemSkullskin; import net.aufdemrand.denizen.utilities.DenizenAPI; +import net.aufdemrand.denizen.utilities.PlayerProfileEditor; import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizen.utilities.packets.PacketHelper; import net.aufdemrand.denizencore.objects.Mechanism; @@ -19,27 +20,14 @@ import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class CraftFakePlayer extends CraftPlayer implements DenizenCustomEntity { - private static final Field gameProfileId; private final CraftServer server; - static { - Field field = null; - try { - field = GameProfile.class.getDeclaredField("id"); - field.setAccessible(true); - } catch (Exception e) { - dB.echoError(e); - } - gameProfileId = field; - } - public CraftFakePlayer(CraftServer server, EntityFakePlayer entity) { super(server, entity); this.server = server; @@ -58,11 +46,11 @@ else if (mechanism.matches("skin")) { skin = mechanism.getValue().asString(); } } - if (name == null || name.length() == 0 || name.length() > 16) { + if (name == null || name.length() > 16) { dB.echoError("You must specify a name with no more than 16 characters for FAKE_PLAYER names!"); return null; } - if (skin != null && (skin.isEmpty() || skin.length() > 16)) { + if (skin != null && skin.length() > 16) { dB.echoError("You must specify a name with no more than 16 characters for FAKE_PLAYER skins!"); } CraftWorld world = (CraftWorld) location.getWorld(); @@ -83,7 +71,7 @@ else if (mechanism.matches("skin")) { msb |= 0x0000000000002000L; uuid = new UUID(msb, uuid.getLeastSignificantBits()); } - setProfileId(gameProfile, uuid); + PlayerProfileEditor.setProfileId(gameProfile, uuid); final EntityFakePlayer fakePlayer = new EntityFakePlayer(worldServer.getMinecraftServer(), worldServer, gameProfile, new PlayerInteractManager(worldServer)); @@ -103,14 +91,6 @@ public void run() { return fakePlayer.getBukkitEntity(); } - private static void setProfileId(GameProfile gameProfile, UUID uuid) { - try { - gameProfileId.set(gameProfile, uuid); - } catch (Exception e) { - dB.echoError(e); - } - } - @Override public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { this.server.getEntityMetadata().setMetadata(this, metadataKey, newMetadataValue);