Skip to content

Commit

Permalink
separate code for different minecraft versions in skull builder
Browse files Browse the repository at this point in the history
  • Loading branch information
jorisguffens committed Nov 23, 2023

Unverified

This user has not yet uploaded their public signing key.
1 parent 9fe363e commit 2a8b3e5
Showing 7 changed files with 296 additions and 81 deletions.
4 changes: 3 additions & 1 deletion bukkit/build.gradle
Original file line number Diff line number Diff line change
@@ -20,7 +20,9 @@ dependencies {
implementation project(':api')
implementation project(':common')

compileOnly 'org.bukkit:bukkit:1.8.8-R0.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT'
compileOnly 'org.spigotmc:spigot-api:1.20.2-R0.1-SNAPSHOT'
compileOnly 'commons-lang:commons-lang:2.6'

compileOnly 'net.milkbowl.vault:VaultAPI:1.7'
compileOnly ('com.discordsrv:discordsrv:1.22.0') {
Original file line number Diff line number Diff line change
@@ -18,7 +18,10 @@
package com.gufli.kingdomcraft.bukkit.gui;

import com.gufli.kingdomcraft.api.KingdomCraftProvider;
import com.gufli.kingdomcraft.bukkit.reflection.Reflection;
import com.gufli.kingdomcraft.bukkit.gui.skull.LegacySkullBuilder;
import com.gufli.kingdomcraft.bukkit.gui.skull.ModernSkullBuilder;
import com.gufli.kingdomcraft.bukkit.gui.skull.SkullBuilder;
import com.gufli.kingdomcraft.bukkit.reflection.VersionUtils;
import org.bukkit.*;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
@@ -29,10 +32,10 @@
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;

@@ -266,90 +269,23 @@ public ItemStackBuilder withLeatherColor(Color color) {

// SKULLS

private static Class<?> GameProfile;
private static Method GameProfile_getProperties;
private static Class<?> Property;
private static Method Property_getName;
private static Method PropertyMap_put;
private static Field CraftMetaSkull_profile;
private static Method CraftMetaSkull_setOwningPlayer;
private static final SkullBuilder skullBuilder;

static {

try {
GameProfile = Class.forName("com.mojang.authlib.GameProfile");
GameProfile_getProperties = GameProfile.getDeclaredMethod("getProperties");

Property = Class.forName("com.mojang.authlib.properties.Property");
Property_getName = Property.getMethod("getName");

Class<?> PropertyMap = Class.forName("com.mojang.authlib.properties.PropertyMap");
PropertyMap_put = PropertyMap.getMethod("put", Object.class, Object.class);

Class<?> CraftMetaSkull = Reflection.PackageType.CRAFTBUKKIT_INVENTORY.getClass("CraftMetaSkull");
CraftMetaSkull_profile = CraftMetaSkull.getDeclaredField("profile");
CraftMetaSkull_profile.setAccessible(true);

// Optional
try {
CraftMetaSkull_setOwningPlayer = CraftMetaSkull.getMethod("setOwningPlayer", OfflinePlayer.class);
} catch (NoSuchMethodException ignored) {}

} catch (NoSuchMethodException | ClassNotFoundException | NoSuchFieldException e) {
e.printStackTrace();
if (VersionUtils.isMcGreaterOrEqualTo("1.17") ) {
skullBuilder = new ModernSkullBuilder();
} else {
skullBuilder = new LegacySkullBuilder();
}
}

public ItemStackBuilder withSkullOwner(OfflinePlayer owner) {
if ( owner == null ) {
return this;
}
return transformMeta(SkullMeta.class, meta -> {
if ( CraftMetaSkull_setOwningPlayer != null ) {
try {
CraftMetaSkull_setOwningPlayer.invoke(meta, owner);
return;
} catch (IllegalAccessException | InvocationTargetException ignored) {}
}

// Fallback to deprecated method
meta.setOwner(owner.getName());
});
}

public ItemStackBuilder withSkullTexture(String texture) {
try {
UUID uuid = UUID.randomUUID();

Object profile = GameProfile.getDeclaredConstructor(UUID.class, String.class).newInstance(uuid, uuid.toString().substring(0, 15));
Object property = Property.getDeclaredConstructor(String.class, String.class).newInstance("textures", texture);
Object properties = GameProfile_getProperties.invoke(profile);
PropertyMap_put.invoke(properties, Property_getName.invoke(property), property);
return withSkullProfile(profile);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
ex.printStackTrace();
}
return this;
}

public ItemStackBuilder withSkullTexture(UUID uuid) {
try {
Object profile = GameProfile.getDeclaredConstructor(UUID.class, String.class).newInstance(uuid, uuid.toString().substring(0, 15));
return withSkullProfile(profile);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
ex.printStackTrace();
}
skullBuilder.withSkullOwner(itemStack, owner);
return this;
}

private ItemStackBuilder withSkullProfile(Object profile) {
try {
SkullMeta meta = (SkullMeta) this.itemStack.getItemMeta();
CraftMetaSkull_profile.set(meta, profile);
this.itemStack.setItemMeta(meta);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
public ItemStackBuilder withSkullTexture(String texture) {
skullBuilder.withSkullTexture(itemStack, texture);
return this;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.gufli.kingdomcraft.bukkit.gui.skull;

import com.gufli.kingdomcraft.bukkit.reflection.Reflection;
import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;

public class LegacySkullBuilder implements SkullBuilder {

private static Class<?> GameProfile;
private static Method GameProfile_getProperties;
private static Class<?> Property;
private static Method Property_getName;
private static Method PropertyMap_put;
private static Field CraftMetaSkull_profile;
private static Method CraftMetaSkull_setOwningPlayer;

static {

try {
GameProfile = Class.forName("com.mojang.authlib.GameProfile");
GameProfile_getProperties = GameProfile.getDeclaredMethod("getProperties");

Property = Class.forName("com.mojang.authlib.properties.Property");
Property_getName = Property.getMethod("getName");

Class<?> PropertyMap = Class.forName("com.mojang.authlib.properties.PropertyMap");
PropertyMap_put = PropertyMap.getMethod("put", Object.class, Object.class);

Class<?> CraftMetaSkull = Reflection.PackageType.CRAFTBUKKIT_INVENTORY.getClass("CraftMetaSkull");
CraftMetaSkull_profile = CraftMetaSkull.getDeclaredField("profile");
CraftMetaSkull_profile.setAccessible(true);

// Optional
try {
CraftMetaSkull_setOwningPlayer = CraftMetaSkull.getMethod("setOwningPlayer", OfflinePlayer.class);
} catch (NoSuchMethodException ignored) {}

} catch (NoSuchMethodException | ClassNotFoundException | NoSuchFieldException e) {
e.printStackTrace();
}
}

@Override
public void withSkullOwner(ItemStack itemStack, OfflinePlayer owner) {
if ( owner == null ) {
return;
}

SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
if ( CraftMetaSkull_setOwningPlayer != null ) {
try {
CraftMetaSkull_setOwningPlayer.invoke(meta, owner);
return;
} catch (IllegalAccessException | InvocationTargetException ignored) {}
}

// Fallback to deprecated method
meta.setOwner(owner.getName());
itemStack.setItemMeta(meta);
}

@Override
public void withSkullTexture(ItemStack itemStack, String texture) {
try {
UUID uuid = UUID.randomUUID();
Object profile = GameProfile.getDeclaredConstructor(UUID.class, String.class).newInstance(uuid, uuid.toString().substring(0, 15));
Object property = Property.getDeclaredConstructor(String.class, String.class).newInstance("textures", texture);
Object properties = GameProfile_getProperties.invoke(profile);
PropertyMap_put.invoke(properties, Property_getName.invoke(property), property);
withSkullProfile(itemStack, profile);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
ex.printStackTrace();
}
}

// public void withSkullTexture(ItemStack itemStack, UUID uuid) {
// try {
// Object profile = GameProfile.getDeclaredConstructor(UUID.class, String.class).newInstance(uuid, uuid.toString().substring(0, 15));
// withSkullProfile(itemStack, profile);
// } catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
// ex.printStackTrace();
// }
// }

private void withSkullProfile(ItemStack itemStack, Object profile) {
try {
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
CraftMetaSkull_profile.set(meta, profile);
itemStack.setItemMeta(meta);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.gufli.kingdomcraft.bukkit.gui.skull;

import org.apache.commons.lang.RandomStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.profile.PlayerProfile;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;

public class ModernSkullBuilder implements SkullBuilder {

@Override
public void withSkullOwner(ItemStack itemStack, OfflinePlayer owner) {
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
meta.setOwningPlayer(owner);
itemStack.setItemMeta(meta);
}

@Override
public void withSkullTexture(ItemStack itemStack, String texture) {
try {
withTexture(itemStack, new URL("https://textures.minecraft.net/texture/" + texture));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}

private void withProfile(ItemStack itemStack, PlayerProfile profile) {
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
meta.setOwnerProfile(profile);
itemStack.setItemMeta(meta);
}

private void withTexture(ItemStack itemStack, URL textureUrl) {
PlayerProfile profile = Bukkit.createPlayerProfile(UUID.randomUUID(), RandomStringUtils.randomAlphanumeric(16));
profile.getTextures().setSkin(textureUrl);
withProfile(itemStack, profile);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gufli.kingdomcraft.bukkit.gui.skull;

import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack;

public interface SkullBuilder {

void withSkullOwner(ItemStack itemStack, OfflinePlayer owner);

void withSkullTexture(ItemStack itemStack, String texture);

}
Original file line number Diff line number Diff line change
@@ -25,8 +25,10 @@
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class Reflection {

@@ -349,5 +351,57 @@ public static Object asNMSCopy(ItemStack stack) {
}
return null;
}
//

/**
* @param v1 version number to compare with
* @param v2 version number
* @return the value 0 if v1 == v2; the value -1 if v1 < v2; the value 1 if v1 > v1
*/
public static int compareVersions(String v1, String v2) {
int[] va1 = parseVersion(v1);
int[] va2 = parseVersion(v2);

for (int i = 0; i < Math.min(va2.length, va1.length); i++) {
if (va1[i] == va2[i]) {
continue;
}

return Integer.compare(va1[i], va2[i]);
}

return 0;
}

private static int[] parseVersion(String version) {
String[] va = version.split(Pattern.quote("."));
String vl = va[va.length - 1];
for (int i = 0; i < vl.length(); i++) {
if ( !Character.isDigit(vl.charAt(i)) ) {
va[va.length - 1] = vl.substring(0, i);
break;
}
}
return Arrays.stream(va)
.filter(s -> !s.equals(""))
.mapToInt(Integer::parseInt)
.toArray();
}

public static boolean isMcLowerOrEqualTo(String version) {
return compareVersions(getVersion(), version) <= 0;
}

public static boolean isMcLowerThan(String version) {
return compareVersions(getVersion(), version) < 0;
}

public static boolean isMcGreaterThan(String version) {
return compareVersions(getVersion(), version) > 0;
}

public static boolean isMcGreaterOrEqualTo(String version) {
return compareVersions(getVersion(), version) >= 0;
}

}
Loading

0 comments on commit 2a8b3e5

Please sign in to comment.