Enables blueprint bundle slot positioning in GUI

https://github.com/BentoBoxWorld/BentoBox/issues/708
This commit is contained in:
tastybento 2019-06-02 15:52:27 -07:00
parent 5c8d88868a
commit 40f0591f7a
5 changed files with 155 additions and 29 deletions

View File

@ -8,6 +8,11 @@ import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelListener; import world.bentobox.bentobox.api.panels.PanelListener;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
/**
* Builds panels
* @author tastybento
*
*/
public class PanelBuilder { public class PanelBuilder {
private String name; private String name;
private TreeMap<Integer, PanelItem> items = new TreeMap<>(); private TreeMap<Integer, PanelItem> items = new TreeMap<>();
@ -79,11 +84,29 @@ public class PanelBuilder {
} }
/** /**
* Get the next free slot number after the largest slot * Get the next free slot number after the largest slot. If larger than the size of the panel, the first free spot available
* is used.
* @return next slot number, or -1 in case none has been found. * @return next slot number, or -1 in case none has been found.
*/ */
public int nextSlot() { public int nextSlot() {
return items.isEmpty() ? 0 : items.lastKey() + 1; int slot = items.isEmpty() ? 0 : items.lastKey() + 1;
if (slot >= size) {
return getFirstAvailableSlot();
}
return slot;
}
/**
* Get the first available slot
* @return slot or -1 if panel is full
*/
public int getFirstAvailableSlot() {
for (int i = 0; i < size; i++) {
if (!slotOccupied(i)) {
return i;
}
}
return -1;
} }
/** /**

View File

@ -1,16 +1,18 @@
package world.bentobox.bentobox.blueprints.dataobjects; package world.bentobox.bentobox.blueprints.dataobjects;
import com.google.gson.annotations.Expose;
import org.bukkit.Material;
import org.bukkit.World;
import world.bentobox.bentobox.blueprints.Blueprint;
import world.bentobox.bentobox.database.objects.DataObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.bukkit.Material;
import org.bukkit.World;
import com.google.gson.annotations.Expose;
import world.bentobox.bentobox.blueprints.Blueprint;
import world.bentobox.bentobox.database.objects.DataObject;
/** /**
* Represents a bundle of three {@link Blueprint}s. * Represents a bundle of three {@link Blueprint}s.
* This is what the player will choose when creating his island. * This is what the player will choose when creating his island.
@ -52,6 +54,15 @@ public class BlueprintBundle implements DataObject {
*/ */
@Expose @Expose
private Map<World.Environment, String> blueprints = new EnumMap<>(World.Environment.class); private Map<World.Environment, String> blueprints = new EnumMap<>(World.Environment.class);
/**
* Preferred slot in GUI.
*/
@Expose
private int slot = 0;
/** /**
* @return the uniqueId * @return the uniqueId
*/ */
@ -164,5 +175,17 @@ public class BlueprintBundle implements DataObject {
public void setRequirePermission(boolean requirePermission) { public void setRequirePermission(boolean requirePermission) {
this.requirePermission = requirePermission; this.requirePermission = requirePermission;
} }
/**
* @return the slot
*/
public int getSlot() {
return slot;
}
/**
* @param slot the slot to set
*/
public void setSlot(int slot) {
this.slot = slot;
}
} }

View File

