Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.modnmetl</groupId>
<artifactId>virtualrealty</artifactId>
<version>2.5.5</version>
<version>2.5.6</version>
<packaging>jar</packaging>

<description>A plot creation and management plugin for Minecraft</description>
Expand Down Expand Up @@ -184,7 +184,7 @@
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.12.0</version>
<version>2.12.1</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ public void removeMember(PlotMember plotMember) {
}

public void removeAllMembers() {
for (PlotMember member : members) {
for (PlotMember member : new LinkedList<>(members)) {
removeMember(member);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ public static PlotItem fromItemStack(ItemStack itemStack) {
public static UUID getPlotItemUuid(ItemStack itemStack) {
NBTItem nbtItem = new NBTItem(itemStack);
String string = nbtItem.getString(NBT_PREFIX + "stack_uuid");
if (string == null) return UUID.randomUUID();
if (string == null || string.isEmpty())
return UUID.randomUUID();
return UUID.fromString(string);
}

Expand Down
93 changes: 23 additions & 70 deletions src/main/java/com/modnmetl/virtualrealty/util/data/SkullUtil.java
Original file line number Diff line number Diff line change
@@ -1,91 +1,44 @@
package com.modnmetl.virtualrealty.util.data;

import com.modnmetl.virtualrealty.VirtualRealty;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import de.tr7zw.changeme.nbtapi.NBT;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;

import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

public class SkullUtil {

public static ItemStack getSkull(String url) {
ItemStack skull;
public static ItemStack getSkull(String texture, UUID uuid) {
final String textureValue = getBase64Value(texture);
ItemStack item;
if (VirtualRealty.legacyVersion) {
skull = new ItemStack(Objects.requireNonNull(Material.getMaterial("SKULL_ITEM")), 1, (short) 3);
item = new ItemStack(Material.valueOf("SKULL_ITEM"));
item.setDurability((short) 3);
} else {
skull = new ItemStack(Material.PLAYER_HEAD, 1, (short) 3);
}
if (url == null || url.isEmpty())
return skull;
SkullMeta skullMeta = (SkullMeta) skull.getItemMeta();

GameProfile profile = new GameProfile(UUID.randomUUID(), generateRandomUsername(16));
byte[] encodedData = Base64.getEncoder().encode(String.format("{textures:{SKIN:{url:\"%s\"}}}", "http://textures.minecraft.net/texture/" + url).getBytes());
profile.getProperties().put("textures", new Property("textures", new String(encodedData)));
Field profileField = null;
try {
profileField = skullMeta.getClass().getDeclaredField("profile");
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
item = new ItemStack(Material.PLAYER_HEAD);
}
profileField.setAccessible(true);
try {
profileField.set(skullMeta, profile);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
skull.setItemMeta(skullMeta);
return skull;
NBT.modify(item, nbt -> {
final ReadWriteNBT skullOwnerCompound = nbt.getOrCreateCompound("SkullOwner");
skullOwnerCompound.setUUID("Id", uuid);
skullOwnerCompound.getOrCreateCompound("Properties")
.getCompoundList("textures")
.addCompound()
.setString("Value", textureValue);
});
return item;
}


public static ItemStack getSkull(String url, UUID uuid) {
ItemStack skull;
if (VirtualRealty.legacyVersion) {
skull = new ItemStack(Objects.requireNonNull(Material.getMaterial("SKULL_ITEM")), 1, (short) 3);
} else {
skull = new ItemStack(Material.PLAYER_HEAD, 1, (short) 3);
}
if (url == null || url.isEmpty())
return skull;
SkullMeta skullMeta = (SkullMeta) skull.getItemMeta();
GameProfile profile = new GameProfile(uuid, generateRandomUsername(16));
byte[] encodedData = Base64.getEncoder().encode(String.format("{textures:{SKIN:{url:\"%s\"}}}", "http://textures.minecraft.net/texture/" + url).getBytes());
profile.getProperties().put("textures", new Property("textures", new String(encodedData)));
Field profileField = null;
try {
profileField = skullMeta.getClass().getDeclaredField("profile");
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
profileField.setAccessible(true);
try {
profileField.set(skullMeta, profile);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
skull.setItemMeta(skullMeta);
return skull;
public static ItemStack getSkull(String url) {
return getSkull(url, UUID.randomUUID());
}

private static String generateRandomUsername(int length) {
// Random username for GameProfile
int leftLimit = 'A'; // letter 'a'
int rightLimit = 'Z'; // letter 'z'
return ThreadLocalRandom.current().ints(leftLimit, rightLimit + 1)
.limit(length)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
private static String getBase64Value(String texture) {
String original = "{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + texture + "\"}}}";
return Base64.getEncoder().encodeToString(original.getBytes(StandardCharsets.UTF_8));
}

}
}