started converter and improved generator

This commit is contained in:
rockyhawk64 2025-07-14 17:02:52 +10:00
parent 2309348f73
commit 29916699d0
19 changed files with 561 additions and 104 deletions

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/panels" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/resource" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/resource_editor" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/resource_example" charset="UTF-8" />

View File

@ -71,6 +71,11 @@
<option name="name" value="Oraxen Repository" />
<option name="url" value="https://repo.oraxen.com/releases" />
</remote-repository>
<remote-repository>
<option name="id" value="papermc" />
<option name="name" value="papermc" />
<option name="url" value="https://repo.papermc.io/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="jitpack-repo" />
<option name="name" value="jitpack-repo" />
@ -106,6 +111,11 @@
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="matteodev" />
<option name="name" value="matteodev" />
<option name="url" value="https://maven.devs.beer/" />
</remote-repository>
<remote-repository>
<option name="id" value="minecraft-repo" />
<option name="name" value="minecraft-repo" />

View File

@ -25,8 +25,10 @@ permissions:
commandpanels.command.data:
default: op
commandpanels.command.open:
default: true
default: op
commandpanels.command.open.other:
default: op
commandpanels.command.help:
default: true
commandpanels.command.convert:
default: true

View File

@ -0,0 +1,223 @@
package me.rockyhawk.commandpanels;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class Converter {
private final Context ctx;
public Converter(Context ctx) {
this.ctx = ctx;
}
// CONVERTER For CommandPanels v3 to v4
// Will be removed at some point when v4 is further adopted
// Does not include 1:! conversions as the two configs are incompatible in many ways
public void convertPanels(CommandSender sender) {
File oldPanelsDir = new File(ctx.plugin.getDataFolder(), "old_panels"); // e.g. plugins/CommandPanels/old_panels
if (!oldPanelsDir.exists()) {
ctx.text.sendError(sender, "Old panels directory not found: " + oldPanelsDir.getPath());
return;
}
File[] files = oldPanelsDir.listFiles((dir, name) -> name.endsWith(".yml"));
if (files == null || files.length == 0) {
ctx.text.sendInfo(sender, "No old panel files found.");
return;
}
for (File file : files) {
try {
YamlConfiguration oldConfig = YamlConfiguration.loadConfiguration(file);
ConfigurationSection panelsSection = oldConfig.getConfigurationSection("panels");
if (panelsSection == null) {
ctx.text.sendError(sender, "No panels section in file: " + file.getName());
continue;
}
for (String panelName : panelsSection.getKeys(false)) {
ConfigurationSection oldPanel = panelsSection.getConfigurationSection(panelName);
if (oldPanel == null) continue;
Map<String, Object> newPanel = convertPanel(panelName, oldPanel);
File outFile = new File(ctx.plugin.folder, panelName + ".yml");
YamlConfiguration newYaml = new YamlConfiguration();
for (Map.Entry<String, Object> entry : newPanel.entrySet()) {
newYaml.set(entry.getKey(), entry.getValue());
}
newYaml.save(outFile);
ctx.text.sendInfo(sender, "Converted panel: " + panelName + " -> " + outFile.getName());
}
} catch (IOException ex) {
ctx.text.sendError(sender, "Failed to convert file: " + file.getName());
}
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> convertPanel(String panelName, ConfigurationSection oldPanel) {
Map<String, Object> newPanel = new LinkedHashMap<>();
newPanel.put("title", oldPanel.getString("title", "&fPanel"));
newPanel.put("type", "inventory"); // hardcoded type unless we detect others
newPanel.put("rows", oldPanel.getInt("rows", 6));
// Commands from "commands" and "commands-on-open"
List<String> openCommands = oldPanel.getStringList("commands-on-open");
List<String> baseCommands = oldPanel.getStringList("commands");
String newOpenCommand = null;
if (!baseCommands.isEmpty()) {
newOpenCommand = baseCommands.get(0); // Only use the first base command
}
List<String> newOpenCommands = new ArrayList<>(openCommands); // Add commands
newPanel.put("command", newOpenCommand);
newPanel.put("commands", newOpenCommands);
// Create layout and items map
Map<String, List<String>> layout = new LinkedHashMap<>();
Map<String, Object> items = new LinkedHashMap<>();
// Add custom items (named reusable entries)
if (oldPanel.isConfigurationSection("custom-item")) {
ConfigurationSection customItems = oldPanel.getConfigurationSection("custom-item");
for (String itemKey : customItems.getKeys(false)) {
items.put(itemKey, convertItem(customItems.getConfigurationSection(itemKey)));
}
}
// Convert item slots to layout
ConfigurationSection itemSection = oldPanel.getConfigurationSection("item");
if (itemSection != null) {
for (String slotKey : itemSection.getKeys(false)) {
ConfigurationSection itemConfig = itemSection.getConfigurationSection(slotKey);
String itemId = panelName + "_slot_" + slotKey;
Map<String, Object> convertedItem = convertItem(itemConfig);
if (itemConfig.contains("commands") || hasNestedConditions(itemConfig)) {
// Move commands into 'actions'
List<String> cmds = itemConfig.getStringList("commands");
if (!cmds.isEmpty()) {
Map<String, Object> leftClick = new HashMap<>();
List<String> cmdList = new ArrayList<>();
for (String cmd : cmds) {
cmdList.add("[msg] " + cmd);
}
leftClick.put("commands", cmdList);
convertedItem.put("actions", leftClick);
}
}
// Handle nested "has0", "has1" logic
List<Map<String, Object>> logicVariants = extractConditionVariants(itemConfig);
if (!logicVariants.isEmpty()) {
// Add base item as default (without conditions)
items.put(itemId + "_base", convertedItem);
layout.put(slotKey, new ArrayList<>(Collections.singletonList(itemId + "_base")));
int i = 0;
for (Map<String, Object> variant : logicVariants) {
String variantId = itemId + "_cond_" + i;
items.put(variantId, variant);
layout.get(slotKey).add(0, variantId); // priority first
i++;
}
} else {
items.put(itemId, convertedItem);
layout.put(slotKey, new ArrayList<>(Collections.singletonList(itemId)));
}
}
}
newPanel.put("layout", layout);
newPanel.put("items", items);
return newPanel;
}
private Map<String, Object> convertItem(ConfigurationSection itemConfig) {
Map<String, Object> item = new LinkedHashMap<>();
if (itemConfig == null) return item;
for (String key : itemConfig.getKeys(false)) {
Object value = itemConfig.get(key);
switch (key) {
case "commands":
// Handled separately in layout
break;
case "name":
case "material":
case "lore":
case "enchanted":
case "damage":
case "stack":
case "leatherarmor":
item.put(key, value);
break;
default:
if (!key.startsWith("has")) {
item.put(key, value);
}
break;
}
}
return item;
}
private boolean hasNestedConditions(ConfigurationSection itemConfig) {
for (String key : itemConfig.getKeys(false)) {
if (key.startsWith("has")) return true;
}
return false;
}
private List<Map<String, Object>> extractConditionVariants(ConfigurationSection itemConfig) {
List<Map<String, Object>> variants = new ArrayList<>();
for (String key : itemConfig.getKeys(false)) {
if (key.startsWith("has")) {
ConfigurationSection conditionSection = itemConfig.getConfigurationSection(key);
if (conditionSection == null) continue;
Map<String, Object> variant = convertItem(conditionSection);
String conditions = "";
for (String subKey : conditionSection.getKeys(false)) {
if (subKey.startsWith("compare")) {
int index = Integer.parseInt(subKey.substring(7));
String valueKey = "value" + index;
if (conditionSection.contains(valueKey)) {
String compare = conditionSection.getString(subKey);
String value = conditionSection.getString(valueKey);
conditions = compare + " $EQUALS " + value;
break;
}
}
}
if (!conditions.isEmpty()) {
variant.put("conditions", conditions);
}
variants.add(variant);
}
}
return variants;
}
}

View File

@ -6,6 +6,7 @@ import me.rockyhawk.commandpanels.session.Panel;
import me.rockyhawk.commandpanels.session.SessionManager;
import me.rockyhawk.commandpanels.session.inventory.InventoryPanel;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
public class InventoryPanelBuilder extends PanelBuilder {
@ -21,7 +22,12 @@ public class InventoryPanelBuilder extends PanelBuilder {
if (!(panel instanceof InventoryPanel)) {
throw new IllegalArgumentException("Expected InventoryPanel, got " + panel.getClass());
}
this.getPlayer().openInventory(panelFactory.createInventory((InventoryPanel) panel, this.getPlayer()));
Inventory panelInv = panelFactory.createInventory((InventoryPanel) panel, this.getPlayer());
if(panelInv.isEmpty()) {
ctx.text.sendError(this.getPlayer(), "Panel must contain at least one item.");
return;
}
this.getPlayer().openInventory(panelInv);
ctx.session.updateSession(this.getPlayer(), panel, openType);
}
}

View File

@ -12,107 +12,86 @@ import org.bukkit.profile.PlayerTextures;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
public class CustomHeads {
//cached itemstacks stored for access
public HashMap<String, ItemStack> savedCustomHeads = new HashMap<>();
//Using the PlayerProfile API for getting custom heads
// Static to remember saved heads across different instances
private static final Map<String, ItemStack> savedCustomHeads = new HashMap<>();
public ItemStack getCustomHead(String base64Texture) {
//check for any saved heads
if(savedCustomHeads.containsKey(base64Texture)) {
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
}
trimCacheIfNeeded();
// 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);
if (decodedTexture == null) return new ItemStack(Material.PLAYER_HEAD);
// Set the skin URL using PlayerTextures
ItemStack skull = new ItemStack(Material.PLAYER_HEAD, 1);
if (!(skull.getItemMeta() instanceof SkullMeta skullMeta)) return skull;
PlayerProfile profile = Bukkit.createPlayerProfile(UUID.randomUUID());
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
} catch (MalformedURLException 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)) {
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
}
trimCacheIfNeeded();
// Create a new player head ItemStack
ItemStack skull = new ItemStack(Material.PLAYER_HEAD, 1);
SkullMeta skullMeta = (SkullMeta) skull.getItemMeta();
if (!(skull.getItemMeta() instanceof SkullMeta skullMeta)) return skull;
// Get the OfflinePlayer object for the provided player name
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName);
PlayerProfile profile = Bukkit.createPlayerProfile(offlinePlayer.getUniqueId());
// 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;
private void trimCacheIfNeeded() {
int CACHE_LIMIT = 2000;
if (savedCustomHeads.size() <= CACHE_LIMIT) return;
Iterator<Map.Entry<String, ItemStack>> iterator = savedCustomHeads.entrySet().iterator();
while (iterator.hasNext() && savedCustomHeads.size() > CACHE_LIMIT) {
iterator.next();
iterator.remove();
}
}
private String extractSkinUrlFromBase64(String base64Texture) {
try {
byte[] decodedBytes = Base64.getDecoder().decode(base64Texture);
String decodedString = new String(decodedBytes, StandardCharsets.UTF_8);
JsonObject jsonObject = JsonParser.parseString(decodedString).getAsJsonObject();
JsonObject textures = jsonObject.getAsJsonObject("textures");
JsonObject skin = textures.getAsJsonObject("SKIN");
return skin.has("url") ? skin.get("url").getAsString() : null;
} catch (Exception e) {
return null;
}
}
}

