diff --git a/src/main/java/net/aufdemrand/denizen/objects/dItem.java b/src/main/java/net/aufdemrand/denizen/objects/dItem.java index c17c27f65d..d9cabc5030 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/dItem.java +++ b/src/main/java/net/aufdemrand/denizen/objects/dItem.java @@ -255,6 +255,10 @@ public ItemStack getItemStack() { return item; } + public void setItemStack(ItemStack item) { + this.item = item; + } + // Compare item to item. // -1 indicates it is not a match // 0 indicates it is a perfect match diff --git a/src/main/java/net/aufdemrand/denizen/objects/dLocation.java b/src/main/java/net/aufdemrand/denizen/objects/dLocation.java index a298724f86..292a63ca8b 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/dLocation.java +++ b/src/main/java/net/aufdemrand/denizen/objects/dLocation.java @@ -1,5 +1,7 @@ package net.aufdemrand.denizen.objects; +import com.google.common.collect.Iterables; +import com.mojang.authlib.GameProfile; import net.aufdemrand.denizen.Settings; import net.aufdemrand.denizencore.objects.*; import net.aufdemrand.denizencore.objects.notable.Notable; @@ -15,12 +17,14 @@ import net.aufdemrand.denizen.utilities.Utilities; import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizen.utilities.entity.Rotation; +import net.minecraft.server.v1_8_R1.TileEntitySkull; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.*; +import org.bukkit.craftbukkit.v1_8_R1.CraftWorld; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -504,10 +508,29 @@ public String getAttribute(Attribute attribute) { // @description // Returns the skin the skull item is displaying - just the name or UUID as text, not a player object. // --> + // <--[tag] + // @attribute + // @returns Element|Element + // @mechanism dLocation.skull_skin + // @description + // Returns the skin the skull item is displaying - just the name or UUID as text, not a player object, + // along with the permanently cached texture property. + // --> if (attribute.startsWith("skull_skin")) { if (getBlock().getState() instanceof Skull) { - return new Element(((Skull) getBlock().getState()).getOwner()) - .getAttribute(attribute.fulfill(1)); + // TODO: use Bukkit Skull method when updated + GameProfile profile = ((TileEntitySkull) ((CraftWorld) getWorld()) + .getTileEntityAt(getBlockX(), getBlockY(), getBlockZ())).getGameProfile(); + String name = profile.getName(); + UUID id = profile.getId(); + com.mojang.authlib.properties.Property property = Iterables.getFirst(profile.getProperties().get("textures"), null); + attribute = attribute.fulfill(1); + if (attribute.startsWith("full")) { + return new Element((id != null ? id : name != null ? name : null) + + (property != null ? "|" + property.getValue() : "")) + .getAttribute(attribute.fulfill(1)); + } + return new Element(id != null ? id.toString() : name != null ? name : null).getAttribute(attribute); } else return "null"; } diff --git a/src/main/java/net/aufdemrand/denizen/objects/properties/item/ItemSkullskin.java b/src/main/java/net/aufdemrand/denizen/objects/properties/item/ItemSkullskin.java index 72422ae777..57be9836c0 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/properties/item/ItemSkullskin.java +++ b/src/main/java/net/aufdemrand/denizen/objects/properties/item/ItemSkullskin.java @@ -1,14 +1,25 @@ package net.aufdemrand.denizen.objects.properties.item; +import com.google.common.collect.Iterables; +import com.mojang.authlib.GameProfile; +import net.aufdemrand.denizen.objects.dItem; +import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizencore.objects.Element; import net.aufdemrand.denizencore.objects.Mechanism; -import net.aufdemrand.denizen.objects.dItem; +import net.aufdemrand.denizencore.objects.dList; import net.aufdemrand.denizencore.objects.dObject; import net.aufdemrand.denizencore.objects.properties.Property; import net.aufdemrand.denizencore.tags.Attribute; -import net.aufdemrand.denizen.utilities.debugging.dB; +import net.aufdemrand.denizencore.utilities.CoreUtilities; +import net.minecraft.server.v1_8_R1.GameProfileSerializer; +import net.minecraft.server.v1_8_R1.ItemStack; +import net.minecraft.server.v1_8_R1.MinecraftServer; +import net.minecraft.server.v1_8_R1.NBTTagCompound; +import org.bukkit.craftbukkit.v1_8_R1.inventory.CraftItemStack; import org.bukkit.inventory.meta.SkullMeta; +import java.util.UUID; + public class ItemSkullskin implements Property { public static boolean describes(dObject item) { @@ -39,14 +50,29 @@ public String getAttribute(Attribute attribute) { // @mechanism dItem.skull_skin // @group properties // @description - // Returns the name of the player whose skin a skull item uses. + // Returns the UUID of the player whose skin a skull item uses. // Note: Item must be a 'skull_item' with a skin. // --> + // <--[tag] + // @attribute + // @returns Element|Element + // @mechanism dItem.skull_skin + // @group properties + // @description + // Returns the UUID of the player whose skin a skull item uses, along + // with the permanently cached texture property. + // Note: Item must be a 'skull_item' with a skin. + // --> + if (attribute.startsWith("skin")) { - if (item.getItemStack().getDurability() == 3 - && ((SkullMeta)item.getItemStack().getItemMeta()).hasOwner()) - return new Element(((SkullMeta)item.getItemStack().getItemMeta()).getOwner()) - .getAttribute(attribute.fulfill(1)); + String skin = getPropertyString(); + if (item.getItemStack().getDurability() == 3 && skin != null) { + attribute = attribute.fulfill(1); + if (attribute.startsWith("full")) { + return new Element(skin).getAttribute(attribute.fulfill(1)); + } + return new Element(CoreUtilities.split(skin, '|').get(0)).getAttribute(attribute); + } else dB.echoError("This skull_item does not have a skin set!"); } @@ -61,8 +87,7 @@ public String getAttribute(Attribute attribute) { // (Only for human 'skull_item's) // --> if (attribute.startsWith("has_skin")) - return new Element(item.getItemStack().getDurability() == 3 - && ((SkullMeta)item.getItemStack().getItemMeta()).hasOwner()) + return new Element(item.getItemStack().getDurability() == 3 && getPropertyString() != null) .getAttribute(attribute.fulfill(1)); @@ -72,11 +97,20 @@ public String getAttribute(Attribute attribute) { @Override public String getPropertyString() { - if (item.getItemStack().getDurability() == 3 - && ((SkullMeta)item.getItemStack().getItemMeta()).hasOwner()) - return ((SkullMeta)item.getItemStack().getItemMeta()).getOwner(); - else - return null; + // TODO: use Bukkit SkullMeta method when updated + if (item.getItemStack().getDurability() == 3) { + ItemStack itemStack = CraftItemStack.asNMSCopy(item.getItemStack()); + if (itemStack.hasTag()) { + NBTTagCompound tag = itemStack.getTag(); + if (tag.hasKeyOfType("SkullOwner", 10)) { + GameProfile profile = GameProfileSerializer.deserialize(tag.getCompound("SkullOwner")); + com.mojang.authlib.properties.Property property = Iterables.getFirst(profile.getProperties().get("textures"), null); + UUID uuid = profile.getId(); + return (uuid != null ? uuid : profile.getName()) + (property != null ? "|" + property.getValue() : ""); + } + } + } + return null; } @Override @@ -90,21 +124,62 @@ public void adjust(Mechanism mechanism) { // <--[mechanism] // @object dItem // @name skull_skin - // @input Element + // @input Element(|Element) // @description // Sets the player skin on a skull_item. + // Optionally, use the second Element for the skin texture cache. + // This will require the player's UUID, not their name. // @tags // + // // // --> + // TODO: use Bukkit SkullMeta method when updated if (mechanism.matches("skull_skin")) { if (item.getItemStack().getDurability() != 3) item.getItemStack().setDurability((short)3); - SkullMeta meta = (SkullMeta) item.getItemStack().getItemMeta(); - meta.setOwner(mechanism.getValue().asString()); - item.getItemStack().setItemMeta(meta); + dList list = mechanism.getValue().asType(dList.class); + String idString = list.get(0); + ItemStack itemStack = CraftItemStack.asNMSCopy(item.getItemStack()); + GameProfile profile; + if (idString.contains("-")) { + UUID uuid = UUID.fromString(idString); + profile = new GameProfile(uuid, null); + } + else { + profile = new GameProfile(null, idString); + } + profile = fillGameProfile(profile); + if (list.size() > 1) { + profile.getProperties().put("textures", new com.mojang.authlib.properties.Property("value", list.get(1))); + } + NBTTagCompound tag = itemStack.hasTag() ? itemStack.getTag() : new NBTTagCompound(); + tag.set("SkullOwner", GameProfileSerializer.serialize(new NBTTagCompound(), profile)); + itemStack.setTag(tag); + item.setItemStack(CraftItemStack.asBukkitCopy(itemStack)); } } + + private static GameProfile fillGameProfile(GameProfile gameProfile) { + if(gameProfile != null) { + GameProfile gameProfile1 = null; + if (gameProfile.getName() != null) { + gameProfile1 = MinecraftServer.getServer().getUserCache().getProfile(gameProfile.getName()); + } else if (gameProfile.getId() != null) { + gameProfile1 = MinecraftServer.getServer().getUserCache().a(gameProfile.getId()); + } + if (gameProfile1 == null) { + return gameProfile; + } else { + com.mojang.authlib.properties.Property property = Iterables.getFirst(gameProfile1.getProperties().get("textures"), null); + if (property == null) { + gameProfile1 = MinecraftServer.getServer().aB().fillProfileProperties(gameProfile1, true); + } + return gameProfile1; + } + } + return null; + } }