forked from Upstream/CommandPanels
3.21.4.2
This commit is contained in:
parent
768b2a6de9
commit
9975b2f76a
@ -51,6 +51,11 @@
|
|||||||
<option name="name" value="Maven Central repository" />
|
<option name="name" value="Maven Central repository" />
|
||||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="oraxen" />
|
||||||
|
<option name="name" value="Oraxen Repository" />
|
||||||
|
<option name="url" value="https://repo.oraxen.com/#/releases" />
|
||||||
|
</remote-repository>
|
||||||
<remote-repository>
|
<remote-repository>
|
||||||
<option name="id" value="phoenix" />
|
<option name="id" value="phoenix" />
|
||||||
<option name="name" value="phoenix" />
|
<option name="name" value="phoenix" />
|
||||||
@ -61,6 +66,16 @@
|
|||||||
<option name="name" value="BenCodez Repo" />
|
<option name="name" value="BenCodez Repo" />
|
||||||
<option name="url" value="https://nexus.bencodez.com/repository/maven-public/" />
|
<option name="url" value="https://nexus.bencodez.com/repository/maven-public/" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="oraxen" />
|
||||||
|
<option name="name" value="Oraxen Repository" />
|
||||||
|
<option name="url" value="https://repo.oraxen.com/releases" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="jitpack-repo" />
|
||||||
|
<option name="name" value="jitpack-repo" />
|
||||||
|
<option name="url" value="https://jitpack.io" />
|
||||||
|
</remote-repository>
|
||||||
<remote-repository>
|
<remote-repository>
|
||||||
<option name="id" value="ess-repo" />
|
<option name="id" value="ess-repo" />
|
||||||
<option name="name" value="ess-repo" />
|
<option name="name" value="ess-repo" />
|
||||||
|
23
pom.xml
23
pom.xml
@ -71,14 +71,14 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
|
||||||
<id>io.papermc</id>
|
|
||||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
<repository>
|
||||||
<id>jitpack.io</id>
|
<id>jitpack.io</id>
|
||||||
<url>https://jitpack.io</url>
|
<url>https://jitpack.io</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>io.papermc</id>
|
||||||
|
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||||
|
</repository>
|
||||||
<repository>
|
<repository>
|
||||||
<id>minecraft-repo</id>
|
<id>minecraft-repo</id>
|
||||||
<url>https://libraries.minecraft.net/</url>
|
<url>https://libraries.minecraft.net/</url>
|
||||||
@ -175,26 +175,15 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.Indyuce</groupId>
|
<groupId>net.Indyuce</groupId>
|
||||||
<artifactId>MMOItems-API</artifactId>
|
<artifactId>MMOItems-API</artifactId>
|
||||||
<version>LATEST</version>
|
<version>6.10-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.lumine</groupId>
|
<groupId>io.lumine</groupId>
|
||||||
<artifactId>MythicLib-dist</artifactId>
|
<artifactId>MythicLib-dist</artifactId>
|
||||||
<version>LATEST</version>
|
<version>1.6.2-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.Realizedd</groupId>
|
|
||||||
<artifactId>TokenManager</artifactId>
|
|
||||||
<version>3.2.4</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>*</groupId>
|
|
||||||
<artifactId>*</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.arcaniax</groupId>
|
<groupId>com.arcaniax</groupId>
|
||||||
<artifactId>HeadDatabase-API</artifactId>
|
<artifactId>HeadDatabase-API</artifactId>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: 3.21.4.1
|
version: 3.21.4.2
|
||||||
main: me.rockyhawk.commandpanels.CommandPanels
|
main: me.rockyhawk.commandpanels.CommandPanels
|
||||||
name: CommandPanels
|
name: CommandPanels
|
||||||
author: RockyHawk
|
author: RockyHawk
|
||||||
|
@ -7,6 +7,7 @@ import me.rockyhawk.commandpanels.api.Panel;
|
|||||||
import me.rockyhawk.commandpanels.classresources.ExecuteOpenVoids;
|
import me.rockyhawk.commandpanels.classresources.ExecuteOpenVoids;
|
||||||
import me.rockyhawk.commandpanels.classresources.MiniMessageUtils;
|
import me.rockyhawk.commandpanels.classresources.MiniMessageUtils;
|
||||||
import me.rockyhawk.commandpanels.classresources.customheads.GetCustomHeads;
|
import me.rockyhawk.commandpanels.classresources.customheads.GetCustomHeads;
|
||||||
|
import me.rockyhawk.commandpanels.classresources.customheads.methods.CustomHeadGameProfile;
|
||||||
import me.rockyhawk.commandpanels.classresources.HasSections;
|
import me.rockyhawk.commandpanels.classresources.HasSections;
|
||||||
import me.rockyhawk.commandpanels.classresources.ItemCreation;
|
import me.rockyhawk.commandpanels.classresources.ItemCreation;
|
||||||
import me.rockyhawk.commandpanels.classresources.placeholders.expansion.CpPlaceholderExpansion;
|
import me.rockyhawk.commandpanels.classresources.placeholders.expansion.CpPlaceholderExpansion;
|
||||||
@ -120,7 +121,6 @@ public class CommandPanels extends JavaPlugin{
|
|||||||
public InventorySaver inventorySaver = new InventorySaver(this);
|
public InventorySaver inventorySaver = new InventorySaver(this);
|
||||||
public ItemStackSerializer itemSerializer = new ItemStackSerializer(this);
|
public ItemStackSerializer itemSerializer = new ItemStackSerializer(this);
|
||||||
public UserInputUtils inputUtils = new UserInputUtils(this);
|
public UserInputUtils inputUtils = new UserInputUtils(this);
|
||||||
public OpenFloodgateGUI floodgateOpenGUI = new OpenFloodgateGUI(this);
|
|
||||||
|
|
||||||
public File panelsf = new File(this.getDataFolder() + File.separator + "panels");
|
public File panelsf = new File(this.getDataFolder() + File.separator + "panels");
|
||||||
public YamlConfiguration blockConfig; //where panel block locations are stored
|
public YamlConfiguration blockConfig; //where panel block locations are stored
|
||||||
@ -128,6 +128,9 @@ public class CommandPanels extends JavaPlugin{
|
|||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
Bukkit.getLogger().info("[CommandPanels] RockyHawk's CommandPanels v" + this.getDescription().getVersion() + " Plugin Loading...");
|
Bukkit.getLogger().info("[CommandPanels] RockyHawk's CommandPanels v" + this.getDescription().getVersion() + " Plugin Loading...");
|
||||||
|
|
||||||
|
//Initialise classes that are not used externally
|
||||||
|
new OpenFloodgateGUI(this);
|
||||||
|
|
||||||
//register config files
|
//register config files
|
||||||
this.blockConfig = YamlConfiguration.loadConfiguration(new File(getDataFolder() + File.separator + "blocks.yml"));
|
this.blockConfig = YamlConfiguration.loadConfiguration(new File(getDataFolder() + File.separator + "blocks.yml"));
|
||||||
panelData.dataConfig = YamlConfiguration.loadConfiguration(new File(getDataFolder() + File.separator + "data.yml"));
|
panelData.dataConfig = YamlConfiguration.loadConfiguration(new File(getDataFolder() + File.separator + "data.yml"));
|
||||||
|
@ -9,9 +9,7 @@ import org.bukkit.configuration.ConfigurationSection;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
public class HasSections {
|
public class HasSections {
|
||||||
CommandPanels plugin;
|
CommandPanels plugin;
|
||||||
@ -20,10 +18,29 @@ public class HasSections {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String hasSection(Panel panel, PanelPosition position, ConfigurationSection cf, Player p) {
|
public String hasSection(Panel panel, PanelPosition position, ConfigurationSection cf, Player p) {
|
||||||
for (String setName : cf.getKeys(false)) {
|
// Use a TreeMap to automatically sort the sections by the extracted number.
|
||||||
if (!cf.isConfigurationSection(setName)) continue;
|
Map<Integer, String> sortedSections = new TreeMap<>();
|
||||||
|
|
||||||
ConfigurationSection currentSection = cf.getConfigurationSection(setName);
|
// Loop through the section names and filter for the ones starting with "has".
|
||||||
|
for (String key : cf.getKeys(false)) {
|
||||||
|
if (!cf.isConfigurationSection(key)) continue;
|
||||||
|
|
||||||
|
// Check if the section starts with "has" and is followed by a number.
|
||||||
|
if (key.startsWith("has")) {
|
||||||
|
try {
|
||||||
|
// Extract the number after "has" and put it in the map for sorting.
|
||||||
|
int number = Integer.parseInt(key.substring(3));
|
||||||
|
sortedSections.put(number, key);
|
||||||
|
} catch (NumberFormatException ignore) {
|
||||||
|
// If the section name doesn't have a valid number after "has", skip it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String hasSection : sortedSections.values()) {
|
||||||
|
if (!cf.isConfigurationSection(hasSection)) continue;
|
||||||
|
|
||||||
|
ConfigurationSection currentSection = cf.getConfigurationSection(hasSection);
|
||||||
int numberOfConditions = currentSection.getKeys(false).size();
|
int numberOfConditions = currentSection.getKeys(false).size();
|
||||||
|
|
||||||
Boolean currentBlockResult = null; // This will store the result of the current block (a set of conditions combined by AND or OR).
|
Boolean currentBlockResult = null; // This will store the result of the current block (a set of conditions combined by AND or OR).
|
||||||
@ -48,7 +65,7 @@ public class HasSections {
|
|||||||
HashSet<String> values = doOperators(new HashSet<>(Collections.singletonList(value)));
|
HashSet<String> values = doOperators(new HashSet<>(Collections.singletonList(value)));
|
||||||
boolean localResult = false; // This tracks the result of the current condition.
|
boolean localResult = false; // This tracks the result of the current condition.
|
||||||
for (String val : values) {
|
for (String val : values) {
|
||||||
if (hasProcess(setName, val, compare, p)) {
|
if (hasProcess(val, compare)) {
|
||||||
localResult = true;
|
localResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -71,7 +88,7 @@ public class HasSections {
|
|||||||
|
|
||||||
if (currentBlockResult != null && currentBlockResult) {
|
if (currentBlockResult != null && currentBlockResult) {
|
||||||
// If the result of this section is true, check nested sections.
|
// If the result of this section is true, check nested sections.
|
||||||
return "." + setName + hasSection(panel, position, currentSection, p);
|
return "." + hasSection + hasSection(panel, position, currentSection, p);
|
||||||
}
|
}
|
||||||
// If the result is false, continue to the next 'has' section.
|
// If the result is false, continue to the next 'has' section.
|
||||||
}
|
}
|
||||||
@ -90,7 +107,7 @@ public class HasSections {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasProcess(String setName, String value, String compare,Player p){
|
private boolean hasProcess(String value, String compare){
|
||||||
//check to see if the value should be reversed
|
//check to see if the value should be reversed
|
||||||
boolean outputValue = true;
|
boolean outputValue = true;
|
||||||
if(value.startsWith("NOT ")){
|
if(value.startsWith("NOT ")){
|
||||||
@ -99,7 +116,6 @@ public class HasSections {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//the current has section with all the functions implemented inside it
|
//the current has section with all the functions implemented inside it
|
||||||
if(setName.startsWith("has")) {
|
|
||||||
if(value.endsWith(" HASPERM")) {
|
if(value.endsWith(" HASPERM")) {
|
||||||
String playername = value.substring(0, value.length()-8);
|
String playername = value.substring(0, value.length()-8);
|
||||||
Player player = Bukkit.getPlayerExact(playername);
|
Player player = Bukkit.getPlayerExact(playername);
|
||||||
@ -111,7 +127,6 @@ public class HasSections {
|
|||||||
}else{
|
}else{
|
||||||
return compare.equals(value) == outputValue;
|
return compare.equals(value) == outputValue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import dev.lone.itemsadder.api.CustomStack;
|
|||||||
import me.arcaniax.hdb.api.HeadDatabaseAPI;
|
import me.arcaniax.hdb.api.HeadDatabaseAPI;
|
||||||
import me.rockyhawk.commandpanels.CommandPanels;
|
import me.rockyhawk.commandpanels.CommandPanels;
|
||||||
import me.rockyhawk.commandpanels.api.Panel;
|
import me.rockyhawk.commandpanels.api.Panel;
|
||||||
|
import me.rockyhawk.commandpanels.classresources.customheads.SavedCustomHead;
|
||||||
import me.rockyhawk.commandpanels.ioclasses.legacy.MinecraftVersions;
|
import me.rockyhawk.commandpanels.ioclasses.legacy.MinecraftVersions;
|
||||||
import me.rockyhawk.commandpanels.openpanelsmanager.PanelPosition;
|
import me.rockyhawk.commandpanels.openpanelsmanager.PanelPosition;
|
||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
@ -27,6 +28,7 @@ import org.bukkit.inventory.meta.trim.TrimMaterial;
|
|||||||
import org.bukkit.inventory.meta.trim.TrimPattern;
|
import org.bukkit.inventory.meta.trim.TrimPattern;
|
||||||
import org.bukkit.potion.PotionType;
|
import org.bukkit.potion.PotionType;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -95,7 +97,41 @@ public class ItemCreation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ItemsAdder support, needs namespaceID (eg, money:coin)
|
//Oraxen support, uses itemID (eg, oraxen= coin)
|
||||||
|
if (matraw.split("\\s")[0].equalsIgnoreCase("oraxen=")) {
|
||||||
|
String itemID = matraw.split("\\s")[1];
|
||||||
|
try {
|
||||||
|
// Load the OraxenItems class
|
||||||
|
Class<?> oraxenItemsClass = Class.forName("io.th0rgal.oraxen.api.OraxenItems");
|
||||||
|
|
||||||
|
// Retrieve the 'getItemById' method from the OraxenItems class
|
||||||
|
Method getItemByIdMethod = oraxenItemsClass.getMethod("getItemById", String.class);
|
||||||
|
getItemByIdMethod.setAccessible(true);
|
||||||
|
|
||||||
|
// Invoke the 'getItemById' method with the itemID
|
||||||
|
Object oraxenItem = getItemByIdMethod.invoke(null, itemID); // static method, so pass 'null'
|
||||||
|
|
||||||
|
// Ensure that the method returned a valid Oraxen item
|
||||||
|
if (oraxenItem != null) {
|
||||||
|
// Now we need to invoke 'getReferenceClone' on the OraxenItem object
|
||||||
|
Method getReferenceCloneMethod = oraxenItem.getClass().getMethod("getReferenceClone");
|
||||||
|
getReferenceCloneMethod.setAccessible(true);
|
||||||
|
ItemStack stack = (ItemStack) getReferenceCloneMethod.invoke(oraxenItem);
|
||||||
|
|
||||||
|
// Check if stack is not null
|
||||||
|
if (stack != null) {
|
||||||
|
s = stack;
|
||||||
|
normalCreation = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.debug(e, null);
|
||||||
|
// Handle the error or inform the player
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//ItemsAdder support, needs namespaceID (eg, itemsadder= money:coin)
|
||||||
if (matraw.split("\\s")[0].equalsIgnoreCase("itemsadder=")) {
|
if (matraw.split("\\s")[0].equalsIgnoreCase("itemsadder=")) {
|
||||||
String namespaceID = matraw.split("\\s")[1];
|
String namespaceID = matraw.split("\\s")[1];
|
||||||
CustomStack stack = CustomStack.getInstance(namespaceID);
|
CustomStack stack = CustomStack.getInstance(namespaceID);
|
||||||
@ -444,16 +480,9 @@ public class ItemCreation {
|
|||||||
}
|
}
|
||||||
if(plugin.getHeads.ifSkullOrHead(cont.getType().toString())){
|
if(plugin.getHeads.ifSkullOrHead(cont.getType().toString())){
|
||||||
if(!Objects.requireNonNull(file.getString("panels." + panelName + ".item." + i + ".material")).contains("%") && !Objects.requireNonNull(file.getString("panels." + panelName + ".item." + i + ".material")).contains("=")) {
|
if(!Objects.requireNonNull(file.getString("panels." + panelName + ".item." + i + ".material")).contains("%") && !Objects.requireNonNull(file.getString("panels." + panelName + ".item." + i + ".material")).contains("=")) {
|
||||||
SkullMeta meta = (SkullMeta) cont.getItemMeta();
|
|
||||||
if (plugin.customHeads.getHeadBase64(cont) != null) {
|
|
||||||
//inject base64 here, disable for legacy as is not working
|
|
||||||
file.set("panels." + panelName + ".item." + i + ".material", "cps= " + plugin.customHeads.getHeadBase64(cont));
|
|
||||||
} else{
|
|
||||||
//return blank head
|
|
||||||
file.set("panels." + panelName + ".item." + i + ".material", plugin.getHeads.playerHeadString());
|
file.set("panels." + panelName + ".item." + i + ".material", plugin.getHeads.playerHeadString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
BannerMeta bannerMeta = (BannerMeta) cont.getItemMeta();
|
BannerMeta bannerMeta = (BannerMeta) cont.getItemMeta();
|
||||||
List<String> dyePattern = new ArrayList<>();
|
List<String> dyePattern = new ArrayList<>();
|
||||||
|
@ -1,216 +1,34 @@
|
|||||||
package me.rockyhawk.commandpanels.classresources.customheads;
|
package me.rockyhawk.commandpanels.classresources.customheads;
|
||||||
|
|
||||||
import com.mojang.authlib.GameProfile;
|
|
||||||
import com.mojang.authlib.properties.Property;
|
|
||||||
import com.mojang.authlib.properties.PropertyMap;
|
|
||||||
import me.arcaniax.hdb.api.HeadDatabaseAPI;
|
|
||||||
import me.rockyhawk.commandpanels.CommandPanels;
|
import me.rockyhawk.commandpanels.CommandPanels;
|
||||||
|
import me.rockyhawk.commandpanels.classresources.customheads.methods.CustomHeadGameProfile;
|
||||||
|
import me.rockyhawk.commandpanels.classresources.customheads.methods.CustomHeadPlayerProfile;
|
||||||
import me.rockyhawk.commandpanels.ioclasses.legacy.MinecraftVersions;
|
import me.rockyhawk.commandpanels.ioclasses.legacy.MinecraftVersions;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
|
||||||
import org.bukkit.inventory.meta.SkullMeta;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class GetCustomHeads {
|
public class GetCustomHeads {
|
||||||
|
CustomHeadGameProfile gameProfileHeadClass;
|
||||||
|
CustomHeadPlayerProfile playerProfileHeadClass;
|
||||||
CommandPanels plugin;
|
CommandPanels plugin;
|
||||||
|
|
||||||
public GetCustomHeads(CommandPanels pl) {
|
public GetCustomHeads(CommandPanels pl) {
|
||||||
this.plugin = pl;
|
this.plugin = pl;
|
||||||
|
gameProfileHeadClass = new CustomHeadGameProfile(pl);
|
||||||
|
playerProfileHeadClass = new CustomHeadPlayerProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMap<String, SavedCustomHead> savedCustomHeads = new HashMap<>();
|
public ItemStack getCustomHead(String base64){
|
||||||
|
if(plugin.legacy.MAJOR_VERSION.greaterThanOrEqualTo(MinecraftVersions.v1_18)){
|
||||||
public String getHeadBase64(ItemStack head) {
|
return playerProfileHeadClass.getCustomHead(base64);
|
||||||
if (plugin.getHeads.ifSkullOrHead(head.getType().toString()) && head.hasItemMeta()) {
|
|
||||||
//check if the head is a HeadDatabase head first
|
|
||||||
if(plugin.getServer().getPluginManager().isPluginEnabled("HeadDatabase")) {
|
|
||||||
HeadDatabaseAPI api = new HeadDatabaseAPI();
|
|
||||||
try {
|
|
||||||
String base64 = api.getBase64(head);
|
|
||||||
if(base64 != null){
|
|
||||||
return base64;
|
|
||||||
}
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
}
|
|
||||||
//try getting Base64 of a custom head
|
|
||||||
if (!(head.getItemMeta() instanceof SkullMeta)) return null;
|
|
||||||
SkullMeta meta = (SkullMeta) head.getItemMeta();
|
|
||||||
if (meta == null) return null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
Field profileField = meta.getClass().getDeclaredField("profile");
|
|
||||||
profileField.setAccessible(true);
|
|
||||||
GameProfile profile = (GameProfile) profileField.get(meta);
|
|
||||||
|
|
||||||
Collection<Property> textures = profile.getProperties().get("textures");
|
|
||||||
if (!textures.isEmpty()) {
|
|
||||||
// Directly accessing fields within the Property object via reflection.
|
|
||||||
Property textureProperty = textures.iterator().next();
|
|
||||||
Field valueField = textureProperty.getClass().getDeclaredField("value");
|
|
||||||
valueField.setAccessible(true);
|
|
||||||
return (String) valueField.get(textureProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception error) {
|
|
||||||
plugin.debug(error, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//getting the head from a Player Name
|
|
||||||
public ItemStack getPlayerHead(String name) {
|
|
||||||
byte id = 0;
|
|
||||||
if (plugin.legacy.MAJOR_VERSION.lessThanOrEqualTo(MinecraftVersions.v1_15)) {
|
|
||||||
id = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
//get texture if already cached
|
|
||||||
if (savedCustomHeads.containsKey(name)) {
|
|
||||||
if (!savedCustomHeads.get(name).isValid && (System.currentTimeMillis() - savedCustomHeads.get(name).lastAttempt) < 60000) {
|
|
||||||
// If the last attempt was less than 60 seconds ago and was invalid, return null or a default item
|
|
||||||
return new ItemStack(Material.valueOf(plugin.getHeads.playerHeadString()));
|
|
||||||
}
|
|
||||||
if(savedCustomHeads.get(name).isValid) {
|
|
||||||
return savedCustomHeads.get(name).headItem; // Return cached item if valid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//create ItemStack
|
|
||||||
ItemStack itemStack = new ItemStack(Material.matchMaterial(plugin.getHeads.playerHeadString()), 1, id);
|
|
||||||
|
|
||||||
//Run fallback code, if API call fails, use legacy setOwner
|
|
||||||
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
|
|
||||||
meta.setOwner(name);
|
|
||||||
itemStack.setItemMeta(meta);
|
|
||||||
|
|
||||||
// Fetch and cache the texture asynchronously
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
|
||||||
try {
|
|
||||||
if(plugin.debug.consoleDebug){
|
|
||||||
plugin.getServer().getConsoleSender().sendMessage(plugin.tex.colour(plugin.tag +
|
|
||||||
ChatColor.WHITE +
|
|
||||||
"Download & Cache Head Texture for " + name));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the player UUID from the Mojang API
|
|
||||||
URL uuidUrl = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
|
|
||||||
URLConnection uuidConnection = uuidUrl.openConnection();
|
|
||||||
uuidConnection.setConnectTimeout(2000); // Set connection timeout to 2 seconds
|
|
||||||
uuidConnection.setReadTimeout(2000); // Set read timeout to 2 seconds
|
|
||||||
//Json is simple and structured so a hard code solution will avoid the need for a library
|
|
||||||
String uuidReader = new Scanner(uuidConnection.getInputStream(),
|
|
||||||
StandardCharsets.UTF_8.name()).useDelimiter("\\A").next();
|
|
||||||
String uuid = uuidReader.split("\"id\" : \"")[1].split("\"")[0];
|
|
||||||
|
|
||||||
// Fetch the skin texture from the Mojang API using the player UUID
|
|
||||||
URL texturesUrl = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid);
|
|
||||||
URLConnection texturesConnection = texturesUrl.openConnection();
|
|
||||||
texturesConnection.setConnectTimeout(2000); // Set connection timeout to 2 seconds
|
|
||||||
texturesConnection.setReadTimeout(2000); // Set read timeout to 2 seconds
|
|
||||||
//Json is simple and structured so a hard code solution will avoid the need for a library
|
|
||||||
String valueReader = new Scanner(texturesConnection.getInputStream(),
|
|
||||||
StandardCharsets.UTF_8.name()).useDelimiter("\\A").next();
|
|
||||||
String value = valueReader.split("\"value\" : \"")[1].split("\"")[0];
|
|
||||||
|
|
||||||
// Once the API call is finished, update the ItemStack on the main thread
|
|
||||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
|
||||||
itemStack.setItemMeta(getCustomHead(name, value).getItemMeta());
|
|
||||||
savedCustomHeads.put(name, new SavedCustomHead(itemStack, value, true));
|
|
||||||
});
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
|
||||||
//do not overwrite a valid cached head
|
|
||||||
if(savedCustomHeads.containsKey(name) && savedCustomHeads.get(name).isValid){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
savedCustomHeads.put(name, new SavedCustomHead(null, null, false)); // Mark as invalid
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return itemStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
//will also use cached heads feature to get heads if player name is provided
|
|
||||||
public ItemStack getCustomHead(String playerName, String b64stringtexture) {
|
|
||||||
//check for any saved heads
|
|
||||||
if(savedCustomHeads.containsKey(playerName)) {
|
|
||||||
if (savedCustomHeads.get(playerName).base64 != null) {
|
|
||||||
return savedCustomHeads.get(playerName).headItem;
|
|
||||||
}
|
|
||||||
savedCustomHeads.get(playerName).isValid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if saved head is not found from player name, get head manually
|
|
||||||
return getCustomHead(b64stringtexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
//used to get heads from Base64 Textures
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public ItemStack getCustomHead(String b64stringtexture) {
|
|
||||||
//get head from base64
|
|
||||||
GameProfile profile = new GameProfile(UUID.randomUUID(), "");
|
|
||||||
PropertyMap propertyMap = profile.getProperties();
|
|
||||||
if (propertyMap == null) {
|
|
||||||
throw new IllegalStateException("Profile doesn't contain a property map");
|
|
||||||
}else{
|
}else{
|
||||||
propertyMap.put("textures", new Property("textures", b64stringtexture));
|
return gameProfileHeadClass.getCustomHead(base64);
|
||||||
byte id = 0;
|
|
||||||
if(plugin.legacy.MAJOR_VERSION.lessThanOrEqualTo(MinecraftVersions.v1_15)){
|
|
||||||
id = 3;
|
|
||||||
}
|
}
|
||||||
ItemStack head = new ItemStack(Material.matchMaterial(plugin.getHeads.playerHeadString()), 1,id);
|
}
|
||||||
ItemMeta headMeta = head.getItemMeta();
|
public ItemStack getPlayerHead(String playerName){
|
||||||
assert headMeta != null;
|
if(plugin.legacy.MAJOR_VERSION.greaterThanOrEqualTo(MinecraftVersions.v1_21)){
|
||||||
|
return playerProfileHeadClass.getPlayerHead(playerName);
|
||||||
Field profileField;
|
|
||||||
Method setProfileMethod = null;
|
|
||||||
try {
|
|
||||||
// Attempt to access the 'profile' field directly
|
|
||||||
// Also writes to 'serializedProfile' field as one cannot be null while the other is not
|
|
||||||
// This block is mainly for 1.20.2+ versions
|
|
||||||
profileField = headMeta.getClass().getDeclaredField("profile");
|
|
||||||
Field serializedProfileField = headMeta.getClass().getDeclaredField("serializedProfile");
|
|
||||||
|
|
||||||
profileField.setAccessible(true);
|
|
||||||
serializedProfileField.setAccessible(true);
|
|
||||||
|
|
||||||
profileField.set(headMeta, profile);
|
|
||||||
serializedProfileField.set(headMeta, profile); // Assuming serializedProfile is of the same type
|
|
||||||
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) {
|
|
||||||
try {
|
|
||||||
// This block covers versions that have a 'setProfile' method instead of direct field access
|
|
||||||
// Likely for versions prior to 1.20.2
|
|
||||||
setProfileMethod = headMeta.getClass().getDeclaredMethod("setProfile", GameProfile.class);
|
|
||||||
} catch (NoSuchMethodException ignore) {}
|
|
||||||
} catch (SecurityException ignored) {}
|
|
||||||
try {
|
|
||||||
if (setProfileMethod == null) {
|
|
||||||
// Attempt to access the 'profile' field directly
|
|
||||||
// This block is a generic fallback for versions lacking the 'setProfile' method
|
|
||||||
profileField = headMeta.getClass().getDeclaredField("profile");
|
|
||||||
profileField.setAccessible(true);
|
|
||||||
profileField.set(headMeta, profile);
|
|
||||||
}else{
|
}else{
|
||||||
// Use the 'setProfile' method if it was found
|
return gameProfileHeadClass.getPlayerHead(playerName);
|
||||||
setProfileMethod.setAccessible(true);
|
|
||||||
setProfileMethod.invoke(headMeta, profile);
|
|
||||||
}
|
|
||||||
} catch (Exception e1) {
|
|
||||||
plugin.debug(e1,null);
|
|
||||||
}
|
|
||||||
|
|
||||||
head.setItemMeta(headMeta);
|
|
||||||
return head;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,185 @@
|
|||||||
|
package me.rockyhawk.commandpanels.classresources.customheads.methods;
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import com.mojang.authlib.properties.Property;
|
||||||
|
import com.mojang.authlib.properties.PropertyMap;
|
||||||
|
import me.rockyhawk.commandpanels.CommandPanels;
|
||||||
|
import me.rockyhawk.commandpanels.classresources.customheads.SavedCustomHead;
|
||||||
|
import me.rockyhawk.commandpanels.ioclasses.legacy.MinecraftVersions;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class CustomHeadGameProfile {
|
||||||
|
CommandPanels plugin;
|
||||||
|
public CustomHeadGameProfile(CommandPanels pl) {
|
||||||
|
this.plugin = pl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, SavedCustomHead> savedCustomHeads = new HashMap<>();
|
||||||
|
|
||||||
|
//getting the head from a Player Name
|
||||||
|
public ItemStack getPlayerHead(String name) {
|
||||||
|
byte id = 0;
|
||||||
|
if (plugin.legacy.MAJOR_VERSION.lessThanOrEqualTo(MinecraftVersions.v1_15)) {
|
||||||
|
id = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get texture if already cached
|
||||||
|
if (savedCustomHeads.containsKey(name)) {
|
||||||
|
if (!savedCustomHeads.get(name).isValid && (System.currentTimeMillis() - savedCustomHeads.get(name).lastAttempt) < 60000) {
|
||||||
|
// If the last attempt was less than 60 seconds ago and was invalid, return null or a default item
|
||||||
|
return new ItemStack(Material.valueOf(plugin.getHeads.playerHeadString()));
|
||||||
|
}
|
||||||
|
if(savedCustomHeads.get(name).isValid) {
|
||||||
|
return savedCustomHeads.get(name).headItem; // Return cached item if valid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//create ItemStack
|
||||||
|
ItemStack itemStack = new ItemStack(Material.matchMaterial(plugin.getHeads.playerHeadString()), 1, id);
|
||||||
|
|
||||||
|
//Run fallback code, if API call fails, use legacy setOwner
|
||||||
|
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
|
||||||
|
meta.setOwner(name);
|
||||||
|
itemStack.setItemMeta(meta);
|
||||||
|
|
||||||
|
// Fetch and cache the texture asynchronously
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
|
try {
|
||||||
|
if(plugin.debug.consoleDebug){
|
||||||
|
plugin.getServer().getConsoleSender().sendMessage(plugin.tex.colour(plugin.tag +
|
||||||
|
ChatColor.WHITE +
|
||||||
|
"Download & Cache Head Texture for " + name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the player UUID from the Mojang API
|
||||||
|
URL uuidUrl = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
|
||||||
|
URLConnection uuidConnection = uuidUrl.openConnection();
|
||||||
|
uuidConnection.setConnectTimeout(2000); // Set connection timeout to 2 seconds
|
||||||
|
uuidConnection.setReadTimeout(2000); // Set read timeout to 2 seconds
|
||||||
|
//Json is simple and structured so a hard code solution will avoid the need for a library
|
||||||
|
String uuidReader = new Scanner(uuidConnection.getInputStream(),
|
||||||
|
StandardCharsets.UTF_8.name()).useDelimiter("\\A").next();
|
||||||
|
String uuid = uuidReader.split("\"id\" : \"")[1].split("\"")[0];
|
||||||
|
|
||||||
|
// Fetch the skin texture from the Mojang API using the player UUID
|
||||||
|
URL texturesUrl = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid);
|
||||||
|
URLConnection texturesConnection = texturesUrl.openConnection();
|
||||||
|
texturesConnection.setConnectTimeout(2000); // Set connection timeout to 2 seconds
|
||||||
|
texturesConnection.setReadTimeout(2000); // Set read timeout to 2 seconds
|
||||||
|
//Json is simple and structured so a hard code solution will avoid the need for a library
|
||||||
|
String valueReader = new Scanner(texturesConnection.getInputStream(),
|
||||||
|
StandardCharsets.UTF_8.name()).useDelimiter("\\A").next();
|
||||||
|
String value = valueReader.split("\"value\" : \"")[1].split("\"")[0];
|
||||||
|
|
||||||
|
// Once the API call is finished, update the ItemStack on the main thread
|
||||||
|
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||||
|
itemStack.setItemMeta(getCustomHead(name, value).getItemMeta());
|
||||||
|
savedCustomHeads.put(name, new SavedCustomHead(itemStack, value, true));
|
||||||
|
});
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||||
|
//do not overwrite a valid cached head
|
||||||
|
if(savedCustomHeads.containsKey(name) && savedCustomHeads.get(name).isValid){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
savedCustomHeads.put(name, new SavedCustomHead(null, null, false)); // Mark as invalid
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
//will also use cached heads feature to get heads if player name is provided
|
||||||
|
public ItemStack getCustomHead(String playerName, String b64stringtexture) {
|
||||||
|
//check for any saved heads
|
||||||
|
if(savedCustomHeads.containsKey(playerName)) {
|
||||||
|
if (savedCustomHeads.get(playerName).base64 != null) {
|
||||||
|
return savedCustomHeads.get(playerName).headItem;
|
||||||
|
}
|
||||||
|
savedCustomHeads.get(playerName).isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//clear cached textures list until length limit is reached
|
||||||
|
Iterator<Map.Entry<String, SavedCustomHead>> iterator = savedCustomHeads.entrySet().iterator();
|
||||||
|
while (savedCustomHeads.size() > 2000 && iterator.hasNext()) {
|
||||||
|
iterator.next(); // Move to next entry
|
||||||
|
iterator.remove(); // Remove the entry
|
||||||
|
}
|
||||||
|
|
||||||
|
//if saved head is not found from player name, get head manually
|
||||||
|
return getCustomHead(b64stringtexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
//used to get heads from Base64 Textures
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public ItemStack getCustomHead(String b64stringtexture) {
|
||||||
|
//get head from base64
|
||||||
|
GameProfile profile = new GameProfile(UUID.randomUUID(), "");
|
||||||
|
PropertyMap propertyMap = profile.getProperties();
|
||||||
|
if (propertyMap == null) {
|
||||||
|
throw new IllegalStateException("Profile doesn't contain a property map");
|
||||||
|
} else {
|
||||||
|
propertyMap.put("textures", new Property("textures", b64stringtexture));
|
||||||
|
byte id = 0;
|
||||||
|
if(plugin.legacy.MAJOR_VERSION.lessThanOrEqualTo(MinecraftVersions.v1_15)){
|
||||||
|
id = 3;
|
||||||
|
}
|
||||||
|
ItemStack head = new ItemStack(Material.matchMaterial(plugin.getHeads.playerHeadString()), 1,id);
|
||||||
|
ItemMeta headMeta = head.getItemMeta();
|
||||||
|
assert headMeta != null;
|
||||||
|
|
||||||
|
Field profileField;
|
||||||
|
Method setProfileMethod = null;
|
||||||
|
try {
|
||||||
|
// Attempt to access the 'profile' field directly
|
||||||
|
// Also writes to 'serializedProfile' field as one cannot be null while the other is not
|
||||||
|
// This block is mainly for 1.20.2+ versions
|
||||||
|
profileField = headMeta.getClass().getDeclaredField("profile");
|
||||||
|
Field serializedProfileField = headMeta.getClass().getDeclaredField("serializedProfile");
|
||||||
|
|
||||||
|
profileField.setAccessible(true);
|
||||||
|
serializedProfileField.setAccessible(true);
|
||||||
|
|
||||||
|
profileField.set(headMeta, profile);
|
||||||
|
serializedProfileField.set(headMeta, profile); // Assuming serializedProfile is of the same type
|
||||||
|
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) {
|
||||||
|
try {
|
||||||
|
// This block covers versions that have a 'setProfile' method instead of direct field access
|
||||||
|
// Likely for versions prior to 1.20.2
|
||||||
|
setProfileMethod = headMeta.getClass().getDeclaredMethod("setProfile", GameProfile.class);
|
||||||
|
} catch (NoSuchMethodException ignore) {}
|
||||||
|
} catch (SecurityException ignored) {}
|
||||||
|
try {
|
||||||
|
if (setProfileMethod == null) {
|
||||||
|
// Attempt to access the 'profile' field directly
|
||||||
|
// This block is a generic fallback for versions lacking the 'setProfile' method
|
||||||
|
profileField = headMeta.getClass().getDeclaredField("profile");
|
||||||
|
profileField.setAccessible(true);
|
||||||
|
profileField.set(headMeta, profile);
|
||||||
|
} else {
|
||||||
|
// Use the 'setProfile' method if it was found
|
||||||
|
setProfileMethod.setAccessible(true);
|
||||||
|
setProfileMethod.invoke(headMeta, profile);
|
||||||
|
}
|
||||||
|
} catch (Exception e1) {
|
||||||
|
plugin.debug(e1,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
head.setItemMeta(headMeta);
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
package me.rockyhawk.commandpanels.classresources.customheads.methods;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
import org.bukkit.profile.PlayerProfile;
|
||||||
|
import org.bukkit.profile.PlayerTextures;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class CustomHeadPlayerProfile {
|
||||||
|
//cached itemstacks stored for access
|
||||||
|
public HashMap<String, ItemStack> savedCustomHeads = new HashMap<>();
|
||||||
|
|
||||||
|
//Using the PlayerProfile API for getting custom heads
|
||||||
|
public ItemStack getCustomHead(String base64Texture) {
|
||||||
|
//check for any saved heads
|
||||||
|
if(savedCustomHeads.containsKey(base64Texture)) {
|
||||||
|
return savedCustomHeads.get(base64Texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
//clear cached textures list until length limit is reached
|
||||||
|
Iterator<Map.Entry<String, ItemStack>> iterator = savedCustomHeads.entrySet().iterator();
|
||||||
|
while (savedCustomHeads.size() > 2000 && iterator.hasNext()) {
|
||||||
|
iterator.next(); // Move to next entry
|
||||||
|
iterator.remove(); // Remove the entry
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new player head ItemStack
|
||||||
|
ItemStack skull = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||||
|
SkullMeta skullMeta = (SkullMeta) skull.getItemMeta();
|
||||||
|
|
||||||
|
// Create a new PlayerProfile
|
||||||
|
UUID uuid = UUID.randomUUID(); // Unique ID for the profile
|
||||||
|
PlayerProfile profile = Bukkit.createPlayerProfile(uuid);
|
||||||
|
|
||||||
|
// Decode the base64 texture and extract the texture URL
|
||||||
|
String decodedTexture = extractSkinUrlFromBase64(base64Texture);
|
||||||
|
|
||||||
|
// Set the skin URL using PlayerTextures
|
||||||
|
PlayerTextures textures = profile.getTextures();
|
||||||
|
try {
|
||||||
|
// Using a URL object for the texture
|
||||||
|
textures.setSkin(new URL(decodedTexture));
|
||||||
|
} catch (MalformedURLException ignore) {} // Base64 has no URL, ignore
|
||||||
|
|
||||||
|
// Apply the textures to the profile
|
||||||
|
profile.setTextures(textures);
|
||||||
|
|
||||||
|
// Apply the PlayerProfile to the SkullMeta
|
||||||
|
skullMeta.setOwnerProfile(profile);
|
||||||
|
|
||||||
|
// Set the modified SkullMeta back to the ItemStack
|
||||||
|
skull.setItemMeta(skullMeta);
|
||||||
|
|
||||||
|
savedCustomHeads.put(base64Texture, skull);
|
||||||
|
return skull;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New method to get a player head by player name
|
||||||
|
public ItemStack getPlayerHead(String playerName) {
|
||||||
|
//check for any saved heads
|
||||||
|
if(savedCustomHeads.containsKey(playerName)) {
|
||||||
|
return savedCustomHeads.get(playerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//clear cached textures list until length limit is reached
|
||||||
|
Iterator<Map.Entry<String, ItemStack>> iterator = savedCustomHeads.entrySet().iterator();
|
||||||
|
while (savedCustomHeads.size() > 2000 && iterator.hasNext()) {
|
||||||
|
iterator.next(); // Move to next entry
|
||||||
|
iterator.remove(); // Remove the entry
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new player head ItemStack
|
||||||
|
ItemStack skull = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||||
|
SkullMeta skullMeta = (SkullMeta) skull.getItemMeta();
|
||||||
|
|
||||||
|
// Get the OfflinePlayer object for the provided player name
|
||||||
|
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName);
|
||||||
|
|
||||||
|
// Create a PlayerProfile from the player's UUID
|
||||||
|
UUID playerUUID = offlinePlayer.getUniqueId();
|
||||||
|
PlayerProfile profile = Bukkit.createPlayerProfile(playerUUID);
|
||||||
|
|
||||||
|
// Apply the PlayerProfile to the SkullMeta
|
||||||
|
skullMeta.setOwnerProfile(profile);
|
||||||
|
|
||||||
|
// Set the modified SkullMeta back to the ItemStack
|
||||||
|
skull.setItemMeta(skullMeta);
|
||||||
|
|
||||||
|
savedCustomHeads.put(playerName, skull);
|
||||||
|
return skull;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to extract the skin URL from the base64 texture
|
||||||
|
private String extractSkinUrlFromBase64(String base64Texture) {
|
||||||
|
// Decode the base64 string
|
||||||
|
byte[] decodedBytes = Base64.getDecoder().decode(base64Texture);
|
||||||
|
String decodedString = new String(decodedBytes);
|
||||||
|
|
||||||
|
// Parse the decoded string as JSON
|
||||||
|
JsonObject jsonObject = JsonParser.parseString(decodedString).getAsJsonObject();
|
||||||
|
|
||||||
|
// Navigate to "textures" -> "SKIN" -> "url"
|
||||||
|
JsonObject textures = jsonObject.getAsJsonObject("textures");
|
||||||
|
JsonObject skin = textures.getAsJsonObject("SKIN");
|
||||||
|
|
||||||
|
// Return the URL if it exists
|
||||||
|
return skin.has("url") ? skin.get("url").getAsString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package me.rockyhawk.commandpanels.classresources.placeholders;
|
package me.rockyhawk.commandpanels.classresources.placeholders;
|
||||||
|
|
||||||
import com.earth2me.essentials.Essentials;
|
import com.earth2me.essentials.Essentials;
|
||||||
import me.realized.tokenmanager.api.TokenManager;
|
|
||||||
import me.rockyhawk.commandpanels.CommandPanels;
|
import me.rockyhawk.commandpanels.CommandPanels;
|
||||||
import me.rockyhawk.commandpanels.api.Panel;
|
import me.rockyhawk.commandpanels.api.Panel;
|
||||||
import me.rockyhawk.commandpanels.ioclasses.legacy.MinecraftVersions;
|
import me.rockyhawk.commandpanels.ioclasses.legacy.MinecraftVersions;
|
||||||
@ -462,13 +461,6 @@ public class Placeholders {
|
|||||||
} catch (Exception place) {
|
} catch (Exception place) {
|
||||||
//skip
|
//skip
|
||||||
}
|
}
|
||||||
if (plugin.getServer().getPluginManager().isPluginEnabled("TokenManager")) {
|
|
||||||
TokenManager api = (TokenManager) Bukkit.getServer().getPluginManager().getPlugin("TokenManager");
|
|
||||||
assert api != null;
|
|
||||||
if(identifier.equals("tokenmanager-balance")) {
|
|
||||||
return Long.toString(api.getTokens(p).orElse(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//end nodes with PlaceHolders
|
//end nodes with PlaceHolders
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -54,9 +54,6 @@ public class Commandpanelsreload implements CommandExecutor {
|
|||||||
registerCommands();
|
registerCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
//pre-cache any player head textures from panels will be reloaded
|
|
||||||
plugin.customHeads.savedCustomHeads.clear();
|
|
||||||
|
|
||||||
sender.sendMessage(plugin.tex.colour(plugin.tag + plugin.config.getString("config.format.reload")));
|
sender.sendMessage(plugin.tex.colour(plugin.tag + plugin.config.getString("config.format.reload")));
|
||||||
}else{
|
}else{
|
||||||
sender.sendMessage(plugin.tex.colour(plugin.tag + plugin.config.getString("config.format.perms")));
|
sender.sendMessage(plugin.tex.colour(plugin.tag + plugin.config.getString("config.format.perms")));
|
||||||
|
@ -52,7 +52,7 @@ public class CommandRunner {
|
|||||||
CommandTagEvent tags = new CommandTagEvent(plugin, panel, position, p, commandRAW);
|
CommandTagEvent tags = new CommandTagEvent(plugin, panel, position, p, commandRAW);
|
||||||
Bukkit.getPluginManager().callEvent(tags);
|
Bukkit.getPluginManager().callEvent(tags);
|
||||||
if (!tags.commandTagUsed) {
|
if (!tags.commandTagUsed) {
|
||||||
Bukkit.dispatchCommand(p, plugin.tex.placeholders(panel, position, p, commandRAW.trim()));
|
Bukkit.dispatchCommand(p, plugin.tex.attachPlaceholders(panel, position, p, commandRAW.trim()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package me.rockyhawk.commandpanels.commandtags;
|
|||||||
import me.rockyhawk.commandpanels.CommandPanels;
|
import me.rockyhawk.commandpanels.CommandPanels;
|
||||||
import me.rockyhawk.commandpanels.api.Panel;
|
import me.rockyhawk.commandpanels.api.Panel;
|
||||||
import me.rockyhawk.commandpanels.openpanelsmanager.PanelPosition;
|
import me.rockyhawk.commandpanels.openpanelsmanager.PanelPosition;
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
@ -40,8 +39,8 @@ public class CommandTagEvent extends Event {
|
|||||||
if(doApiPlaceholders) {
|
if(doApiPlaceholders) {
|
||||||
this.args = plugin.tex.attachPlaceholders(panel1,pos, player, split[1].trim()).split("\\s");
|
this.args = plugin.tex.attachPlaceholders(panel1,pos, player, split[1].trim()).split("\\s");
|
||||||
}else{
|
}else{
|
||||||
this.args = ChatColor.translateAlternateColorCodes('&',plugin.placeholders.setPlaceholders(panel, pos, p,split[1].trim(),false)).split("\\s");
|
this.args = plugin.placeholders.setPlaceholders(panel, pos, p,split[1].trim(),false).split("\\s");
|
||||||
this.args = ChatColor.translateAlternateColorCodes('&',plugin.placeholders.setPlaceholders(panel, pos, p,split[1].trim(),true)).split("\\s");
|
this.args = plugin.placeholders.setPlaceholders(panel, pos, p,split[1].trim(),true).split("\\s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
package me.rockyhawk.commandpanels.commandtags.paywalls;
|
package me.rockyhawk.commandpanels.commandtags.paywalls;
|
||||||
|
|
||||||
import me.realized.tokenmanager.api.TokenManager;
|
|
||||||
import me.rockyhawk.commandpanels.CommandPanels;
|
import me.rockyhawk.commandpanels.CommandPanels;
|
||||||
import me.rockyhawk.commandpanels.commandtags.PaywallEvent;
|
import me.rockyhawk.commandpanels.commandtags.PaywallEvent;
|
||||||
import me.rockyhawk.commandpanels.commandtags.PaywallOutput;
|
import me.rockyhawk.commandpanels.commandtags.PaywallOutput;
|
||||||
@ -10,10 +8,13 @@ import org.bukkit.ChatColor;
|
|||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.OptionalLong;
|
||||||
|
|
||||||
public class TokenPaywall implements Listener {
|
public class TokenPaywall implements Listener {
|
||||||
CommandPanels plugin;
|
private final CommandPanels plugin;
|
||||||
|
|
||||||
public TokenPaywall(CommandPanels pl) {
|
public TokenPaywall(CommandPanels pl) {
|
||||||
this.plugin = pl;
|
this.plugin = pl;
|
||||||
}
|
}
|
||||||
@ -24,12 +25,27 @@ public class TokenPaywall implements Listener {
|
|||||||
// if player uses tokenpaywall= [price]
|
// if player uses tokenpaywall= [price]
|
||||||
try {
|
try {
|
||||||
if (plugin.getServer().getPluginManager().isPluginEnabled("TokenManager")) {
|
if (plugin.getServer().getPluginManager().isPluginEnabled("TokenManager")) {
|
||||||
final TokenManager api = (TokenManager) Bukkit.getPluginManager().getPlugin("TokenManager");
|
// Using reflection in this method as TokenManager has issues with Maven due to the Jitpack dependency
|
||||||
assert api != null;
|
Object api = Bukkit.getPluginManager().getPlugin("TokenManager");
|
||||||
int balance = Integer.parseInt(Long.toString(api.getTokens(e.p).orElse(0)));
|
if (api != null) {
|
||||||
|
// Use reflection to access the getTokens and removeTokens methods
|
||||||
|
Method getTokensMethod = api.getClass().getMethod("getTokens", org.bukkit.entity.Player.class);
|
||||||
|
Method removeTokensMethod = api.getClass().getMethod("removeTokens", org.bukkit.entity.Player.class, long.class);
|
||||||
|
|
||||||
|
// Call getTokens
|
||||||
|
Object result = getTokensMethod.invoke(api, e.p);
|
||||||
|
long balance;
|
||||||
|
|
||||||
|
if (result instanceof OptionalLong) {
|
||||||
|
balance = ((OptionalLong) result).orElse(0L);
|
||||||
|
} else {
|
||||||
|
balance = 0L;
|
||||||
|
}
|
||||||
|
|
||||||
if (balance >= Double.parseDouble(e.args[0])) {
|
if (balance >= Double.parseDouble(e.args[0])) {
|
||||||
if (e.doDelete) {
|
if (e.doDelete) {
|
||||||
api.removeTokens(e.p, Long.parseLong(e.args[0]));
|
// Call removeTokens
|
||||||
|
removeTokensMethod.invoke(api, e.p, Long.parseLong(e.args[0]));
|
||||||
}
|
}
|
||||||
// if the message is empty don't send
|
// if the message is empty don't send
|
||||||
if (plugin.config.getBoolean("purchase.tokens.enable") && e.doDelete) {
|
if (plugin.config.getBoolean("purchase.tokens.enable") && e.doDelete) {
|
||||||
@ -47,8 +63,12 @@ public class TokenPaywall implements Listener {
|
|||||||
plugin.tex.sendString(e.p, plugin.tag + ChatColor.RED + "Needs TokenManager to work!");
|
plugin.tex.sendString(e.p, plugin.tag + ChatColor.RED + "Needs TokenManager to work!");
|
||||||
e.PAYWALL_OUTPUT = PaywallOutput.Blocked;
|
e.PAYWALL_OUTPUT = PaywallOutput.Blocked;
|
||||||
}
|
}
|
||||||
} catch (Exception buyc) {
|
} else {
|
||||||
plugin.debug(buyc, e.p);
|
plugin.tex.sendString(e.p, plugin.tag + ChatColor.RED + "Needs TokenManager to work!");
|
||||||
|
e.PAYWALL_OUTPUT = PaywallOutput.Blocked;
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
plugin.debug(ex, e.p);
|
||||||
plugin.tex.sendString(e.p, plugin.tag + plugin.config.getString("config.format.error") + " " + "commands: " + e.name);
|
plugin.tex.sendString(e.p, plugin.tag + plugin.config.getString("config.format.error") + " " + "commands: " + e.name);
|
||||||
e.PAYWALL_OUTPUT = PaywallOutput.Blocked;
|
e.PAYWALL_OUTPUT = PaywallOutput.Blocked;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package me.rockyhawk.commandpanels.openpanelsmanager;
|
|||||||
import me.rockyhawk.commandpanels.CommandPanels;
|
import me.rockyhawk.commandpanels.CommandPanels;
|
||||||
import me.rockyhawk.commandpanels.api.Panel;
|
import me.rockyhawk.commandpanels.api.Panel;
|
||||||
import me.rockyhawk.commandpanels.api.PanelClosedEvent;
|
import me.rockyhawk.commandpanels.api.PanelClosedEvent;
|
||||||
import me.rockyhawk.commandpanels.classresources.customheads.SavedCustomHead;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -15,8 +14,6 @@ import org.bukkit.event.inventory.InventoryCloseEvent;
|
|||||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class UtilsPanelsLoader implements Listener {
|
public class UtilsPanelsLoader implements Listener {
|
||||||
@ -74,13 +71,6 @@ public class UtilsPanelsLoader implements Listener {
|
|||||||
|
|
||||||
//close panels and run commands for Top panel
|
//close panels and run commands for Top panel
|
||||||
plugin.openPanels.closePanelForLoader(e.getPlayer().getName(),PanelPosition.Top);
|
plugin.openPanels.closePanelForLoader(e.getPlayer().getName(),PanelPosition.Top);
|
||||||
|
|
||||||
//clear cached textures list until length limit is reached
|
|
||||||
Iterator<Map.Entry<String, SavedCustomHead>> iterator = plugin.customHeads.savedCustomHeads.entrySet().iterator();
|
|
||||||
while (plugin.customHeads.savedCustomHeads.size() > 2000 && iterator.hasNext()) {
|
|
||||||
iterator.next(); // Move to next entry
|
|
||||||
iterator.remove(); // Remove the entry
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
Loading…
Reference in New Issue
Block a user