From 4c16b0d7792b2945c4c838b638c9cb035b4aa035 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 19 May 2019 23:18:24 -0700 Subject: [PATCH] Implement Blueprint Bundles GUI (#691) * WIP Blueprint GUI * Basic implementation. Still WIP. Needs to enable description adding. * Added description entry for blueprint bundle. * Readded maven-javadoc-plugin --- pom.xml | 13 - .../blueprints/AdminBlueprintCommand.java | 5 +- .../bentobox/blueprints/Blueprint.java | 28 +- .../conversation/DescriptionPrompt.java | 60 ++++ .../DescriptionSuccessPrompt.java | 52 ++++ .../conversation/NameConversationPrefix.java | 13 + .../blueprints/conversation/NamePrompt.java | 48 +++ .../conversation/NameSuccessPrompt.java | 45 +++ .../dataobjects/BlueprintBundle.java | 8 + .../bentobox/managers/BlueprintsManager.java | 40 ++- .../panels/BlueprintManagementPanel.java | 273 +++++++++++++++++- .../panels/BundleManagementPanel.java | 14 + .../bentobox/panels/IslandCreationPanel.java | 2 +- .../bentobox/panels/ManagementPanel.java | 2 +- 14 files changed, 569 insertions(+), 34 deletions(-) create mode 100644 src/main/java/world/bentobox/bentobox/blueprints/conversation/DescriptionPrompt.java create mode 100644 src/main/java/world/bentobox/bentobox/blueprints/conversation/DescriptionSuccessPrompt.java create mode 100644 src/main/java/world/bentobox/bentobox/blueprints/conversation/NameConversationPrefix.java create mode 100644 src/main/java/world/bentobox/bentobox/blueprints/conversation/NamePrompt.java create mode 100644 src/main/java/world/bentobox/bentobox/blueprints/conversation/NameSuccessPrompt.java create mode 100644 src/main/java/world/bentobox/bentobox/panels/BundleManagementPanel.java diff --git a/pom.xml b/pom.xml index 245c06d37..e93366b40 100644 --- a/pom.xml +++ b/pom.xml @@ -293,19 +293,6 @@ - - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - - attach-sources - - jar-no-fork - - - - org.apache.maven.plugins maven-shade-plugin diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintCommand.java index f412983ad..475cbb20a 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintCommand.java @@ -3,11 +3,14 @@ package world.bentobox.bentobox.api.commands.admin.blueprints; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Particle; + +import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.ConfirmableCommand; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.blueprints.BlueprintClipboard; import world.bentobox.bentobox.managers.BlueprintsManager; +import world.bentobox.bentobox.panels.BlueprintManagementPanel; import java.io.File; import java.util.HashMap; @@ -50,7 +53,7 @@ public class AdminBlueprintCommand extends ConfirmableCommand { @Override public boolean execute(User user, String label, List args) { - showHelp(this, user); + new BlueprintManagementPanel(getPlugin()).openPanel(user, (GameModeAddon)getAddon()); return true; } diff --git a/src/main/java/world/bentobox/bentobox/blueprints/Blueprint.java b/src/main/java/world/bentobox/bentobox/blueprints/Blueprint.java index 692136ba9..fbbdd1939 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/Blueprint.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/Blueprint.java @@ -3,6 +3,7 @@ */ package world.bentobox.bentobox.blueprints; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -20,7 +21,7 @@ import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity; * @author tastybento * */ -public class Blueprint { +public class Blueprint implements Comparable { /** * Unique name for this blueprint. The filename will be this plus the blueprint suffix @@ -56,8 +57,9 @@ public class Blueprint { /** * @param name the name to set */ - public void setName(String name) { + public Blueprint setName(String name) { this.name = name; + return this; } /** * @return the displayName @@ -68,8 +70,9 @@ public class Blueprint { /** * @param displayName the displayName to set */ - public void setDisplayName(String displayName) { + public Blueprint setDisplayName(String displayName) { this.displayName = displayName; + return this; } /** * @return the icon @@ -79,9 +82,11 @@ public class Blueprint { } /** * @param icon the icon to set + * @return */ - public void setIcon(Material icon) { + public Blueprint setIcon(Material icon) { this.icon = icon; + return this; } /** * @return the description @@ -92,8 +97,17 @@ public class Blueprint { /** * @param description the description to set */ - public void setDescription(List description) { + public Blueprint setDescription(List description) { this.description = description; + return this; + } + /** + * @param description the description to set + */ + public Blueprint setDescription(String description) { + if (this.description == null) this.description = new ArrayList<>(); + this.description.add(description); + return this; } /** * @return the attached @@ -183,5 +197,9 @@ public class Blueprint { public void setBedrock(Vector bedrock) { this.bedrock = bedrock; } + @Override + public int compareTo(Blueprint o) { + return this.name.compareToIgnoreCase(o.name); + } } diff --git a/src/main/java/world/bentobox/bentobox/blueprints/conversation/DescriptionPrompt.java b/src/main/java/world/bentobox/bentobox/blueprints/conversation/DescriptionPrompt.java new file mode 100644 index 000000000..959729bb9 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/blueprints/conversation/DescriptionPrompt.java @@ -0,0 +1,60 @@ +package world.bentobox.bentobox.blueprints.conversation; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.ChatColor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; + +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; + +/** + * Collects a description + * @author tastybento + * + */ +public class DescriptionPrompt extends StringPrompt { + + private GameModeAddon addon; + private BlueprintBundle bb; + + public DescriptionPrompt(GameModeAddon addon, BlueprintBundle bb) { + this.addon = addon; + this.bb = bb; + } + + @SuppressWarnings("unchecked") + @Override + public String getPromptText(ConversationContext context) { + if (context.getSessionData("description") != null) { + StringBuilder sb = new StringBuilder(); + for (String line : ((List) context.getSessionData("description"))) { + sb.append(ChatColor.DARK_PURPLE); + sb.append(line); + sb.append(System.getProperty("line.separator")); + } + return sb.toString(); + } + return "Enter a multi line description for " + bb.getDisplayName() + System.getProperty("line.separator") + + ChatColor.GOLD + " and 'quit' on a line by itself to finish."; + } + + @SuppressWarnings("unchecked") + @Override + public Prompt acceptInput(ConversationContext context, String input) { + if (input.equals("quit")) { + return new DescriptionSuccessPrompt(addon, bb); + } + List desc = new ArrayList<>(); + if (context.getSessionData("description") != null) { + desc = ((List) context.getSessionData("description")); + } + desc.add(ChatColor.translateAlternateColorCodes('&', input)); + context.setSessionData("description", desc); + return this; + } +} + diff --git a/src/main/java/world/bentobox/bentobox/blueprints/conversation/DescriptionSuccessPrompt.java b/src/main/java/world/bentobox/bentobox/blueprints/conversation/DescriptionSuccessPrompt.java new file mode 100644 index 000000000..e6f3a7bff --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/blueprints/conversation/DescriptionSuccessPrompt.java @@ -0,0 +1,52 @@ +package world.bentobox.bentobox.blueprints.conversation; + +import java.util.List; + +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.MessagePrompt; +import org.bukkit.conversations.Prompt; +import org.bukkit.entity.Player; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; +import world.bentobox.bentobox.panels.BlueprintManagementPanel; + +public class DescriptionSuccessPrompt extends MessagePrompt { + + private GameModeAddon addon; + private BlueprintBundle bb; + + /** + * @param addon + * @param bb + */ + public DescriptionSuccessPrompt(GameModeAddon addon, BlueprintBundle bb) { + this.addon = addon; + this.bb = bb; + } + + @Override + public String getPromptText(ConversationContext context) { + @SuppressWarnings("unchecked") + List description = (List)context.getSessionData("description"); + if (description != null) { + bb.setDescription(description); + BentoBox.getInstance().getBlueprintsManager().addBlueprintBundle(addon, bb); + BentoBox.getInstance().getBlueprintsManager().saveBlueprintBundle(addon, bb); + new BlueprintManagementPanel(BentoBox.getInstance()).openBB(User.getInstance((Player)context.getForWhom()), addon, bb); + // Set the name + // if successfully + return "Success!"; + } else { + return "Cancelling"; + } + } + + @Override + protected Prompt getNextPrompt(ConversationContext context) { + return Prompt.END_OF_CONVERSATION; + } + +} diff --git a/src/main/java/world/bentobox/bentobox/blueprints/conversation/NameConversationPrefix.java b/src/main/java/world/bentobox/bentobox/blueprints/conversation/NameConversationPrefix.java new file mode 100644 index 000000000..96adc8367 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/blueprints/conversation/NameConversationPrefix.java @@ -0,0 +1,13 @@ +package world.bentobox.bentobox.blueprints.conversation; + +import org.bukkit.ChatColor; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.ConversationPrefix; + +public class NameConversationPrefix implements ConversationPrefix { + + @Override + public String getPrefix(ConversationContext conversationContext) { + return ChatColor.GOLD + "> "; + } +} diff --git a/src/main/java/world/bentobox/bentobox/blueprints/conversation/NamePrompt.java b/src/main/java/world/bentobox/bentobox/blueprints/conversation/NamePrompt.java new file mode 100644 index 000000000..c98e1143e --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/blueprints/conversation/NamePrompt.java @@ -0,0 +1,48 @@ +package world.bentobox.bentobox.blueprints.conversation; + +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; + +import net.md_5.bungee.api.ChatColor; +import world.bentobox.bentobox.api.addons.GameModeAddon; + +public class NamePrompt extends StringPrompt { + + private GameModeAddon addon; + + public NamePrompt(GameModeAddon addon) { + this.addon = addon; + } + + @Override + public String getPromptText(ConversationContext context) { + return "Enter a name, or 'quit' to quit"; + } + + @Override + public Prompt acceptInput(ConversationContext context, String input) { + // Convert color codes + input = ChatColor.translateAlternateColorCodes('&', input); + if (ChatColor.stripColor(input).length() > 32) { + context.getForWhom().sendRawMessage("Too long"); + return this; + } + // Make a uniqueid + StringBuilder uniqueId = new StringBuilder(ChatColor.stripColor(input).toLowerCase().replace(" ", "_")); + // Check if this name is unique + int max = 0; + while (max++ < 32 && addon.getPlugin().getBlueprintsManager().getBlueprintBundles(addon).containsKey(uniqueId.toString())) { + uniqueId.append("x"); + } + if (max == 32) { + context.getForWhom().sendRawMessage("Please pick a more unique name"); + return this; + } + context.setSessionData("uniqueId", uniqueId.toString()); + context.setSessionData("name", input); + return new NameSuccessPrompt(addon); + } + +} + diff --git a/src/main/java/world/bentobox/bentobox/blueprints/conversation/NameSuccessPrompt.java b/src/main/java/world/bentobox/bentobox/blueprints/conversation/NameSuccessPrompt.java new file mode 100644 index 000000000..cf9b0d57c --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/blueprints/conversation/NameSuccessPrompt.java @@ -0,0 +1,45 @@ +package world.bentobox.bentobox.blueprints.conversation; + +import org.bukkit.Material; +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.MessagePrompt; +import org.bukkit.conversations.Prompt; +import org.bukkit.entity.Player; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; +import world.bentobox.bentobox.panels.BlueprintManagementPanel; + +public class NameSuccessPrompt extends MessagePrompt { + + private GameModeAddon addon; + + public NameSuccessPrompt(GameModeAddon addon) { + this.addon = addon; + } + + @Override + public String getPromptText(ConversationContext context) { + String name = (String) context.getSessionData("name"); + String uniqueId = (String) context.getSessionData("uniqueId"); + BlueprintBundle bb = new BlueprintBundle(); + bb.setIcon(Material.RED_WOOL); + bb.setUniqueId(uniqueId); + bb.setDisplayName(name); + BentoBox.getInstance().getBlueprintsManager().addBlueprintBundle(addon, bb); + BentoBox.getInstance().getBlueprintsManager().saveBlueprintBundle(addon, bb); + new BlueprintManagementPanel(BentoBox.getInstance()).openPanel(User.getInstance((Player)context.getForWhom()), addon); + // Set the name + // if successfully + return "Success!"; + // Else return failure + } + + @Override + protected Prompt getNextPrompt(ConversationContext context) { + return Prompt.END_OF_CONVERSATION; + } + +} \ No newline at end of file diff --git a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintBundle.java b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintBundle.java index 1e3bce6ff..fd8087feb 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintBundle.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintBundle.java @@ -125,6 +125,14 @@ public class BlueprintBundle implements DataObject { this.blueprints.put(env, bp.getName()); } + /** + * Removes a blueprint from this environment slot + * @param env - the world environment + */ + public void clearBlueprint(World.Environment env) { + this.blueprints.remove(env); + } + /** * Get the blueprint for the environment type * @param env - {@link World#Environment} type diff --git a/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java b/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java index 5fe7f7e5a..5587599de 100644 --- a/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java @@ -6,6 +6,7 @@ import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.nio.file.Files; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; @@ -287,6 +288,15 @@ public class BlueprintsManager { return blueprints; } + /** + * Get blueprints for this game mode + * @param addon - game mdoe addon + * @return Map of name and blueprint or empty map + */ + public Map getBlueprints(GameModeAddon addon) { + return blueprints.getOrDefault(addon, new HashMap<>()); + } + /** * Paste the islands to world * @param addon - GameModeAddon @@ -316,8 +326,18 @@ public class BlueprintsManager { return false; } Blueprint bp = blueprints.get(addon).get(bb.getBlueprint(World.Environment.NORMAL)); + if (bp == null) { + // Oops, no overworld + bp = blueprints.get(addon).get("island"); + plugin.logError("Blueprint bundle has no normal world blueprint, using default"); + if (bp == null) { + plugin.logError("NO DEFAULT BLUEPRINT FOUND! Make sure 'island.blu' exists!"); + } + } // Paste overworld - new BlueprintPaster(plugin, bp, addon.getOverWorld(), island, task); + if (bp != null) { + new BlueprintPaster(plugin, bp, addon.getOverWorld(), island, task); + } // Make nether island if (bb.getBlueprint(World.Environment.NETHER) != null && addon.getWorldSettings().isNetherGenerate() @@ -383,4 +403,22 @@ public class BlueprintsManager { return true; } + /** + * Removes a blueprint bundle + * @param addon - Game Mode Addon + * @param bb - Blueprint Bundle to delete + */ + public void deleteBlueprintBundle(@NonNull GameModeAddon addon, BlueprintBundle bb) { + if (blueprintBundles.containsKey(addon)) { + blueprintBundles.get(addon).keySet().removeIf(k -> k.equals(bb.getUniqueId())); + } + File bpf = getBlueprintsFolder(addon); + File fileName = new File(bpf, bb.getUniqueId() + BLUEPRINT_BUNDLE_SUFFIX); + try { + Files.deleteIfExists(fileName.toPath()); + } catch (IOException e) { + plugin.logError("Could not delete Blueprint Bundle " + e.getLocalizedMessage()); + } + } + } diff --git a/src/main/java/world/bentobox/bentobox/panels/BlueprintManagementPanel.java b/src/main/java/world/bentobox/bentobox/panels/BlueprintManagementPanel.java index 1a4477d37..2cc5aae7d 100644 --- a/src/main/java/world/bentobox/bentobox/panels/BlueprintManagementPanel.java +++ b/src/main/java/world/bentobox/bentobox/panels/BlueprintManagementPanel.java @@ -1,27 +1,276 @@ package world.bentobox.bentobox.panels; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.conversations.Conversable; +import org.bukkit.conversations.ConversationFactory; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.event.inventory.ClickType; import org.eclipse.jdt.annotation.NonNull; + +import com.google.common.collect.ImmutableMap; + +import net.md_5.bungee.api.ChatColor; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.panels.Panel; +import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.builders.PanelBuilder; +import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.blueprints.Blueprint; +import world.bentobox.bentobox.blueprints.conversation.DescriptionPrompt; +import world.bentobox.bentobox.blueprints.conversation.NameConversationPrefix; +import world.bentobox.bentobox.blueprints.conversation.NamePrompt; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; +import world.bentobox.bentobox.util.Util; /** - * @author tastybento, Poslovitch + * @author tastybento * @since 1.5.0 */ public class BlueprintManagementPanel { - private static final String LOCALE_REF = "blueprint-management"; + private static final String INFO = "Click on blueprint then click here"; + private BentoBox plugin; + private final static Blueprint NORMAL_BP = new Blueprint().setIcon(Material.GREEN_STAINED_GLASS_PANE).setName("Normal").setDescription(INFO); + private final static Blueprint NETHER_BP = new Blueprint().setIcon(Material.RED_STAINED_GLASS_PANE).setName("Nether").setDescription(INFO); + private final static Blueprint END_BP = new Blueprint().setIcon(Material.YELLOW_STAINED_GLASS_PANE).setName("The End").setDescription(INFO); + private final static Map SLOT_TO_ENV = ImmutableMap.of(3, World.Environment.NORMAL, 5, World.Environment.NETHER, 7, World.Environment.THE_END); + private final static Map ENV_TO_BP = ImmutableMap.of(World.Environment.NORMAL, NORMAL_BP, World.Environment.NETHER, NETHER_BP, World.Environment.THE_END, END_BP); + private static final int MAX_WORLD_SLOT = 9; + private static final int MIN_WORLD_SLOT = 0; + private Entry selected; + private Map blueprints = new HashMap<>(); - private BlueprintManagementPanel() {} - - public static void openPanel(@NonNull User user, @NonNull GameModeAddon addon) { - PanelBuilder builder = new PanelBuilder() - .name(user.getTranslation(LOCALE_REF + "title")) - .size(54); - - - - builder.build().open(user); + public BlueprintManagementPanel(BentoBox plugin) { + this.plugin = plugin; } + + public void openPanel(@NonNull User user, @NonNull GameModeAddon addon) { + // Show panel of blueprint bundles + // Clicking on a bundle opens up the bundle edit panel + + // Create the panel + PanelBuilder pb = new PanelBuilder().name("Blueprint Bundle Manager").user(user).size(45); + // Get the bundles + plugin.getBlueprintsManager().getBlueprintBundles(addon).values().stream().limit(36) + .forEach(bb -> pb.item(new PanelItemBuilder() + .name(bb.getDisplayName()) + .description("Click to edit") + .icon(bb.getIcon()) + .clickHandler((panel, u, clickType, slot) -> { + u.closeInventory(); + openBB(u, addon, bb); + return true; + }) + .build())); + + // Panel has New Blueprint Bundle button - clicking in creates a new bundle + pb.item(36, getNewBundle(user, addon)); + + pb.build(); + } + + public void openBB(User user, @NonNull GameModeAddon addon, BlueprintBundle bb) { + int index = 18; + for (Blueprint bp : plugin.getBlueprintsManager().getBlueprints(addon).values()) { + blueprints.put(index++, bp); + } + // Create the panel + PanelBuilder pb = new PanelBuilder().name(bb.getDisplayName()).user(user).size(45); + // Display bundle icon + pb.item(0, new PanelItemBuilder() + .name("Click to edit description") + .description(bb.getDescription()) + .icon(bb.getIcon()) + .clickHandler((panel, u, clickType, slot) -> { + u.closeInventory(); + // Description conversation + askForDescription(u.getPlayer(), addon, bb); + return true; + }) + .build()); + SLOT_TO_ENV.forEach((k,v) -> { + String bpName = bb.getBlueprint(v); + pb.item(k-1, getWorldInstrTile(v)); + pb.item(k, getBlueprintItem(addon, k, bb, plugin.getBlueprintsManager().getBlueprints(addon).getOrDefault(bpName, ENV_TO_BP.get(v)))); + }); + + for (int i = 9; i < 18; i++) { + pb.item(i, new PanelItemBuilder().icon(Material.BLACK_STAINED_GLASS_PANE).name("-").build()); + } + blueprints.entrySet().stream().limit(18).forEach(b -> pb.item(getBlueprintItem(addon, b.getKey(), bb, b.getValue()))); + // Buttons for non-default bundle + if (!bb.getUniqueId().equals("default")) { + // Panel has a Trash icon. If right clicked it is discarded + pb.item(36, getTrashIcon(addon, bb)); + // Toggle permission - default is always allowed + pb.item(39, getPermissionIcon(addon, bb)); + } + // Panel has a Back icon. + pb.item(44, new PanelItemBuilder().icon(Material.ARROW).name("Back").clickHandler((panel, u, clickType, slot) -> { + openPanel(u,addon); + return true; + }).build()); + + pb.build(); + + } + + private PanelItem getWorldInstrTile(Environment env) { + return new PanelItemBuilder() + .name(Util.prettifyText(env.name()) + " world") + .description("Place bluprint", "to right to set") + .icon(Material.GRAY_STAINED_GLASS_PANE) + .build(); + } + + private PanelItem getTrashIcon(@NonNull GameModeAddon addon, BlueprintBundle bb) { + return new PanelItemBuilder() + .name("Trash") + .description("Right click here to delete") + .icon(Material.TNT) + .clickHandler((panel, u, clickType, slot) -> { + if (clickType.equals(ClickType.RIGHT)) { + u.getPlayer().playSound(u.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1F, 1F); + plugin.getBlueprintsManager().deleteBlueprintBundle(addon, bb); + openPanel(u,addon); + } + return true; + }) + .build(); + } + + private PanelItem getPermissionIcon(@NonNull GameModeAddon addon, BlueprintBundle bb) { + return new PanelItemBuilder().icon(Material.PAINTING).name("Permission") + .description(bb.isRequirePermission() ? ChatColor.RED + "Required" : ChatColor.GREEN + "Not required") + .description(bb.isRequirePermission() ? addon.getPermissionPrefix() + "island.create." + bb.getUniqueId() : "") + .clickHandler((panel, u, clickType, slot) -> { + // Toggle permission + u.getPlayer().playSound(u.getLocation(), Sound.UI_BUTTON_CLICK, 1F, 1F); + bb.setRequirePermission(!bb.isRequirePermission()); + // Save + plugin.getBlueprintsManager().saveBlueprintBundle(addon, bb); + panel.getInventory().setItem(39, getPermissionIcon(addon, bb).getItem()); + return true; + }).build(); + } + + private PanelItem getBlueprintItem(GameModeAddon addon, int pos, BlueprintBundle bb, Blueprint blueprint) { + // Create description + List desc = blueprint.getDescription() == null ? new ArrayList<>() : blueprint.getDescription(); + if ((!blueprint.equals(END_BP) && !blueprint.equals(NORMAL_BP) && !blueprint.equals(NETHER_BP))) { + if ((pos > MIN_WORLD_SLOT && pos < MAX_WORLD_SLOT)) { + desc.add(ChatColor.RED + "Right click to remove"); + } else { + desc.add(ChatColor.GREEN + "Click to select, then add to bundle"); + } + } + return new PanelItemBuilder() + .name(blueprint.getDisplayName() == null ? blueprint.getName() : blueprint.getDisplayName()) + .description(desc) + .icon(blueprint.getIcon() == null ? Material.PAPER : blueprint.getIcon()) + .clickHandler((panel, u, clickType, slot) -> { + // Handle the world squares + if (slot > MIN_WORLD_SLOT && slot < MAX_WORLD_SLOT) { + if (clickType.equals(ClickType.RIGHT)) { + u.getPlayer().playSound(u.getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, 1F); + PanelItem item = getBlueprintItem(addon, slot, bb, ENV_TO_BP.get(SLOT_TO_ENV.get(slot))); + // Remove the item and replace with the blank + bb.clearBlueprint(SLOT_TO_ENV.get(slot)); + panel.getItems().put(slot, item); + panel.getInventory().setItem(slot, item.getItem()); + // Save + plugin.getBlueprintsManager().saveBlueprintBundle(addon, bb); + } else if (selected == null) { + u.sendRawMessage("Select Blueprint first"); + u.getPlayer().playSound(u.getLocation(), Sound.BLOCK_ANVIL_HIT, 1F, 1F); + } else { + // Add + u.getPlayer().playSound(u.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); + Blueprint bp = selected.getValue(); + PanelItem item = getBlueprintItem(addon, slot, bb, bp); + // make slot the chosen one + bb.setBlueprint(SLOT_TO_ENV.get(slot), bp); + panel.getItems().put(slot, item); + panel.getInventory().setItem(slot, item.getItem()); + // Save + plugin.getBlueprintsManager().saveBlueprintBundle(addon, bb); + } + } else { + // Select blueprint + if (blueprints.containsKey(slot)) { + if (selected == null) { + // Nothing selected + u.getPlayer().playSound(u.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 2F); + selected = new AbstractMap.SimpleEntry<>(slot, blueprints.get(slot)); + panel.getInventory().getItem(slot).addUnsafeEnchantment(Enchantment.ARROW_DAMAGE, 1); + } else if (slot == selected.getKey()){ + // Clicked on same item + } else { + // Another item already selected + panel.getInventory().getItem(selected.getKey()).removeEnchantment(Enchantment.ARROW_DAMAGE); + u.getPlayer().playSound(u.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 2F); + selected = new AbstractMap.SimpleEntry<>(slot, blueprints.get(slot)); + panel.getInventory().getItem(slot).addUnsafeEnchantment(Enchantment.ARROW_DAMAGE, 1); + } + } + + } + + return true; + }) + .build(); + } + + private PanelItem getNewBundle(@NonNull User user, @NonNull GameModeAddon addon) { + return new PanelItemBuilder() + .name("New Bundle") + .description("Click to make a new bundle") + .icon(Material.GREEN_BANNER) + .clickHandler((panel, u, clickType, slot) -> { + u.closeInventory(); + askForName(u.getPlayer(), addon); + return true; + }) + .build(); + } + + public boolean trashBundle(Panel panel, User user, ClickType clickType, int slot ) { + return true; + } + + public void askForName(Conversable whom, GameModeAddon addon) { + new ConversationFactory(BentoBox.getInstance()) + .withModality(true) + .withLocalEcho(false) + .withPrefix(new NameConversationPrefix()) + .withTimeout(90) + .withFirstPrompt(new NamePrompt(addon)) + .withEscapeSequence("exit") + .withEscapeSequence("quit") + .buildConversation(whom).begin(); + } + + public void askForDescription(Conversable whom, GameModeAddon addon, BlueprintBundle bb) { + new ConversationFactory(BentoBox.getInstance()) + .withModality(true) + .withLocalEcho(false) + .withPrefix(new NameConversationPrefix()) + .withTimeout(90) + .withFirstPrompt(new DescriptionPrompt(addon, bb)) + .buildConversation(whom).begin(); + } + + } diff --git a/src/main/java/world/bentobox/bentobox/panels/BundleManagementPanel.java b/src/main/java/world/bentobox/bentobox/panels/BundleManagementPanel.java new file mode 100644 index 000000000..5eb318288 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/panels/BundleManagementPanel.java @@ -0,0 +1,14 @@ +package world.bentobox.bentobox.panels; + +import org.bukkit.event.inventory.ClickType; + +import world.bentobox.bentobox.api.panels.Panel; +import world.bentobox.bentobox.api.user.User; + +public class BundleManagementPanel { + private BundleManagementPanel() {} + + public static boolean openPanel(Panel panel, User user, ClickType clickType, int slot ) { + return true; + } +} diff --git a/src/main/java/world/bentobox/bentobox/panels/IslandCreationPanel.java b/src/main/java/world/bentobox/bentobox/panels/IslandCreationPanel.java index 1d31ed5b2..cc6ad64cd 100644 --- a/src/main/java/world/bentobox/bentobox/panels/IslandCreationPanel.java +++ b/src/main/java/world/bentobox/bentobox/panels/IslandCreationPanel.java @@ -43,7 +43,7 @@ public class IslandCreationPanel { || user.hasPermission(perm)) { // Add an item pb.item(new PanelItemBuilder().name(bb.getDisplayName()).description(bb.getDescription()) - .icon(bb.getIcon()).name(bb.getUniqueId()).clickHandler((panel, user1, clickType, slot1) -> { + .icon(bb.getIcon()).clickHandler((panel, user1, clickType, slot1) -> { user1.closeInventory(); command.execute(user1, label, Collections.singletonList(bb.getUniqueId())); return true; diff --git a/src/main/java/world/bentobox/bentobox/panels/ManagementPanel.java b/src/main/java/world/bentobox/bentobox/panels/ManagementPanel.java index a1f4efc36..6c8c49b5a 100644 --- a/src/main/java/world/bentobox/bentobox/panels/ManagementPanel.java +++ b/src/main/java/world/bentobox/bentobox/panels/ManagementPanel.java @@ -72,7 +72,7 @@ public class ManagementPanel { .name(user.getTranslation(LOCALE_REF + "views.gamemodes.blueprints.name")) .description(user.getTranslation(LOCALE_REF + "views.gamemodes.blueprints.description")) .clickHandler((panel, user1, clickType, slot) -> { - BlueprintManagementPanel.openPanel(user, gameModeAddon); + new BlueprintManagementPanel(plugin).openPanel(user, gameModeAddon); return true; }) .build();