@ -2,6 +2,7 @@ package world.bentobox.bentobox.panels;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -47,6 +48,7 @@ public class BlueprintManagementPanel {
private final Map<World.Environment, Blueprint> ENV_TO_BP; private final Map<World.Environment, Blueprint> ENV_TO_BP;
private static final int MAX_WORLD_SLOT = 9; private static final int MAX_WORLD_SLOT = 9;
private static final int MIN_WORLD_SLOT = 0; private static final int MIN_WORLD_SLOT = 0;
public static final int MAX_BP_SLOT = 35;
private Entry<Integer, Blueprint> selected; private Entry<Integer, Blueprint> selected;
private Map<Integer, Blueprint> blueprints = new HashMap<>(); private Map<Integer, Blueprint> blueprints = new HashMap<>();
private final User user; private final User user;
@ -80,13 +82,18 @@ public class BlueprintManagementPanel {
// Create the panel // Create the panel
PanelBuilder pb = new PanelBuilder().name(t("title")).user(user).size(45); PanelBuilder pb = new PanelBuilder().name(t("title")).user(user).size(45);
// Get the bundles // Get the bundles
Comparator<BlueprintBundle> sortByDisplayName = (p, o) -> p.getDisplayName().compareToIgnoreCase(o.getDisplayName());
plugin.getBlueprintsManager().getBlueprintBundles(addon).values().stream().limit(36) plugin.getBlueprintsManager().getBlueprintBundles(addon).values().stream().limit(36)
.forEach(bb -> pb.item(new PanelItemBuilder() .sorted(sortByDisplayName)
.forEach(bb -> {
// Make item
PanelItem item = new PanelItemBuilder()
.name(bb.getDisplayName()) .name(bb.getDisplayName())
.description(t("edit"), .description(t("edit"),
!bb.getUniqueId().equals(BlueprintsManager.DEFAULT_BUNDLE_NAME) ? t("rename") : "") !bb.getUniqueId().equals(BlueprintsManager.DEFAULT_BUNDLE_NAME) ? t("rename") : "")
.icon(bb.getIcon()) .icon(bb.getIcon())
.clickHandler((panel, u, clickType, slot) -> { .clickHandler((panel, u, clickType, slot) -> {
u.closeInventory(); u.closeInventory();
if (clickType.equals(ClickType.RIGHT) && !bb.getUniqueId().equals(BlueprintsManager.DEFAULT_BUNDLE_NAME)) { if (clickType.equals(ClickType.RIGHT) && !bb.getUniqueId().equals(BlueprintsManager.DEFAULT_BUNDLE_NAME)) {
// Rename // Rename
@ -96,7 +103,22 @@ public class BlueprintManagementPanel {
} }
return true; return true;
}) })
.build())); .build();
// Determine slot
if (bb.getSlot() < 0 || bb.getSlot() > MAX_BP_SLOT) {
bb.setSlot(0);
}
if (pb.slotOccupied(bb.getSlot())) {
int slot = pb.getFirstAvailableSlot();
if (slot == -1) {
// TODO add paging
plugin.logError("Too many blueprint bundles to show!");
}
pb.item(slot, item);
} else {
pb.item(bb.getSlot(), item);
}
});
// Panel has New Blueprint Bundle button - clicking in creates a new bundle // Panel has New Blueprint Bundle button - clicking in creates a new bundle
pb.item(36, getNewBundle(user, addon)); pb.item(36, getNewBundle(user, addon));
@ -134,8 +156,10 @@ public class BlueprintManagementPanel {
// Toggle permission - default is always allowed // Toggle permission - default is always allowed
pb.item(39, getPermissionIcon(addon, bb)); pb.item(39, getPermissionIcon(addon, bb));
} }
// Preferred slot
pb.item(40, getSlotIcon(addon, bb));
// Panel has a Back icon. // Panel has a Back icon.
pb.item(44, new PanelItemBuilder().icon(Material.ARROW).name(t("back")).clickHandler((panel, u, clickType, slot) -> { pb.item(44, new PanelItemBuilder().icon(Material.OAK_DOOR).name(t("back")).clickHandler((panel, u, clickType, slot) -> {
openPanel(); openPanel();
return true; return true;
}).build()); }).build());
@ -144,6 +168,39 @@ public class BlueprintManagementPanel {
} }
/**
* Gets the preferred slot icon
* @param addon - addon
* @param bb - blueprint bundle
* @return slot panel item
*/
private PanelItem getSlotIcon(GameModeAddon addon, BlueprintBundle bb) {
return new PanelItemBuilder()
.name(t("slot", TextVariables.NUMBER, String.valueOf(bb.getSlot())))
.description(t("slot-instructions"))
.icon(Material.IRON_TRAPDOOR)
.clickHandler((panel, u, clickType, slot) -> {
// Increment or decrement slot
if (clickType.isLeftClick()) {
bb.setSlot(bb.getSlot() + 1);
if (bb.getSlot() > MAX_BP_SLOT) {
bb.setSlot(0);
}
} else if (clickType.isRightClick()) {
bb.setSlot(bb.getSlot() - 1);
if (bb.getSlot() < 0) {
bb.setSlot(MAX_BP_SLOT);
}
}
u.getPlayer().playSound(u.getLocation(), Sound.UI_BUTTON_CLICK, 1F, 1F);
// Save
plugin.getBlueprintsManager().saveBlueprintBundle(addon, bb);
panel.getInventory().setItem(40, getSlotIcon(addon, bb).getItem());
return true;
})
.build();
}
/** /**
* Gets the panel item for Blueprint Bundle * Gets the panel item for Blueprint Bundle
* @param bb - blueprint bundle * @param bb - blueprint bundle

View File

@ -1,13 +1,16 @@
package world.bentobox.bentobox.panels; package world.bentobox.bentobox.panels;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder; import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
@ -34,7 +37,9 @@ public class IslandCreationPanel {
// Create the panel // Create the panel
PanelBuilder pb = new PanelBuilder().name(user.getTranslation("commands.island.create.pick")).user(user); PanelBuilder pb = new PanelBuilder().name(user.getTranslation("commands.island.create.pick")).user(user);
// Get the bundles // Get the bundles
Collection<BlueprintBundle> bbs = plugin.getBlueprintsManager().getBlueprintBundles((@NonNull GameModeAddon) command.getAddon()).values(); Comparator<BlueprintBundle> sortByDisplayName = (p, o) -> p.getDisplayName().compareToIgnoreCase(o.getDisplayName());
List<BlueprintBundle> bbs = plugin.getBlueprintsManager().getBlueprintBundles((@NonNull GameModeAddon) command.getAddon()).values()
.stream().sorted(sortByDisplayName).collect(Collectors.toList());
// Loop through them and create items in the panel // Loop through them and create items in the panel
for (BlueprintBundle bb : bbs) { for (BlueprintBundle bb : bbs) {
String perm = command.getPermissionPrefix() + "island.create." + bb.getUniqueId(); String perm = command.getPermissionPrefix() + "island.create." + bb.getUniqueId();
@ -42,12 +47,26 @@ public class IslandCreationPanel {
|| !bb.isRequirePermission() || !bb.isRequirePermission()
|| user.hasPermission(perm)) { || user.hasPermission(perm)) {
// Add an item // Add an item
pb.item(new PanelItemBuilder().name(bb.getDisplayName()).description(bb.getDescription()) PanelItem item = new PanelItemBuilder().name(bb.getDisplayName()).description(bb.getDescription())
.icon(bb.getIcon()).clickHandler((panel, user1, clickType, slot1) -> { .icon(bb.getIcon()).clickHandler((panel, user1, clickType, slot1) -> {
user1.closeInventory(); user1.closeInventory();
command.execute(user1, label, Collections.singletonList(bb.getUniqueId())); command.execute(user1, label, Collections.singletonList(bb.getUniqueId()));
return true; return true;
}).build()); }).build();
// Determine slot
if (bb.getSlot() < 0 || bb.getSlot() > BlueprintManagementPanel.MAX_BP_SLOT) {
bb.setSlot(0);
}
if (pb.slotOccupied(bb.getSlot())) {
int slot = pb.getFirstAvailableSlot();
if (slot == -1) {
// TODO add paging
plugin.logError("Too many blueprint bundles to show!");
}
pb.item(slot, item);
} else {
pb.item(bb.getSlot(), item);
}
} }
} }
pb.build(); pb.build();

View File

@ -272,6 +272,10 @@ commands:
default-color: "" default-color: ""
success: "Success!" success: "Success!"
cancelling: "Cancelling" cancelling: "Cancelling"
slot: "&fPreferred Slot [number]"
slot-instructions: |
&aLeft click to increment
&aRight click to decrement
resetflags: resetflags:
description: "Reset all islands to default flag settings in config.yml" description: "Reset all islands to default flag settings in config.yml"
world: world: