This commit is contained in:
rockyhawk64 2024-08-07 17:58:28 +10:00
parent 6f2a39d613
commit a27360f8ff
10 changed files with 167 additions and 47 deletions

View File

@ -1,4 +1,4 @@
version: 3.21.3.2
version: 3.21.3.3
main: me.rockyhawk.commandpanels.CommandPanels
name: CommandPanels
author: RockyHawk

View File

@ -1,6 +1,7 @@
package me.rockyhawk.commandpanels;
import com.bencodez.votingplugin.VotingPluginHooks;
import com.google.common.collect.ImmutableMultimap;
import io.lumine.mythic.lib.api.item.NBTItem;
import me.rockyhawk.commandpanels.api.CommandPanelsAPI;
import me.rockyhawk.commandpanels.api.Panel;
@ -36,6 +37,7 @@ import me.rockyhawk.commandpanels.ioclasses.nbt.NBTManager;
import me.rockyhawk.commandpanels.ioclasses.legacy.LegacyVersion;
import me.rockyhawk.commandpanels.ioclasses.legacy.MinecraftVersions;
import me.rockyhawk.commandpanels.ioclasses.legacy.PlayerHeads;
import me.rockyhawk.commandpanels.ioclasses.potions.ClassicPotionData;
import me.rockyhawk.commandpanels.ioclasses.potions.LegacyPotionData;
import me.rockyhawk.commandpanels.openpanelsmanager.*;
import me.rockyhawk.commandpanels.openwithitem.HotbarItemLoader;
@ -104,6 +106,7 @@ public class CommandPanels extends JavaPlugin{
public GetCustomHeads customHeads = new GetCustomHeads(this);
public Updater updater = new Updater(this);
public PlayerHeads getHeads = new PlayerHeads(this);
public ClassicPotionData classicPotion = new ClassicPotionData(this);
public LegacyPotionData legacyPotion = new LegacyPotionData(this);
public LegacyVersion legacy = new LegacyVersion(this);
@ -357,7 +360,7 @@ public class CommandPanels extends JavaPlugin{
}
//setAttributeModifiers was added into 1.14 api
if(legacy.MAJOR_VERSION.greaterThanOrEqualTo(MinecraftVersions.v1_14)){
renamedMeta.setAttributeModifiers(null);
renamedMeta.setAttributeModifiers(ImmutableMultimap.of());
}
}
if (customName != null) {

View File

@ -283,7 +283,11 @@ public class ItemCreation {
//potion legacy or current
if(plugin.legacy.MAJOR_VERSION.lessThanOrEqualTo(MinecraftVersions.v1_19) ||
(plugin.legacy.MAJOR_VERSION == MinecraftVersions.v1_20 && plugin.legacy.MINOR_VERSION <= 4)){
plugin.legacyPotion.applyPotionEffect(p,s,effectType);
if(plugin.legacy.MAJOR_VERSION.equals(MinecraftVersions.v1_8)){
plugin.classicPotion.applyPotionEffect(p, s, effectType);
}else {
plugin.legacyPotion.applyPotionEffect(p, s, effectType);
}
}else{
try {
PotionMeta potionMeta = (PotionMeta)s.getItemMeta();
@ -299,6 +303,18 @@ public class ItemCreation {
}
}
}
if(itemSection.contains("potion-color")){
if(plugin.legacy.MAJOR_VERSION.greaterThanOrEqualTo(MinecraftVersions.v1_11)){
String[] rgb = Objects.requireNonNull(itemSection.getString("potion-color")).split(",");
Color color = Color.fromRGB(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
PotionMeta potionMeta = (PotionMeta)s.getItemMeta();
assert potionMeta != null;
potionMeta.setColor(color);
s.setItemMeta(potionMeta);
}
}
if (itemSection.contains("damage")) {
//change the damage amount (placeholders accepted)
//if the damage is not unbreakable and should be a value

View File

@ -26,8 +26,7 @@ public class GetCustomHeads {
this.plugin = pl;
}
//will not go above 2000 elements in the list
public HashSet<SavedCustomHead> savedCustomHeads = new HashSet<>();
public HashMap<String, SavedCustomHead> savedCustomHeads = new HashMap<>();
public String getHeadBase64(ItemStack head) {
if (plugin.getHeads.ifSkullOrHead(head.getType().toString()) && head.hasItemMeta()) {
@ -75,10 +74,13 @@ public class GetCustomHeads {
}
//get texture if already cached
for(SavedCustomHead head : savedCustomHeads){
if(head.playerName == null) {continue;}
if(head.playerName.equals(name)){
return head.headItem;
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
}
}
@ -96,7 +98,7 @@ public class GetCustomHeads {
if(plugin.debug.consoleDebug){
plugin.getServer().getConsoleSender().sendMessage(plugin.tex.colour(plugin.tag +
ChatColor.WHITE +
"Attempting to Download & Cache Head Texture for " + name));
"Download & Cache Head Texture for " + name));
}
// Fetch the player UUID from the Mojang API
@ -121,27 +123,40 @@ public class GetCustomHeads {
// Once the API call is finished, update the ItemStack on the main thread
Bukkit.getScheduler().runTask(plugin, () -> {
itemStack.setItemMeta(getCustomHead(value).getItemMeta());
savedCustomHeads.add(new SavedCustomHead(itemStack, value, name));
itemStack.setItemMeta(getCustomHead(name, value).getItemMeta());
savedCustomHeads.put(name, new SavedCustomHead(itemStack, value, true));
});
} catch (Exception ignore) {
// Ignore as errors should be skipped and no need to show in console
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) {
//check for any saved heads
for(SavedCustomHead head : savedCustomHeads){
if(head.base64.equals(b64stringtexture)){
return head.headItem;
}
}
//get head from base64
GameProfile profile = new GameProfile(UUID.randomUUID(), "");
PropertyMap propertyMap = profile.getProperties();

View File

@ -4,17 +4,14 @@ import org.bukkit.inventory.ItemStack;
public class SavedCustomHead {
public String base64;
public String playerName = null;
public ItemStack headItem;
public boolean isValid; // true if the head was successfully fetched, false otherwise
public long lastAttempt; // timestamp of the last attempt
public SavedCustomHead(ItemStack head, String base64value) {
base64 = base64value;
headItem = head;
}
public SavedCustomHead(ItemStack head, String base64value, String player) {
playerName = player;
public SavedCustomHead(ItemStack head, String base64value, boolean isValidAttempt) {
base64 = base64value;
headItem = head;
isValid = isValidAttempt;
lastAttempt = System.currentTimeMillis();
}
}

View File

@ -8,8 +8,8 @@ import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Objects;
import java.util.Set;
public class ItemTags implements Listener {
@ -102,21 +102,19 @@ public class ItemTags implements Listener {
e.commandTagUsed();
//if player uses setcustomdata= [slot] [position] [data] it will change the custom model data of the item
PanelPosition position = PanelPosition.valueOf(e.args[1]);
ItemStack EditItem;
ItemStack editItem;
if(position == PanelPosition.Top) {
EditItem = e.p.getOpenInventory().getTopInventory().getItem(Integer.parseInt(e.args[0]));
editItem = e.p.getOpenInventory().getTopInventory().getItem(Integer.parseInt(e.args[0]));
}else if(position == PanelPosition.Middle) {
EditItem = e.p.getInventory().getItem(Integer.parseInt(e.args[0])+9);
editItem = e.p.getInventory().getItem(Integer.parseInt(e.args[0])+9);
}else{
EditItem = e.p.getInventory().getItem(Integer.parseInt(e.args[0]));
editItem = e.p.getInventory().getItem(Integer.parseInt(e.args[0]));
}
assert EditItem != null;
try{
if(EditItem.hasItemMeta()){
Objects.requireNonNull(EditItem.getItemMeta()).setCustomModelData(Integer.valueOf(e.args[2]));
}
ItemMeta itemMeta = editItem.getItemMeta();
itemMeta.setCustomModelData(Integer.valueOf(e.args[2]));
editItem.setItemMeta(itemMeta);
} catch (Exception err){
plugin.debug(err,e.p);
}

View File

@ -64,8 +64,12 @@ public class OpenFloodgateGUI implements Listener {
form.validResultHandler((SimpleFormResponse response) -> {
int clickedButtonId = response.clickedButtonId();
String configKey = buttonCommands.get(clickedButtonId);
if(fgPanel.contains(configKey + ".commands")) {
plugin.commandRunner.runCommands(e.getPanel(), PanelPosition.Top, e.getPlayer(), fgPanel.getStringList(configKey + ".commands"), null);
String section = plugin.has.hasSection(e.getPanel(), PanelPosition.Top, fgPanel.getConfigurationSection(configKey), e.getPlayer());
ConfigurationSection buttonConfig = fgPanel.getConfigurationSection(configKey + section);
if(buttonConfig.contains("commands")) {
plugin.commandRunner.runCommands(e.getPanel(), PanelPosition.Top, e.getPlayer(), buttonConfig.getStringList("commands"), null);
}
});
@ -77,7 +81,8 @@ public class OpenFloodgateGUI implements Listener {
.filter(key -> key.matches("\\d+"))
.sorted(Comparator.comparingInt(Integer::parseInt)) // Ensure numeric sorting
.map(key -> {
ConfigurationSection buttonConfig = fgPanel.getConfigurationSection(key);
String section = plugin.has.hasSection(panel, PanelPosition.Top, fgPanel.getConfigurationSection(key), p);
ConfigurationSection buttonConfig = fgPanel.getConfigurationSection(key + section);
if (buttonConfig == null) return null;
String buttonContent = plugin.tex.placeholders(panel, null, p, buttonConfig.getString("text"));
@ -101,7 +106,9 @@ public class OpenFloodgateGUI implements Listener {
List<String> commandsOrder = new ArrayList<>();
fgPanel.getKeys(false).forEach(key -> {
if (key.matches("\\d+")) {
ConfigurationSection fieldConfig = fgPanel.getConfigurationSection(key);
String section = plugin.has.hasSection(e.getPanel(), e.getPosition(), fgPanel.getConfigurationSection(key), e.getPlayer());
ConfigurationSection fieldConfig = fgPanel.getConfigurationSection(key + section);
try {
String type = "toggle";
if(fieldConfig.contains("type")) {
@ -145,10 +152,13 @@ public class OpenFloodgateGUI implements Listener {
if (!response.hasNext()) {
break; // Safety check to prevent NoSuchElementException
}
if(fgPanel.contains(configKey + ".commands")) {
String section = plugin.has.hasSection(e.getPanel(), e.getPosition(), fgPanel.getConfigurationSection(configKey), e.getPlayer());
ConfigurationSection fieldConfig = fgPanel.getConfigurationSection(configKey + section);
if(fieldConfig.contains("commands")) {
Object fieldValue = response.next(); // Retrieve the next response value
String value = String.valueOf(fieldValue); // Convert the field value to String
List<String> commands = fgPanel.getStringList(configKey + ".commands"); // Retrieve commands for this field
List<String> commands = fieldConfig.getStringList("commands"); // Retrieve commands for this field
List<String> processedCommands = new ArrayList<>();
for (String command : commands) {
processedCommands.add(command.replaceAll("%cp-input%", value)); // Replace the placeholder in each command

View File

@ -0,0 +1,77 @@
package me.rockyhawk.commandpanels.ioclasses.potions;
import me.rockyhawk.commandpanels.CommandPanels;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ClassicPotionData {
private CommandPanels plugin;
public ClassicPotionData(CommandPanels plugin) {
this.plugin = plugin;
}
public void applyPotionEffect(Player p, ItemStack item, String[] effectType) {
try {
if (item == null || item.getType() != org.bukkit.Material.POTION) {
p.sendMessage(plugin.tex.colour(plugin.tag + ChatColor.RED + "Item is not a potion."));
return;
}
Class<?> potionClass = Class.forName("org.bukkit.potion.Potion");
Class<?> potionTypeClass = Class.forName("org.bukkit.potion.PotionType");
Object potionType = Enum.valueOf((Class<Enum>) potionTypeClass, effectType[0].toUpperCase());
Constructor<?> potionConstructor = potionClass.getConstructor(potionTypeClass, int.class);
Object potion = potionConstructor.newInstance(potionType, effectType.length >= 3 && effectType[2].equalsIgnoreCase("true") ? 2 : 1);
Method setSplashMethod = potionClass.getMethod("setSplash", boolean.class);
boolean isSplash = (item.getDurability() & 0x4000) != 0; // Checks if the durability indicates it's a splash potion
setSplashMethod.invoke(potion, isSplash);
try {
Method setHasExtendedDurationMethod = potionClass.getMethod("setHasExtendedDuration", boolean.class);
setHasExtendedDurationMethod.invoke(potion, effectType.length >= 2 && effectType[1].equalsIgnoreCase("true"));
}catch (Exception ignore){
//ignore as some potions like instant potions cannot be extended
}
Method applyMethod = potionClass.getMethod("apply", ItemStack.class);
applyMethod.invoke(potion, item);
} catch (Exception er) {
plugin.debug(er, p);
p.sendMessage(plugin.tex.colour(plugin.tag + ChatColor.RED + "Incorrect potion type or format."));
}
}
public String retrievePotionData(ItemStack item) {
try {
if (item == null || item.getType() != org.bukkit.Material.POTION) {
return "Item is not a potion";
}
Class<?> potionClass = Class.forName("org.bukkit.potion.Potion");
Method fromItemStackMethod = potionClass.getMethod("fromItemStack", ItemStack.class);
Object potion = fromItemStackMethod.invoke(null, item);
Method getTypeMethod = potionClass.getMethod("getType");
Method isExtendedMethod = potionClass.getMethod("hasExtendedDuration");
Method isUpgradedMethod = potionClass.getMethod("getLevel");
Object potionType = getTypeMethod.invoke(potion);
boolean extended = (Boolean) isExtendedMethod.invoke(potion);
boolean upgraded = ((Integer) isUpgradedMethod.invoke(potion)) > 1;
boolean isSplash = (item.getDurability() & 0x4000) != 0; // Checks if the durability indicates it's a splash potion
return potionType.toString() + " " + extended + " " + upgraded + " Splash:" + isSplash;
} catch (Exception e) {
plugin.debug(e, null);
return "Failed to retrieve potion data";
}
}
}

View File

@ -10,6 +10,9 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class LegacyPotionData {
/*
* To be used in Minecraft 1.9 to 1.20.4
* */
private CommandPanels plugin;
public LegacyPotionData(CommandPanels plugin) {

View File

@ -16,6 +16,7 @@ import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
public class UtilsPanelsLoader implements Listener {
@ -75,10 +76,10 @@ public class UtilsPanelsLoader implements Listener {
plugin.openPanels.closePanelForLoader(e.getPlayer().getName(),PanelPosition.Top);
//clear cached textures list until length limit is reached
Iterator<SavedCustomHead> iterator = plugin.customHeads.savedCustomHeads.iterator();
Iterator<Map.Entry<String, SavedCustomHead>> iterator = plugin.customHeads.savedCustomHeads.entrySet().iterator();
while (plugin.customHeads.savedCustomHeads.size() > 2000 && iterator.hasNext()) {
iterator.next(); // Move to next element
iterator.remove(); // Remove the element
iterator.next(); // Move to next entry
iterator.remove(); // Remove the entry
}
}