mirror of
https://github.com/rockyhawk64/CommandPanels.git
synced 2025-11-18 07:14:17 +01:00
started converter and improved generator
This commit is contained in:
parent
2309348f73
commit
29916699d0
@ -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" />
|
||||
|
||||
@ -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" />
|
||||
|
||||
@ -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
|
||||
223
src/me/rockyhawk/commandpanels/Converter.java
Normal file
223
src/me/rockyhawk/commandpanels/Converter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user