mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-09-28 14:47:30 +02:00
Panel template (#1841)
* Implement basic functionality to read data from template panels. Create TemplateReader class that has static method which generates a PanelTemplateRecord. This record contains every necessary information from user created template file so everyone could use it to generate a functional panel. These classes are just for reading templates and do not create actual panel. * Add template clearing via bentobox reload command.
This commit is contained in:
parent
faf351fd59
commit
2607256c06
@ -0,0 +1,87 @@
|
||||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.api.panels.reader;
|
||||
|
||||
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* This Record contains all necessary information about Item Template that can be used to craft panel item.
|
||||
*
|
||||
* @param icon ItemStack of the Item
|
||||
* @param title Title of the item
|
||||
* @param description Lore message of the item
|
||||
* @param actions List of Actions for a button
|
||||
* @param dataMap DataMap that links additional objects for a button.
|
||||
* @param fallback FallBack item if current one is not possible to generate.
|
||||
*
|
||||
* @since 1.17.3
|
||||
*/
|
||||
public record ItemTemplateRecord(ItemStack icon,
|
||||
String title,
|
||||
String description,
|
||||
List<ActionRecords> actions,
|
||||
Map<String, Object> dataMap,
|
||||
ItemTemplateRecord fallback)
|
||||
{
|
||||
/**
|
||||
* Instantiates a new Item template record without actions and data map.
|
||||
*
|
||||
* @param icon the icon
|
||||
* @param title the title
|
||||
* @param description the description
|
||||
* @param fallback the fallback
|
||||
*/
|
||||
public ItemTemplateRecord(ItemStack icon, String title, String description, ItemTemplateRecord fallback)
|
||||
{
|
||||
this(icon, title, description, new ArrayList<>(6), new HashMap<>(0), fallback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method adds given object associated with key into data map.
|
||||
* @param key Key value of object.
|
||||
* @param data Data that is associated with a key.
|
||||
*/
|
||||
public void addData(String key, Object data)
|
||||
{
|
||||
this.dataMap.put(key, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add action to the actions list.
|
||||
*
|
||||
* @param actionData the action data
|
||||
*/
|
||||
public void addAction(ActionRecords actionData)
|
||||
{
|
||||
this.actions.add(actionData);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Classes
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* The Action Records holds data about each action.
|
||||
*
|
||||
* @param clickType the click type
|
||||
* @param actionType the string that represents action type
|
||||
* @param content the content of the action
|
||||
* @param tooltip the tooltip of action
|
||||
*/
|
||||
public record ActionRecords(ClickType clickType, String actionType, String content, String tooltip) {}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.api.panels.reader;
|
||||
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.Panel;
|
||||
|
||||
|
||||
/**
|
||||
* This is template object for the panel reader. It contains data that can exist in the panel.
|
||||
* PanelBuilder will use this to build panel.
|
||||
*
|
||||
* @param type the type of GUI
|
||||
* @param title the title of GUI
|
||||
* @param border the border block for GUI
|
||||
* @param background the background block for GUI.
|
||||
* @param content The 2D array of ItemTemplateRecords
|
||||
*
|
||||
* @since 1.17.3
|
||||
*/
|
||||
public record PanelTemplateRecord(Panel.Type type,
|
||||
String title,
|
||||
TemplateItem border,
|
||||
TemplateItem background,
|
||||
ItemTemplateRecord[][] content)
|
||||
{
|
||||
/**
|
||||
* Instantiates a new Panel template record with empty content.
|
||||
*
|
||||
* @param type the type
|
||||
* @param title the title
|
||||
* @param border the border
|
||||
* @param background the background
|
||||
*/
|
||||
public PanelTemplateRecord(Panel.Type type, String title, TemplateItem border, TemplateItem background)
|
||||
{
|
||||
this(type, title, border, background, new ItemTemplateRecord[6][9]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method adds give item template record in given slot.
|
||||
* @param rowIndex row index of content array
|
||||
* @param columnIndex column index of content array.
|
||||
* @param panelItemTemplate item template record that must be added.
|
||||
*/
|
||||
public void addButtonTemplate(int rowIndex, int columnIndex, ItemTemplateRecord panelItemTemplate)
|
||||
{
|
||||
this.content[rowIndex][columnIndex] = panelItemTemplate;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Classes
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* This record contains info about border and background item.
|
||||
*/
|
||||
public record TemplateItem(ItemStack icon, String title, String description)
|
||||
{
|
||||
public TemplateItem(ItemStack icon)
|
||||
{
|
||||
this(icon, null, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,324 @@
|
||||
//
|
||||
// Created by BONNe
|
||||
// Copyright - 2021
|
||||
//
|
||||
|
||||
|
||||
package world.bentobox.bentobox.api.panels.reader;
|
||||
|
||||
|
||||
import com.google.common.base.Enums;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.Panel;
|
||||
import world.bentobox.bentobox.util.ItemParser;
|
||||
|
||||
|
||||
/**
|
||||
* This class manages Template file reading, creating PanelTemplateRecord object and storing it internally.
|
||||
* This class just reads and returns given panel template. It does not create a functional panel.
|
||||
*
|
||||
* @since 1.17.3
|
||||
*/
|
||||
public class TemplateReader
|
||||
{
|
||||
/**
|
||||
* Read template panel panel template record.
|
||||
*
|
||||
* @param panelName the panel name
|
||||
* @param panelLocation the panel location directory
|
||||
* @return the panel template record
|
||||
*/
|
||||
public static PanelTemplateRecord readTemplatePanel(@NonNull String panelName, @NonNull File panelLocation)
|
||||
{
|
||||
if (!panelLocation.exists())
|
||||
{
|
||||
// Return null because folder does not exist.
|
||||
return null;
|
||||
}
|
||||
|
||||
File file = new File(panelLocation, panelName.endsWith(".yml") ? panelName : panelName + ".yml");
|
||||
|
||||
if (!file.exists())
|
||||
{
|
||||
// Return as file does not exist.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if panel is already crafted.
|
||||
if (TemplateReader.loadedPanels.containsKey(file.getAbsolutePath()))
|
||||
{
|
||||
return TemplateReader.loadedPanels.get(file.getAbsolutePath());
|
||||
}
|
||||
|
||||
PanelTemplateRecord record;
|
||||
|
||||
try
|
||||
{
|
||||
// Load config
|
||||
YamlConfiguration config = new YamlConfiguration();
|
||||
config.load(file);
|
||||
// Read panel
|
||||
record = readPanelTemplate(config.getConfigurationSection(panelName));
|
||||
// Put panel into memory
|
||||
TemplateReader.loadedPanels.put(file.getAbsolutePath(), record);
|
||||
}
|
||||
catch (IOException | InvalidConfigurationException e)
|
||||
{
|
||||
record = null;
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method reads panel template from given configuration section.
|
||||
* @param configurationSection Section that contains panel template data.
|
||||
* @return Panel Template.
|
||||
*/
|
||||
private static PanelTemplateRecord readPanelTemplate(@Nullable ConfigurationSection configurationSection)
|
||||
{
|
||||
if (configurationSection == null)
|
||||
{
|
||||
// No data to return.
|
||||
return null;
|
||||
}
|
||||
|
||||
String title = configurationSection.getString("title");
|
||||
Panel.Type type = configurationSection.getObject("type", Panel.Type.class);
|
||||
|
||||
PanelTemplateRecord.TemplateItem borderItem = null;
|
||||
|
||||
// Read Border Icon.
|
||||
if (configurationSection.isConfigurationSection("border"))
|
||||
{
|
||||
// Process border icon if it contains more options.
|
||||
ConfigurationSection borderSection = configurationSection.getConfigurationSection("border");
|
||||
|
||||
if (borderSection != null)
|
||||
{
|
||||
borderItem = new PanelTemplateRecord.TemplateItem(
|
||||
ItemParser.parse((borderSection.getString("icon", Material.AIR.name()))),
|
||||
borderSection.getString("name", null),
|
||||
borderSection.getString("description", null));
|
||||
}
|
||||
}
|
||||
else if (configurationSection.isString("border"))
|
||||
{
|
||||
// Process border icon if it contains only icon.
|
||||
|
||||
borderItem = new PanelTemplateRecord.TemplateItem(
|
||||
ItemParser.parse((configurationSection.getString("border", Material.AIR.name()))));
|
||||
}
|
||||
|
||||
PanelTemplateRecord.TemplateItem backgroundItem = null;
|
||||
|
||||
// Read Background block
|
||||
if (configurationSection.isConfigurationSection("background"))
|
||||
{
|
||||
// Process border icon if it contains more options.
|
||||
ConfigurationSection backgroundSection = configurationSection.getConfigurationSection("background");
|
||||
|
||||
if (backgroundSection != null)
|
||||
{
|
||||
backgroundItem = new PanelTemplateRecord.TemplateItem(
|
||||
ItemParser.parse((backgroundSection.getString("icon", Material.AIR.name()))),
|
||||
backgroundSection.getString("name", null),
|
||||
backgroundSection.getString("description", null));
|
||||
}
|
||||
}
|
||||
else if (configurationSection.isString("background"))
|
||||
{
|
||||
// Process background icon if it contains only icon.
|
||||
|
||||
backgroundItem = new PanelTemplateRecord.TemplateItem(
|
||||
ItemParser.parse((configurationSection.getString("background", Material.AIR.name()))));
|
||||
}
|
||||
|
||||
// Read reusable
|
||||
Map<String, ItemTemplateRecord> panelItemDataMap = new HashMap<>();
|
||||
ConfigurationSection reusable = configurationSection.getConfigurationSection("reusable");
|
||||
|
||||
if (reusable != null)
|
||||
{
|
||||
// Add all reusables to the local storage.
|
||||
reusable.getKeys(false).forEach(key ->
|
||||
readPanelItemTemplate(reusable.getConfigurationSection(key), key, panelItemDataMap));
|
||||
}
|
||||
|
||||
// Create template record.
|
||||
PanelTemplateRecord template = new PanelTemplateRecord(type, title, borderItem, backgroundItem);
|
||||
|
||||
// Read content
|
||||
ConfigurationSection content = configurationSection.getConfigurationSection("content");
|
||||
|
||||
if (content == null)
|
||||
{
|
||||
// Return empty template.
|
||||
return template;
|
||||
}
|
||||
|
||||
for (int rowIndex = 0; rowIndex < 6; rowIndex++)
|
||||
{
|
||||
// Read each line.
|
||||
if (content.isConfigurationSection(String.valueOf(rowIndex + 1)))
|
||||
{
|
||||
ConfigurationSection line = content.getConfigurationSection(String.valueOf(rowIndex + 1));
|
||||
|
||||
if (line != null)
|
||||
{
|
||||
// Populate existing lines with items.
|
||||
for (int columnIndex = 0; columnIndex < 9; columnIndex++)
|
||||
{
|
||||
if (line.isConfigurationSection(String.valueOf(columnIndex + 1)))
|
||||
{
|
||||
// If it contains a section, then build a new button template from it.
|
||||
template.addButtonTemplate(rowIndex,
|
||||
columnIndex,
|
||||
readPanelItemTemplate(line.getConfigurationSection(String.valueOf(columnIndex + 1))));
|
||||
}
|
||||
else if (line.isString(String.valueOf(columnIndex + 1)))
|
||||
{
|
||||
// If it contains just a single word, assume it is a reusable.
|
||||
template.addButtonTemplate(rowIndex,
|
||||
columnIndex,
|
||||
panelItemDataMap.get(line.getString(String.valueOf(columnIndex + 1))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Garbage collector.
|
||||
panelItemDataMap.clear();
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates PanelItemTemplate from a given configuration section.
|
||||
* @param section Section that should contain all information about the panel item template.
|
||||
* @return PanelItemTemplate that should represent button from a section.
|
||||
*/
|
||||
@Nullable
|
||||
private static ItemTemplateRecord readPanelItemTemplate(@Nullable ConfigurationSection section)
|
||||
{
|
||||
return readPanelItemTemplate(section, null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This method creates PanelItemTemplate from a given configuration section.
|
||||
* @param section Section that should contain all information about the panel item template.
|
||||
* @return PanelItemTemplate that should represent button from a section.
|
||||
*/
|
||||
@Nullable
|
||||
private static ItemTemplateRecord readPanelItemTemplate(@Nullable ConfigurationSection section,
|
||||
String itemKey,
|
||||
Map<String, ItemTemplateRecord> reusableItemMap)
|
||||
{
|
||||
if (section == null)
|
||||
{
|
||||
// No section, no item.
|
||||
return null;
|
||||
}
|
||||
|
||||
ItemTemplateRecord fallback;
|
||||
|
||||
if (section.isConfigurationSection("fallback"))
|
||||
{
|
||||
fallback = readPanelItemTemplate(section.getConfigurationSection("fallback"));
|
||||
}
|
||||
else if (section.isString("fallback") && reusableItemMap != null)
|
||||
{
|
||||
fallback = reusableItemMap.get(section.getString("fallback"));
|
||||
}
|
||||
else
|
||||
{
|
||||
fallback = null;
|
||||
}
|
||||
|
||||
// Create Item Record
|
||||
ItemTemplateRecord itemRecord = new ItemTemplateRecord(ItemParser.parse(section.getString("icon")),
|
||||
section.getString("title", null),
|
||||
section.getString("description", null),
|
||||
fallback);
|
||||
|
||||
// Read data
|
||||
if (section.isConfigurationSection("data"))
|
||||
{
|
||||
ConfigurationSection dataSection = section.getConfigurationSection("data");
|
||||
|
||||
if (dataSection != null)
|
||||
{
|
||||
dataSection.getKeys(false).forEach(key -> itemRecord.addData(key, dataSection.get(key)));
|
||||
}
|
||||
}
|
||||
|
||||
// Read Click data
|
||||
if (section.isConfigurationSection("actions"))
|
||||
{
|
||||
ConfigurationSection actionSection = section.getConfigurationSection("actions");
|
||||
|
||||
if (actionSection != null)
|
||||
{
|
||||
actionSection.getKeys(false).forEach(actionKey -> {
|
||||
ClickType clickType = Enums.getIfPresent(ClickType.class, actionKey.toUpperCase()).orNull();
|
||||
|
||||
if (clickType != null)
|
||||
{
|
||||
ConfigurationSection actionDataSection = actionSection.getConfigurationSection(actionKey);
|
||||
|
||||
if (actionDataSection != null)
|
||||
{
|
||||
ItemTemplateRecord.ActionRecords actionData =
|
||||
new ItemTemplateRecord.ActionRecords(clickType,
|
||||
actionDataSection.getString("type"),
|
||||
actionDataSection.getString("content"),
|
||||
actionDataSection.getString("tooltip"));
|
||||
|
||||
itemRecord.addAction(actionData);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add item to the map
|
||||
if (reusableItemMap != null && itemKey != null)
|
||||
{
|
||||
reusableItemMap.put(itemKey, itemRecord);
|
||||
}
|
||||
|
||||
return itemRecord;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method clears loaded panels from the cache.
|
||||
*/
|
||||
public static void clearPanels()
|
||||
{
|
||||
loadedPanels.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This map contains already read panels and their location.
|
||||
* This improves performance for GUI opening, with a some memory usage.
|
||||
*/
|
||||
private static final Map<String, PanelTemplateRecord> loadedPanels = new HashMap<>();
|
||||
}
|
@ -7,6 +7,7 @@ import org.bukkit.Bukkit;
|
||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||
import world.bentobox.bentobox.api.events.BentoBoxReadyEvent;
|
||||
import world.bentobox.bentobox.api.panels.reader.TemplateReader;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.commands.reload.BentoBoxReloadLocalesCommand;
|
||||
import world.bentobox.bentobox.listeners.PanelListenerManager;
|
||||
@ -45,6 +46,8 @@ public class BentoBoxReloadCommand extends ConfirmableCommand {
|
||||
|
||||
// Close all open panels
|
||||
PanelListenerManager.closeAllPanels();
|
||||
// Clear all template panels.
|
||||
TemplateReader.clearPanels();
|
||||
|
||||
// Reload settings
|
||||
getPlugin().loadSettings();
|
||||
|
Loading…
Reference in New Issue
Block a user