Implements Basic/Advanced/Expert settings panels (#888)

* Implements Basic/Advanced/Expert settings panels

Better alternative to https://github.com/BentoBoxWorld/BentoBox/pull/887

* Remove StatusIcon class - not used.

* Fixes glow of active tab.

* Moved FlagMode to Flag.Mode

* Display the LOCK flag no matter what the tab is

* Made the "mode" being saved for the player instead of per-tab
This means that a player will have its "mode" saved when he comes back later in the Settings Panel while also making the navigation more fluent - he won't need to set PROTECTION and SETTING to the same mode everytime.

Also renamed Flag.Mode#getNextFlag() to #getNext()
Added PlayersManager#setFlagsDisplayMode(UUID, Flag.Mode), #getFlagsDisplayMode(UUID)

* Play a sound when click on the mode button

* Added a description to the "mode" item

* Modified the mode for some flags
This commit is contained in:
tastybento 2019-08-12 14:54:05 -07:00 committed by Florian CUNY
parent 996a4e3df4
commit 2f78957d31
11 changed files with 357 additions and 94 deletions

View File

@ -65,9 +65,10 @@ public class AdminSettingsCommand extends CompositeCommand {
new TabbedPanelBuilder()
.user(user)
.world(getWorld())
.tab(2, new SettingsTab(getWorld(), user, Flag.Type.WORLD_SETTING))
.tab(6, new WorldDefaultSettingsTab(getWorld(), user))
.startingSlot(2)
.tab(1, new SettingsTab(getWorld(), user, Flag.Type.WORLD_SETTING))
.tab(2, new WorldDefaultSettingsTab(getWorld(), user))
.startingSlot(1)
.size(54)
.build().openPanel();
return true;
}
@ -75,9 +76,10 @@ public class AdminSettingsCommand extends CompositeCommand {
new TabbedPanelBuilder()
.user(user)
.world(getWorld())
.tab(2, new SettingsTab(getWorld(), user, island, Flag.Type.PROTECTION))
.tab(6, new SettingsTab(getWorld(), user, island, Flag.Type.SETTING))
.startingSlot(2)
.tab(1, new SettingsTab(getWorld(), user, island, Flag.Type.PROTECTION))
.tab(2, new SettingsTab(getWorld(), user, island, Flag.Type.SETTING))
.startingSlot(1)
.size(54)
.build().openPanel();
return true;
}

View File

@ -43,9 +43,10 @@ public class IslandSettingsCommand extends CompositeCommand {
new TabbedPanelBuilder()
.user(user)
.world(getWorld())
.tab(2, new SettingsTab(getWorld(), user, island, Flag.Type.PROTECTION))
.tab(6, new SettingsTab(getWorld(), user, island, Flag.Type.SETTING))
.startingSlot(2)
.tab(1, new SettingsTab(getWorld(), user, island, Flag.Type.PROTECTION))
.tab(2, new SettingsTab(getWorld(), user, island, Flag.Type.SETTING))
.startingSlot(1)
.size(54)
.build().openPanel();
return true;
}

View File

@ -62,6 +62,61 @@ public class Flag implements Comparable<Flag> {
}
}
/**
* Defines the flag mode
* @author tastybento
* @since 1.6.0
*/
public enum Mode {
/**
* Flag should be shown in the basic settings
*/
BASIC,
/**
* Flag should be shown in the advanced settings
*/
ADVANCED,
/**
* Flag should be shown in the expert settings
*/
EXPERT,
/**
* Flag should be shown in the top row if applicable
*/
TOP_ROW;
/**
* Get the next ranking mode above this one. If at the top, it cycles back to the bottom mode
* @return next ranking mode
*/
public Mode getNext() {
switch(this) {
case ADVANCED:
return EXPERT;
case BASIC:
return ADVANCED;
default:
return BASIC;
}
}
/**
* Get a list of ranks that are ranked greater than this rank
* @param rank - rank to compare
* @return true if ranked greater
*/
public boolean isGreaterThan(Mode rank) {
switch(this) {
case EXPERT:
return rank.equals(BASIC) || rank.equals(ADVANCED);
case ADVANCED:
return rank.equals(BASIC);
default:
return false;
}
}
}
private static final String PROTECTION_FLAGS = "protection.flags.";
private final String id;
@ -75,6 +130,7 @@ public class Flag implements Comparable<Flag> {
private Set<GameModeAddon> gameModes = new HashSet<>();
private final Addon addon;
private final int cooldown;
private final Mode mode;
private Flag(Builder builder) {
this.id = builder.id;
@ -90,6 +146,7 @@ public class Flag implements Comparable<Flag> {
}
this.cooldown = builder.cooldown;
this.addon = builder.addon;
this.mode = builder.mode;
}
public String getID() {
@ -369,6 +426,14 @@ public class Flag implements Comparable<Flag> {
}
/**
* @return the mode
* @since 1.6.0
*/
public Mode getMode() {
return mode;
}
@Override
public String toString() {
return "Flag [id=" + id + "]";
@ -411,6 +476,9 @@ public class Flag implements Comparable<Flag> {
// Cooldown
private int cooldown;
// Mode
public Mode mode = Mode.EXPERT;
/**
* Builder for making flags
* @param id - a unique id that MUST be the same as the enum of the flag
@ -514,6 +582,18 @@ public class Flag implements Comparable<Flag> {
return this;
}
/**
* Set the flag difficulty mode.
* Defaults to {@link Flag.Mode#EXPERT}.
* @param mode
* @return Builder
* @since 1.6.0
*/
public Builder mode(Mode mode) {
this.mode = mode;
return this;
}
/**
* Build the flag
* @return Flag

View File

@ -1,6 +1,8 @@
package world.bentobox.bentobox.api.panels;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Represents a tab in a {@link TabbedPanel}. Contains {@link PanelItem}'s.
@ -30,4 +32,11 @@ public interface Tab {
*/
String getPermission();
/**
* @return Map of icons to be shown in the tab row when the tab is active
* Make sure these do not overlap any tabs that are in the tab row
*/
default Map<Integer, PanelItem> getTabIcons() {
return Collections.emptyMap();
}
}

View File

@ -27,6 +27,7 @@ import world.bentobox.bentobox.api.user.User;
*/
public class TabbedPanel extends Panel implements PanelListener {
private static final String PROTECTION_PANEL = "protection.panel.";
private final TabbedPanelBuilder tpb;
private @NonNull BentoBox plugin = BentoBox.getInstance();
private int activeTab;
@ -68,11 +69,11 @@ public class TabbedPanel extends Panel implements PanelListener {
public void openPanel(int activeTab, int page) {
if (!tpb.getTabs().containsKey(activeTab)) {
// Request to open a non-existent tab
throw new InvalidParameterException("Attemot to open a non-existent tab in a tabbed panel. Missing tab #" + activeTab);
throw new InvalidParameterException("Attempt to open a non-existent tab in a tabbed panel. Missing tab #" + activeTab);
}
if (page < 0) {
// Request to open a non-existent tab
throw new InvalidParameterException("Attemot to open a tab in a tabbed panel to a negative page! " + page);
throw new InvalidParameterException("Attempt to open a tab in a tabbed panel to a negative page! " + page);
}
this.activeTab = activeTab;
this.activePage = page;
@ -82,7 +83,7 @@ public class TabbedPanel extends Panel implements PanelListener {
Tab tab = tpb.getTabs().get(activeTab);
// Set up the tabbed header
setupHeader(items);
setupHeader(tab, items);
// Show the active tab
if (tpb.getTabs().containsKey(activeTab)) {
@ -91,15 +92,17 @@ public class TabbedPanel extends Panel implements PanelListener {
// Add forward and backward icons
if (page > 0) {
// Previous page icon
items.put(items.lastKey() + 1, new PanelItemBuilder().icon(Material.ARROW).name(tpb.getUser().getTranslation("previous")).clickHandler((panel, user1, clickType, slot1) -> {
openPanel(activeTab, page - 1);
items.put(items.lastKey() + 1, new PanelItemBuilder().icon(Material.ARROW).name(tpb.getUser().getTranslation(PROTECTION_PANEL + "previous")).clickHandler((panel, user1, clickType, slot1) -> {
this.activePage--;
this.refreshPanel();
return true;
}).build());
}
if ((page + 1) * 44 < items.size()) {
if ((page + 1) * 45 < items.size()) {
// Next page icon
items.put(items.lastKey() + 1, new PanelItemBuilder().icon(Material.ARROW).name(tpb.getUser().getTranslation("next")).clickHandler((panel, user1, clickType, slot1) -> {
openPanel(activeTab, page + 1);
items.put(items.lastKey() + 1, new PanelItemBuilder().icon(Material.ARROW).name(tpb.getUser().getTranslation(PROTECTION_PANEL + "next")).clickHandler((panel, user1, clickType, slot1) -> {
this.activePage++;
this.refreshPanel();
return true;
}).build());
}
@ -112,22 +115,26 @@ public class TabbedPanel extends Panel implements PanelListener {
/**
* Shows the top row of icons
* @param tab - active tab
* @param items - panel builder
*/
private void setupHeader(TreeMap<Integer, PanelItem> items) {
private void setupHeader(Tab tab, TreeMap<Integer, PanelItem> items) {
// Set up top
for (int i = 0; i < 9; i++) {
items.put(i, new PanelItemBuilder().icon(Material.BLACK_STAINED_GLASS_PANE).name("").build());
items.put(i, new PanelItemBuilder().icon(Material.LIGHT_BLUE_STAINED_GLASS_PANE).name("").build());
}
// Add icons
for (Entry<Integer, Tab> tabPanel : tpb.getTabs().entrySet()) {
// Set the glow of the active tab
tabPanel.getValue().getIcon().setGlow(tabPanel.getKey() == activeTab);
// Add the icon to the top row
if (tabPanel.getValue().getPermission().isEmpty() || tpb.getUser().hasPermission(tabPanel.getValue().getPermission()) || tpb.getUser().isOp()) {
items.put(tabPanel.getKey(), tabPanel.getValue().getIcon());
PanelItem activeIcon = tabPanel.getValue().getIcon();
// Set the glow of the active tab
activeIcon.setGlow(tabPanel.getValue().equals(tab));
items.put(tabPanel.getKey(), activeIcon);
}
}
// Add any subsidiary icons
tab.getTabIcons().forEach(items::put);
}
@ -163,4 +170,25 @@ public class TabbedPanel extends Panel implements PanelListener {
return tpb.getTabs().get(activeTab);
}
/**
* @return the activePage
*/
public int getActivePage() {
return activePage;
}
/**
* @param activePage the activePage to set
*/
public void setActivePage(int activePage) {
this.activePage = activePage;
}
/**
* @param activeTab the activeTab to set
*/
public void setActiveTab(int activeTab) {
this.activeTab = activeTab;
}
}

View File

@ -14,7 +14,9 @@ import org.bukkit.entity.Player;
import com.google.gson.annotations.Expose;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.util.Util;
/**
@ -43,6 +45,12 @@ public class Players implements DataObject {
@Expose
private Set<String> pendingKicks = new HashSet<>();
/**
* Stores the display mode of the Settings Panel.
* @since 1.6.0
*/
@Expose
private Flag.Mode flagsDisplayMode = Flag.Mode.BASIC;
/**
* This is required for database storage
@ -71,6 +79,7 @@ public class Players implements DataObject {
* @param world - world to check
* @return Location - home location in world
*/
@Nullable
public Location getHomeLocation(World world) {
return getHomeLocation(world, 1); // Default
}
@ -81,6 +90,7 @@ public class Players implements DataObject {
* @param number - a number
* @return Location of this home or null if not available
*/
@Nullable
public Location getHomeLocation(World world, int number) {
// Remove any lost worlds/locations
homeLocations.keySet().removeIf(l -> l == null || l.getWorld() == null);
@ -234,7 +244,7 @@ public class Players implements DataObject {
* @param deaths the deaths to set
*/
public void setDeaths(World world, int deaths) {
this.deaths.put(world.getName(), deaths > getPlugin().getIWM().getDeathsMax(world) ? getPlugin().getIWM().getDeathsMax(world) : deaths);
this.deaths.put(world.getName(), Math.min(deaths, getPlugin().getIWM().getDeathsMax(world)));
}
/**
@ -281,33 +291,51 @@ public class Players implements DataObject {
this.deaths = deaths;
}
/**
* This method returns the pendingKicks value.
* Returns the pendingKicks value.
* @return the value of pendingKicks.
* @since 1.3.0
*/
public Set<String> getPendingKicks()
{
return pendingKicks;
}
/**
* This method sets the pendingKicks value.
* Sets the pendingKicks value.
* @param pendingKicks the pendingKicks new value.
* @since 1.3.0
*/
public void setPendingKicks(Set<String> pendingKicks)
{
this.pendingKicks = pendingKicks;
}
/**
* This method adds given world in pendingKicks world set.
* Adds given world in pendingKicks world set.
* @param world World that must be added to pendingKicks set.
* @since 1.3.0
*/
public void addToPendingKick(World world)
{
this.pendingKicks.add(Util.getWorld(world).getName());
}
/**
* Returns the display mode for the Flags in the Settings Panel.
* @return the display mode for the Flags in the Settings Panel.
* @since 1.6.0
*/
public Flag.Mode getFlagsDisplayMode() {
return flagsDisplayMode;
}
/**
* Sets the display mode for the Flags in the Settings Panel.
* @param flagsDisplayMode the display mode for the Flags in the Settings Panel.
* @since 1.6.0
*/
public void setFlagsDisplayMode(Flag.Mode flagsDisplayMode) {
this.flagsDisplayMode = flagsDisplayMode;
}
}

View File

@ -73,12 +73,12 @@ public final class Flags {
* Prevents players from breaking blocks on one's island.
* @see BreakBlocksListener
*/
public static final Flag BREAK_BLOCKS = new Flag.Builder("BREAK_BLOCKS", Material.STONE).listener(new BreakBlocksListener()).build();
public static final Flag BREAK_BLOCKS = new Flag.Builder("BREAK_BLOCKS", Material.STONE).listener(new BreakBlocksListener()).mode(Flag.Mode.BASIC).build();
/**
* Prevents players from placing blocks on one's island.
* @see PlaceBlocksListener
*/
public static final Flag PLACE_BLOCKS = new Flag.Builder("PLACE_BLOCKS", Material.GRASS).listener(new PlaceBlocksListener()).build();
public static final Flag PLACE_BLOCKS = new Flag.Builder("PLACE_BLOCKS", Material.GRASS).listener(new PlaceBlocksListener()).mode(Flag.Mode.BASIC).build();
/**
* Prevents players from generating Frosted Ice on one's island using "Frost Walker" enchanted boots.
@ -87,27 +87,27 @@ public final class Flags {
public static final Flag FROST_WALKER = new Flag.Builder("FROST_WALKER", Material.ICE).build();
// Block interactions - all use BlockInteractionListener()
public static final Flag ANVIL = new Flag.Builder("ANVIL", Material.ANVIL).listener(new BlockInteractionListener()).build();
public static final Flag ANVIL = new Flag.Builder("ANVIL", Material.ANVIL).listener(new BlockInteractionListener()).mode(Flag.Mode.BASIC).build();
public static final Flag BEACON = new Flag.Builder("BEACON", Material.BEACON).build();
public static final Flag BED = new Flag.Builder("BED", Material.RED_BED).build();
public static final Flag BREWING = new Flag.Builder("BREWING", Material.BREWING_STAND).build();
public static final Flag CONTAINER = new Flag.Builder("CONTAINER", Material.CHEST).build();
public static final Flag DISPENSER = new Flag.Builder("DISPENSER", Material.DISPENSER).build();
public static final Flag DROPPER = new Flag.Builder("DROPPER", Material.DROPPER).build();
public static final Flag HOPPER = new Flag.Builder("HOPPER", Material.HOPPER).build();
public static final Flag DOOR = new Flag.Builder("DOOR", Material.OAK_DOOR).defaultSetting(true).build();
public static final Flag TRAPDOOR = new Flag.Builder("TRAPDOOR", Material.OAK_TRAPDOOR).defaultSetting(true).build();
public static final Flag BREWING = new Flag.Builder("BREWING", Material.BREWING_STAND).mode(Flag.Mode.ADVANCED).build();
public static final Flag CONTAINER = new Flag.Builder("CONTAINER", Material.CHEST).mode(Flag.Mode.BASIC).build();
public static final Flag DISPENSER = new Flag.Builder("DISPENSER", Material.DISPENSER).mode(Flag.Mode.ADVANCED).build();
public static final Flag DROPPER = new Flag.Builder("DROPPER", Material.DROPPER).mode(Flag.Mode.ADVANCED).build();
public static final Flag HOPPER = new Flag.Builder("HOPPER", Material.HOPPER).mode(Flag.Mode.ADVANCED).build();
public static final Flag DOOR = new Flag.Builder("DOOR", Material.OAK_DOOR).defaultSetting(true).mode(Flag.Mode.BASIC).build();
public static final Flag TRAPDOOR = new Flag.Builder("TRAPDOOR", Material.OAK_TRAPDOOR).defaultSetting(true).mode(Flag.Mode.BASIC).build();
public static final Flag CRAFTING = new Flag.Builder("CRAFTING", Material.CRAFTING_TABLE).defaultSetting(true).build();
public static final Flag ENCHANTING = new Flag.Builder("ENCHANTING", Material.ENCHANTING_TABLE).defaultSetting(true).build();
public static final Flag FURNACE = new Flag.Builder("FURNACE", Material.FURNACE).build();
public static final Flag GATE = new Flag.Builder("GATE", Material.OAK_FENCE_GATE).defaultSetting(true).build();
public static final Flag ENCHANTING = new Flag.Builder("ENCHANTING", Material.ENCHANTING_TABLE).defaultSetting(true).mode(Flag.Mode.BASIC).build();
public static final Flag FURNACE = new Flag.Builder("FURNACE", Material.FURNACE).mode(Flag.Mode.BASIC).build();
public static final Flag GATE = new Flag.Builder("GATE", Material.OAK_FENCE_GATE).mode(Flag.Mode.BASIC).defaultSetting(true).build();
public static final Flag NOTE_BLOCK = new Flag.Builder("NOTE_BLOCK", Material.NOTE_BLOCK).build();
public static final Flag JUKEBOX = new Flag.Builder("JUKEBOX", Material.JUKEBOX).build();
public static final Flag LEVER = new Flag.Builder("LEVER", Material.LEVER).build();
public static final Flag BUTTON = new Flag.Builder("BUTTON", Material.OAK_BUTTON).build();
public static final Flag REDSTONE = new Flag.Builder("REDSTONE", Material.REDSTONE).build();
public static final Flag LEVER = new Flag.Builder("LEVER", Material.LEVER).mode(Flag.Mode.ADVANCED).build();
public static final Flag BUTTON = new Flag.Builder("BUTTON", Material.OAK_BUTTON).mode(Flag.Mode.ADVANCED).build();
public static final Flag REDSTONE = new Flag.Builder("REDSTONE", Material.REDSTONE).mode(Flag.Mode.ADVANCED).build();
public static final Flag SPAWN_EGGS = new Flag.Builder("SPAWN_EGGS", Material.COW_SPAWN_EGG).build();
public static final Flag ITEM_FRAME = new Flag.Builder("ITEM_FRAME", Material.ITEM_FRAME).build();
public static final Flag ITEM_FRAME = new Flag.Builder("ITEM_FRAME", Material.ITEM_FRAME).mode(Flag.Mode.ADVANCED).build();
/**
* Prevents players from interacting with the Dragon Egg.
* @since 1.3.1
@ -117,7 +117,7 @@ public final class Flags {
public static final Flag DRAGON_EGG = new Flag.Builder("DRAGON_EGG", Material.DRAGON_EGG).build();
// Entity interactions
public static final Flag ARMOR_STAND = new Flag.Builder("ARMOR_STAND", Material.ARMOR_STAND).listener(new EntityInteractListener()).build();
public static final Flag ARMOR_STAND = new Flag.Builder("ARMOR_STAND", Material.ARMOR_STAND).listener(new EntityInteractListener()).mode(Flag.Mode.ADVANCED).build();
public static final Flag RIDING = new Flag.Builder("RIDING", Material.GOLDEN_HORSE_ARMOR).build();
/**
* Prevents players from issuing any kind of interactions with Minecarts (entering, placing and opening if chest).
@ -125,25 +125,25 @@ public final class Flags {
* @see EntityInteractListener
* @see PlaceBlocksListener
*/
public static final Flag MINECART = new Flag.Builder("MINECART", Material.MINECART).build();
public static final Flag MINECART = new Flag.Builder("MINECART", Material.MINECART).mode(Flag.Mode.ADVANCED).build();
/**
* Prevents players from issuing any kind of interactions with Boats (entering, placing).
* @since 1.3.0
* @see EntityInteractListener
* @see PlaceBlocksListener
*/
public static final Flag BOAT = new Flag.Builder("BOAT", Material.OAK_BOAT).build();
public static final Flag TRADING = new Flag.Builder("TRADING", Material.EMERALD).defaultSetting(true).build();
public static final Flag NAME_TAG = new Flag.Builder("NAME_TAG", Material.NAME_TAG).build();
public static final Flag BOAT = new Flag.Builder("BOAT", Material.OAK_BOAT).mode(Flag.Mode.BASIC).build();
public static final Flag TRADING = new Flag.Builder("TRADING", Material.EMERALD).defaultSetting(true).mode(Flag.Mode.BASIC).build();
public static final Flag NAME_TAG = new Flag.Builder("NAME_TAG", Material.NAME_TAG).mode(Flag.Mode.ADVANCED).build();
// Breeding
public static final Flag BREEDING = new Flag.Builder("BREEDING", Material.CARROT).listener(new BreedingListener()).build();
public static final Flag BREEDING = new Flag.Builder("BREEDING", Material.CARROT).listener(new BreedingListener()).mode(Flag.Mode.ADVANCED).build();
// Buckets. All bucket use is covered by one listener
public static final Flag BUCKET = new Flag.Builder("BUCKET", Material.BUCKET).listener(new BucketListener()).build();
public static final Flag BUCKET = new Flag.Builder("BUCKET", Material.BUCKET).listener(new BucketListener()).mode(Flag.Mode.BASIC).build();
public static final Flag COLLECT_LAVA = new Flag.Builder("COLLECT_LAVA", Material.LAVA_BUCKET).build();
public static final Flag COLLECT_WATER = new Flag.Builder("COLLECT_WATER", Material.WATER_BUCKET).build();
public static final Flag MILKING = new Flag.Builder("MILKING", Material.MILK_BUCKET).build();
public static final Flag COLLECT_WATER = new Flag.Builder("COLLECT_WATER", Material.WATER_BUCKET).mode(Flag.Mode.ADVANCED).build();
public static final Flag MILKING = new Flag.Builder("MILKING", Material.MILK_BUCKET).mode(Flag.Mode.ADVANCED).build();
public static final Flag FISH_SCOOPING = new Flag.Builder("FISH_SCOOPING", Material.TROPICAL_FISH_BUCKET).build();
// Chorus Fruit and Enderpearls
@ -152,7 +152,7 @@ public final class Flags {
// Physical interactions
public static final Flag CROP_TRAMPLE = new Flag.Builder("CROP_TRAMPLE", Material.WHEAT).listener(new PhysicalInteractionListener()).build();
public static final Flag PRESSURE_PLATE = new Flag.Builder("PRESSURE_PLATE", Material.STONE_PRESSURE_PLATE).build();
public static final Flag PRESSURE_PLATE = new Flag.Builder("PRESSURE_PLATE", Material.STONE_PRESSURE_PLATE).mode(Flag.Mode.ADVANCED).build();
public static final Flag TURTLE_EGGS = new Flag.Builder("TURTLE_EGGS", Material.TURTLE_EGG).build();
// Throwing things
@ -190,7 +190,7 @@ public final class Flags {
*
* @see FireListener
*/
public static final Flag FLINT_AND_STEEL = new Flag.Builder("FLINT_AND_STEEL", Material.FLINT_AND_STEEL).listener(new FireListener()).build();
public static final Flag FLINT_AND_STEEL = new Flag.Builder("FLINT_AND_STEEL", Material.FLINT_AND_STEEL).listener(new FireListener()).mode(Flag.Mode.ADVANCED).build();
/**
* Prevents players from priming TNT.
@ -207,12 +207,12 @@ public final class Flags {
public static final Flag FIRE_EXTINGUISH = new Flag.Builder("FIRE_EXTINGUISH", Material.POTION).build();
// Inventories
public static final Flag MOUNT_INVENTORY = new Flag.Builder("MOUNT_INVENTORY", Material.IRON_HORSE_ARMOR).listener(new InventoryListener()).build();
public static final Flag MOUNT_INVENTORY = new Flag.Builder("MOUNT_INVENTORY", Material.IRON_HORSE_ARMOR).listener(new InventoryListener()).mode(Flag.Mode.ADVANCED).build();
// Hurting things
public static final Flag HURT_ANIMALS = new Flag.Builder("HURT_ANIMALS", Material.STONE_SWORD).listener(new HurtingListener()).build();
public static final Flag HURT_MONSTERS = new Flag.Builder("HURT_MONSTERS", Material.WOODEN_SWORD).build();
public static final Flag HURT_VILLAGERS = new Flag.Builder("HURT_VILLAGERS", Material.GOLDEN_SWORD).build();
public static final Flag HURT_ANIMALS = new Flag.Builder("HURT_ANIMALS", Material.STONE_SWORD).listener(new HurtingListener()).mode(Flag.Mode.ADVANCED).build();
public static final Flag HURT_MONSTERS = new Flag.Builder("HURT_MONSTERS", Material.WOODEN_SWORD).mode(Flag.Mode.BASIC).build();
public static final Flag HURT_VILLAGERS = new Flag.Builder("HURT_VILLAGERS", Material.GOLDEN_SWORD).mode(Flag.Mode.ADVANCED).build();
// Leashes
public static final Flag LEASH = new Flag.Builder("LEASH", Material.LEAD).listener(new LeashListener()).build();
@ -230,19 +230,34 @@ public final class Flags {
public static final Flag END_PORTAL = new Flag.Builder("END_PORTAL", Material.END_PORTAL_FRAME).build();
// Shearing
public static final Flag SHEARING = new Flag.Builder("SHEARING", Material.SHEARS).listener(new ShearingListener()).build();
public static final Flag SHEARING = new Flag.Builder("SHEARING", Material.SHEARS).listener(new ShearingListener()).mode(Flag.Mode.ADVANCED).build();
// Item pickup or drop
public static final Flag ITEM_DROP = new Flag.Builder("ITEM_DROP", Material.BEETROOT_SOUP).defaultSetting(true).listener(new ItemDropPickUpListener()).build();
public static final Flag ITEM_PICKUP = new Flag.Builder("ITEM_PICKUP", Material.BEETROOT_SEEDS).build();
public static final Flag ITEM_DROP = new Flag.Builder("ITEM_DROP", Material.BEETROOT_SOUP).defaultSetting(true).listener(new ItemDropPickUpListener()).mode(Flag.Mode.BASIC).build();
public static final Flag ITEM_PICKUP = new Flag.Builder("ITEM_PICKUP", Material.BEETROOT_SEEDS).mode(Flag.Mode.BASIC).build();
// Experience
public static final Flag EXPERIENCE_PICKUP = new Flag.Builder("EXPERIENCE_PICKUP", Material.EXPERIENCE_BOTTLE).listener(new ExperiencePickupListener()).build();
public static final Flag EXPERIENCE_PICKUP = new Flag.Builder("EXPERIENCE_PICKUP", Material.EXPERIENCE_BOTTLE).listener(new ExperiencePickupListener()).mode(Flag.Mode.ADVANCED).build();
// Command ranks
public static final Flag COMMAND_RANKS = new Flag.Builder("COMMAND_RANKS", Material.PLAYER_HEAD)
.clickHandler(new CommandRankClickListener()).usePanel(true).build();
/**
* Protects against visitors dying stuff, like sheep or signs
*
* @since 1.5.0
* @see DyeListener
*/
public static final Flag DYE = new Flag.Builder("DYE", Material.LIGHT_BLUE_DYE).listener(new DyeListener()).mode(Flag.Mode.ADVANCED).build();
/**
* Protects against visitors using elytra. By default, it is allowed.
*
* @since 1.6.0
*/
public static final Flag ELYTRA = new Flag.Builder("ELYTRA", Material.ELYTRA).defaultRank(RanksManager.VISITOR_RANK).listener(new ElytraListener()).mode(Flag.Mode.ADVANCED).build();
// TNT
/**
@ -255,18 +270,18 @@ public final class Flags {
public static final Flag LOCK = new Flag.Builder("LOCK", Material.TRIPWIRE_HOOK).defaultSetting(true)
.defaultRank(RanksManager.VISITOR_RANK).listener(new LockAndBanListener())
.clickHandler(new CycleClick("LOCK", RanksManager.VISITOR_RANK, RanksManager.MEMBER_RANK))
.build();
.mode(Flag.Mode.TOP_ROW).build();
/*
* Settings flags (not protection flags)
*/
// PVP
public static final Flag PVP_OVERWORLD = new Flag.Builder("PVP_OVERWORLD", Material.ARROW).type(Type.SETTING)
.defaultRank(DISABLED).listener(new PVPListener()).cooldown(60).build();
.defaultRank(DISABLED).listener(new PVPListener()).cooldown(60).mode(Flag.Mode.BASIC).build();
public static final Flag PVP_NETHER = new Flag.Builder("PVP_NETHER", Material.IRON_AXE).type(Type.SETTING)
.defaultRank(DISABLED).cooldown(60).build();
.defaultRank(DISABLED).cooldown(60).mode(Flag.Mode.BASIC).build();
public static final Flag PVP_END = new Flag.Builder("PVP_END", Material.END_CRYSTAL).type(Type.SETTING)
.defaultRank(DISABLED).cooldown(60).build();
.defaultRank(DISABLED).cooldown(60).mode(Flag.Mode.BASIC).build();
// Fire
/**
@ -274,18 +289,21 @@ public final class Flags {
* @since 1.3.0
* @see FireListener
*/
public static final Flag FIRE_BURNING = new Flag.Builder("FIRE_BURNING", Material.CHARCOAL).defaultSetting(true).type(Type.SETTING).build();
public static final Flag FIRE_BURNING = new Flag.Builder("FIRE_BURNING", Material.CHARCOAL).defaultSetting(true).type(Type.SETTING)
.mode(Flag.Mode.ADVANCED).build();
/**
* Prevents fire from being ignited by non-players.
* @since 1.3.0
* @see FireListener
*/
public static final Flag FIRE_IGNITE = new Flag.Builder("FIRE_IGNITE", Material.FLINT_AND_STEEL).defaultSetting(true).type(Type.SETTING).build();
public static final Flag FIRE_IGNITE = new Flag.Builder("FIRE_IGNITE", Material.FLINT_AND_STEEL).defaultSetting(true)
.mode(Flag.Mode.ADVANCED).type(Type.SETTING).build();
/**
* Prevents fire from spreading to other blocks.
* @see FireListener
*/
public static final Flag FIRE_SPREAD = new Flag.Builder("FIRE_SPREAD", Material.FIREWORK_STAR).defaultSetting(true).type(Type.SETTING).build();
public static final Flag FIRE_SPREAD = new Flag.Builder("FIRE_SPREAD", Material.FIREWORK_STAR).defaultSetting(true).type(Type.SETTING)
.mode(Flag.Mode.ADVANCED).build();
// Others
public static final Flag ANIMAL_SPAWN = new Flag.Builder("ANIMAL_SPAWN", Material.APPLE).defaultSetting(true).type(Type.SETTING)
@ -304,7 +322,8 @@ public final class Flags {
* @since 1.5.0
* @see TNTListener
*/
public static final Flag TNT_DAMAGE = new Flag.Builder("TNT_DAMAGE", Material.TNT).type(Type.SETTING).build();
public static final Flag TNT_DAMAGE = new Flag.Builder("TNT_DAMAGE", Material.TNT).type(Type.SETTING)
.mode(Flag.Mode.ADVANCED).build();
/*
* World Settings - they apply to every island in the game worlds.
@ -415,21 +434,6 @@ public final class Flags {
*/
public static final Flag NATURAL_SPAWNING_OUTSIDE_RANGE = new Flag.Builder("NATURAL_SPAWNING_OUTSIDE_RANGE", Material.ZOMBIE_SPAWN_EGG).type(Type.WORLD_SETTING).listener(new NaturalSpawningOutsideRangeListener()).defaultSetting(true).build();
/**
* Protects against visitors dying stuff, like sheep or signs
*
* @since 1.5.0
* @see DyeListener
*/
public static final Flag DYE = new Flag.Builder("DYE", Material.LIGHT_BLUE_DYE).type(Type.PROTECTION).listener(new DyeListener()).build();
/**
* Protects against visitors using elytra. By default, it is allowed.
*
* @since 1.6.0
*/
public static final Flag ELYTRA = new Flag.Builder("ELYTRA", Material.ELYTRA).type(Type.PROTECTION).defaultRank(RanksManager.VISITOR_RANK).listener(new ElytraListener()).build();
/**
* Toggles wither explosion damage
* @since 1.6.0

View File

@ -14,6 +14,7 @@ import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Names;
@ -422,7 +423,6 @@ public class PlayersManager {
return User.getInstance(uuid);
}
/**
* Adds a reset to this player's number of resets
* @param world world where island is
@ -431,7 +431,27 @@ public class PlayersManager {
public void addReset(World world, UUID playerUUID) {
addPlayer(playerUUID);
playerCache.get(playerUUID).addReset(world);
}
/**
* Sets the Flags display mode for the Settings Panel for this player.
* @param playerUUID player's UUID
* @param displayMode the {@link Flag.Mode} to set
* @since 1.6.0
*/
public void setFlagsDisplayMode(UUID playerUUID, Flag.Mode displayMode) {
addPlayer(playerUUID);
playerCache.get(playerUUID).setFlagsDisplayMode(displayMode);
}
/**
* Returns the Flags display mode for the Settings Panel for this player.
* @param playerUUID player's UUID
* @return the {@link Flag.Mode display mode} for the Flags in the Settings Panel.
* @since 1.6.0
*/
public Flag.Mode getFlagsDisplayMode(UUID playerUUID) {
addPlayer(playerUUID);
return playerCache.get(playerUUID).getFlagsDisplayMode();
}
}

View File

@ -1,19 +1,28 @@
package world.bentobox.bentobox.panels.settings;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.event.inventory.ClickType;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.flags.Flag.Type;
import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler;
import world.bentobox.bentobox.api.panels.Tab;
import world.bentobox.bentobox.api.panels.TabbedPanel;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.lists.Flags;
/**
* Implements a {@link Tab} that shows settings for
@ -22,7 +31,7 @@ import world.bentobox.bentobox.database.objects.Island;
* @since 1.6.0
*
*/
public class SettingsTab implements Tab {
public class SettingsTab implements Tab, ClickHandler {
protected static final String PROTECTION_PANEL = "protection.panel.";
protected BentoBox plugin = BentoBox.getInstance();
@ -32,7 +41,7 @@ public class SettingsTab implements Tab {
protected Island island;
/**
* Show a tab of settings for the island owned by targetUUID to user
* Show a tab of settings
* @param world - world
* @param user - user who is viewing the tab
* @param island - the island
@ -46,7 +55,7 @@ public class SettingsTab implements Tab {
}
/**
* Show a tab of settings for the island owned by targetUUID to user
* Show a tab of settings
* @param world - world
* @param user - user who is viewing the tab
* @param type - flag type
@ -67,6 +76,10 @@ public class SettingsTab implements Tab {
.collect(Collectors.toList());
// Remove any that are not for this game mode
plugin.getIWM().getAddon(world).ifPresent(gm -> flags.removeIf(f -> !f.getGameModes().isEmpty() && !f.getGameModes().contains(gm)));
// Remove any that are the wrong rank or that will be on the top row
Flag.Mode mode = plugin.getPlayers().getFlagsDisplayMode(user.getUniqueId());
plugin.getIWM().getAddon(world).ifPresent(gm -> flags.removeIf(f -> f.getMode().isGreaterThan(mode) ||
f.getMode().equals(Flag.Mode.TOP_ROW)));
return flags;
}
@ -98,7 +111,50 @@ public class SettingsTab implements Tab {
*/
@Override
public List<PanelItem> getPanelItems() {
return getFlags().stream().map((f -> f.toPanelItem(plugin, user, island, plugin.getIWM().getHiddenFlags(world).contains(f.getID())))).collect(Collectors.toList());
List<Flag> flags = getFlags();
int i = 0;
// Jump past empty tabs
while (flags.isEmpty() && i++ < Flag.Mode.values().length) {
plugin.getPlayers().setFlagsDisplayMode(user.getUniqueId(), plugin.getPlayers().getFlagsDisplayMode(user.getUniqueId()).getNext());
flags = getFlags();
}
return flags.stream().map((f -> f.toPanelItem(plugin, user, island, plugin.getIWM().getHiddenFlags(world).contains(f.getID())))).collect(Collectors.toList());
}
@Override
public Map<Integer, PanelItem> getTabIcons() {
Map<Integer, PanelItem> icons = new HashMap<>();
// Add the lock icon - we want it to be displayed no matter the tab
if (island != null) {
icons.put(5, Flags.LOCK.toPanelItem(plugin, user, island, false));
}
// Add the mode icon
switch(plugin.getPlayers().getFlagsDisplayMode(user.getUniqueId())) {
case ADVANCED:
icons.put(7, new PanelItemBuilder().icon(Material.GOLD_INGOT)
.name(user.getTranslation(PROTECTION_PANEL + "mode.advanced.name"))
.description(user.getTranslation(PROTECTION_PANEL + "mode.advanced.description"), "",
user.getTranslation(PROTECTION_PANEL + "mode.click-to-switch", "[next]", user.getTranslation(PROTECTION_PANEL + "mode.expert.name")))
.clickHandler(this)
.build());
break;
case EXPERT:
icons.put(7, new PanelItemBuilder().icon(Material.NETHER_BRICK)
.name(user.getTranslation(PROTECTION_PANEL + "mode.expert.name"))
.description(user.getTranslation(PROTECTION_PANEL + "mode.expert.description"), "",
user.getTranslation(PROTECTION_PANEL + "mode.click-to-switch", "[next]", user.getTranslation(PROTECTION_PANEL + "mode.basic.name")))
.clickHandler(this)
.build());
break;
default:
icons.put(7, new PanelItemBuilder().icon(Material.IRON_INGOT)
.name(user.getTranslation(PROTECTION_PANEL + "mode.basic.name"))
.description(user.getTranslation(PROTECTION_PANEL + "mode.basic.description"), "",
user.getTranslation(PROTECTION_PANEL + "mode.click-to-switch", "[next]", user.getTranslation(PROTECTION_PANEL + "mode.advanced.name")))
.clickHandler(this)
.build());
}
return icons;
}
/* (non-Javadoc)
@ -138,4 +194,17 @@ public class SettingsTab implements Tab {
return island;
}
@Override
public boolean onClick(Panel panel, User user, ClickType clickType, int slot) {
// Cycle the mode
plugin.getPlayers().setFlagsDisplayMode(user.getUniqueId(), plugin.getPlayers().getFlagsDisplayMode(user.getUniqueId()).getNext());
if (panel instanceof TabbedPanel) {
TabbedPanel tp = ((TabbedPanel)panel);
tp.setActivePage(0);
tp.refreshPanel();
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_OFF, 1F, 1F);
}
return true;
}
}

View File

@ -1067,6 +1067,17 @@ protection:
panel:
next: "Next Page"
previous: "Previous Page"
mode:
advanced:
name: "&6Advanced Settings"
description: "&aDisplays a sensible amount of settings."
basic:
name: "&aBasic Settings"
description: "&aDisplays the most useful settings."
expert:
name: "&cExpert Settings"
description: "&aDisplays all the available settings."
click-to-switch: "&eClick &ato switch to the &r[next]&r&a."
PROTECTION:
title: "&6Protection"
description: |-

View File

@ -279,6 +279,17 @@ protection:
panel:
next: "Page suivante"
previous: "Page précédente"
mode:
advanced:
name: "&6Paramètres avancés"
description: "&aAffiche un nombre important de paramètres."
basic:
name: "&aParamètres simplifiés"
description: "&aAffiche les paramètres les plus utilisés."
expert:
name: "&cParamètres complets"
description: "&aAffiche tous les paramètres disponibles."
click-to-switch: "&eCliquez &apour afficher les &r[next]&r&a."
PROTECTION:
title: "&6Protection"
description: |-