View File

@ -25,6 +25,7 @@ public class MainCommand implements CommandExecutor {
register(new HelpCommand());
register(new VersionCommand());
register(new DataCommand());
register(new ConvertCommand());
}
private void register(SubCommand subCommand) {

View File

@ -44,6 +44,9 @@ public class TabComplete implements TabCompleter {
if (sender.hasPermission("commandpanels.command.data")) {
output.add("data");
}
if (sender.hasPermission("commandpanels.command.convert")) {
output.add("convert");
}
}
if (args.length == 2) {

View File

@ -0,0 +1,27 @@
package me.rockyhawk.commandpanels.commands.subcommands;
import me.rockyhawk.commandpanels.Context;
import me.rockyhawk.commandpanels.Converter;
import me.rockyhawk.commandpanels.commands.SubCommand;
import org.bukkit.command.CommandSender;
public class ConvertCommand implements SubCommand {
@Override
public String getName() {
return "convert";
}
@Override
public String getPermission() {
return "commandpanels.command.convert";
}
@Override
public boolean execute(Context ctx, CommandSender sender, String[] args) {
Converter converter = new Converter(ctx);
converter.convertPanels(sender);
ctx.fileHandler.reloadPanels();
return true;
}
}

View File

@ -1,7 +1,7 @@
package me.rockyhawk.commandpanels.session.inventory.generator;
import me.rockyhawk.commandpanels.Context;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import me.rockyhawk.commandpanels.session.inventory.generator.resolvers.*;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
@ -10,7 +10,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.File;
@ -21,9 +20,17 @@ public class GenerateManager implements Listener {
private final Context ctx;
private final Set<UUID> generatingPlayers = new HashSet<>();
private final LegacyComponentSerializer legacy = LegacyComponentSerializer.builder()
.character('&')
.build();
private final List<ItemResolver> resolvers = List.of(
new DisplayNameResolver(),
new ItemModelResolver(),
new LoreResolver(),
new EnchantmentsResolver(),
new PotionResolver(),
new DamageResolver(),
new CustomHeadResolver(),
new ArmorColorResolver()
);
public GenerateManager(Context ctx) {
this.ctx = ctx;
@ -35,17 +42,14 @@ public class GenerateManager implements Listener {
if (isInGenerateMode(player) && e.getInventory().getHolder() instanceof BlockState) {
handleInventoryOpen(player, e.getInventory());
e.setCancelled(true);
}
}
/**
* Put player into generate mode for 10 seconds
*/
public void startGenerateMode(Player player) {
generatingPlayers.add(player.getUniqueId());
ctx.text.sendInfo(player, "Generate mode enabled.");
// Schedule a timeout to remove generate mode after 10 seconds
new BukkitRunnable() {
@Override
public void run() {
@ -53,27 +57,18 @@ public class GenerateManager implements Listener {
ctx.text.sendInfo(player, "Generate mode expired.");
}
}
}.runTaskLater(ctx.plugin, 20L * 10); // 20 ticks * 10 = 10 seconds
}.runTaskLater(ctx.plugin, 20L * 10);
}
/**
* Check if a player is in generate mode.
*/
public boolean isInGenerateMode(Player player) {
return generatingPlayers.contains(player.getUniqueId());
}
/**
* Called when player opens an inventory.
* Generates the YAML and removes player from generate mode.
*/
@SuppressWarnings("ConstantConditions")
public void handleInventoryOpen(Player player, Inventory inv) {
if (!isInGenerateMode(player)) return;
generatingPlayers.remove(player.getUniqueId());
String panelName = findAvailablePanelName();
// Prepare YAML configuration
@ -85,6 +80,7 @@ public class GenerateManager implements Listener {
Map<String, List<String>> layout = new LinkedHashMap<>();
Map<String, Object> items = new LinkedHashMap<>();
// Loop through items
for (int i = 0; i < inv.getSize(); i++) {
ItemStack item = inv.getItem(i);
if (item == null || item.getType() == Material.AIR) continue;
@ -92,29 +88,14 @@ public class GenerateManager implements Listener {
String key = ("item_" + item.getType() + "_" + i).toLowerCase();
layout.put(String.valueOf(i), Collections.singletonList(key));
// Create item data for generated file and basic options
Map<String, Object> itemData = new LinkedHashMap<>();
itemData.put("material", item.getType().name());
itemData.put("stack", item.getAmount());
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (meta.hasDisplayName()) itemData.put("name", legacy.serialize(meta.displayName()));
if (meta.hasItemModel()) itemData.put("item-model", meta.getItemModel().toString());
if (meta.hasLore()) {
List<String> serializedLore = meta.lore().stream()
.map(legacy::serialize)
.toList();
itemData.put("lore", serializedLore);
}
if (meta.hasEnchants()) {
List<String> enchantList = new ArrayList<>();
for (var entry : meta.getEnchants().entrySet()) {
String name = entry.getKey().getKey().getKey();
int level = entry.getValue();
enchantList.add(name + " " + level);
}
itemData.put("enchantments", enchantList);
}
// Run resolvers for custom item decorations
for (ItemResolver resolver : resolvers) {
resolver.resolve(item, itemData);
}
items.put(key, itemData);
@ -144,6 +125,6 @@ public class GenerateManager implements Listener {
return panelName;
}
}
return "panel_1"; // fallback, theoretically unreachable
return "panel_1";
}
}

View File

@ -0,0 +1,9 @@
package me.rockyhawk.commandpanels.session.inventory.generator;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
public interface ItemResolver {
void resolve(ItemStack item, Map<String, Object> itemData);
}

View File

@ -0,0 +1,19 @@
package me.rockyhawk.commandpanels.session.inventory.generator.resolvers;
import me.rockyhawk.commandpanels.session.inventory.generator.ItemResolver;
import org.bukkit.Color;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import java.util.Map;
public class ArmorColorResolver implements ItemResolver {
@Override
public void resolve(ItemStack item, Map<String, Object> itemData) {
if (!(item.getItemMeta() instanceof LeatherArmorMeta meta)) return;
Color color = meta.getColor();
itemData.put("leather-armor", color.getRed() + "," + color.getGreen() + "," + color.getBlue());
}
}

View File

@ -0,0 +1,47 @@
package me.rockyhawk.commandpanels.session.inventory.generator.resolvers;
import com.google.gson.JsonObject;
import me.rockyhawk.commandpanels.session.inventory.generator.ItemResolver;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.profile.PlayerProfile;
import org.bukkit.profile.PlayerTextures;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
public class CustomHeadResolver implements ItemResolver {
@Override
public void resolve(ItemStack item, Map<String, Object> itemData) {
if (item.getType() != Material.PLAYER_HEAD) return;
if (!(item.getItemMeta() instanceof SkullMeta meta)) return;
PlayerProfile profile = meta.getOwnerProfile();
if (profile == null) return;
PlayerTextures textures = profile.getTextures();
URL skinUrl = textures.getSkin();
if (skinUrl != null) {
// Construct the texture JSON
JsonObject skin = new JsonObject();
JsonObject texturesObj = new JsonObject();
JsonObject skinObj = new JsonObject();
skinObj.addProperty("url", skinUrl.toString());
texturesObj.add("SKIN", skinObj);
skin.add("textures", texturesObj);
// Convert to Base64
String json = skin.toString();
String base64 = Base64.getEncoder().encodeToString(json.getBytes(StandardCharsets.UTF_8));
// Store in itemData
itemData.put("material", "[head] " + base64);
}
}
}

View File

@ -0,0 +1,20 @@
package me.rockyhawk.commandpanels.session.inventory.generator.resolvers;
import me.rockyhawk.commandpanels.session.inventory.generator.ItemResolver;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import java.util.Map;
public class DamageResolver implements ItemResolver {
@Override
public void resolve(ItemStack item, Map<String, Object> itemData) {
if (!(item.getItemMeta() instanceof Damageable damageMeta)) return;
int damage = damageMeta.getDamage();
if (damage > 0) {
itemData.put("damage", damage);
}
}
}

View File

@ -0,0 +1,20 @@
package me.rockyhawk.commandpanels.session.inventory.generator.resolvers;
import me.rockyhawk.commandpanels.session.inventory.generator.ItemResolver;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Map;
public class DisplayNameResolver implements ItemResolver {
private final LegacyComponentSerializer legacy = LegacyComponentSerializer.builder().character('&').build();
@Override
public void resolve(ItemStack item, Map<String, Object> itemData) {
ItemMeta meta = item.getItemMeta();
if (meta != null && meta.hasDisplayName()) {
itemData.put("name", legacy.serialize(meta.displayName()));
}
}
}

View File

@ -0,0 +1,25 @@
package me.rockyhawk.commandpanels.session.inventory.generator.resolvers;
import me.rockyhawk.commandpanels.session.inventory.generator.ItemResolver;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class EnchantmentsResolver implements ItemResolver {
@Override
public void resolve(ItemStack item, Map<String, Object> itemData) {
ItemMeta meta = item.getItemMeta();
if (meta != null && meta.hasEnchants()) {
List<String> enchantList = new ArrayList<>();
meta.getEnchants().forEach((enchantment, level) -> {
String name = enchantment.getKey().getKey();
enchantList.add(name + " " + level);
});
itemData.put("enchantments", enchantList);
}
}
}

View File

@ -0,0 +1,18 @@
package me.rockyhawk.commandpanels.session.inventory.generator.resolvers;
import me.rockyhawk.commandpanels.session.inventory.generator.ItemResolver;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Map;
public class ItemModelResolver implements ItemResolver {
@Override
public void resolve(ItemStack item, Map<String, Object> itemData) {
ItemMeta meta = item.getItemMeta();
if (meta != null && meta.hasItemModel()) {
itemData.put("item-model", meta.getItemModel().toString());
}
}
}

View File

@ -0,0 +1,25 @@
package me.rockyhawk.commandpanels.session.inventory.generator.resolvers;
import me.rockyhawk.commandpanels.session.inventory.generator.ItemResolver;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class LoreResolver implements ItemResolver {
private final LegacyComponentSerializer legacy = LegacyComponentSerializer.builder().character('&').build();
@Override
public void resolve(ItemStack item, Map<String, Object> itemData) {
ItemMeta meta = item.getItemMeta();
if (meta != null && meta.hasLore()) {
List<String> serializedLore = meta.lore().stream()
.map(legacy::serialize)
.collect(Collectors.toList());
itemData.put("lore", serializedLore);
}
}
}

View File

@ -0,0 +1,41 @@
package me.rockyhawk.commandpanels.session.inventory.generator.resolvers;
import me.rockyhawk.commandpanels.session.inventory.generator.ItemResolver;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.util.*;
public class PotionResolver implements ItemResolver {
private static final Set<Material> POTION_MATERIALS = EnumSet.of(
Material.POTION,
Material.SPLASH_POTION,
Material.LINGERING_POTION,
Material.TIPPED_ARROW
);
@Override
public void resolve(ItemStack item, Map<String, Object> itemData) {
if (!POTION_MATERIALS.contains(item.getType())) return;
if (!(item.getItemMeta() instanceof PotionMeta meta)) return;
if (meta.getBasePotionType() != null) {
itemData.put("potion", meta.getBasePotionType().name());
}
if (meta.hasColor()) {
Color color = meta.getColor();
itemData.put("potion-color", Map.of(
"r", color.getRed(),
"g", color.getGreen(),
"b", color.getBlue()
));
}
}
}