mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-12-17 22:57:52 +01:00
Merge branch 'develop' of https://github.com/BentoBoxWorld/BentoBox.git into develop
This commit is contained in:
commit
ed0084f2c4
1
ADDON.md
1
ADDON.md
@ -1,4 +1,5 @@
|
||||
The following is a list of all addons currently made for BentoBox:
|
||||
* [**Bank**](https://github.com/BentoBoxWorld/Bank/): Provides an island bank to enable island members to share money.
|
||||
* [**Biomes**](https://github.com/BentoBoxWorld/Biomes/): Enables players to change biomes on islands.
|
||||
* [**Border**](https://github.com/BentoBoxWorld/Border/): Adds a world border around islands.
|
||||
* [**Cauldron Witchery**](https://github.com/BentoBoxWorld/CauldronWitchery/): Allows summoning mobs using some magic!
|
||||
|
@ -25,6 +25,7 @@ Start now to create the server you've dreamed of!
|
||||
These are some popular Gamemodes:
|
||||
* [**AcidIsland**](https://github.com/BentoBoxWorld/AcidIsland): You are marooned in a sea of acid!
|
||||
* [**AOneBlock**](https://github.com/BentoBoxWorld/AOneBlock): Start to play with only 1 magical block.
|
||||
* [**Boxed**](https://github.com/BentoBoxWorld/Boxed): A game mode where you are boxed into a tiny space that only expands by completing advancements.
|
||||
* [**BSkyBlock**](https://github.com/BentoBoxWorld/BSkyBlock): The successor to the popular ASkyBlock.
|
||||
* [**CaveBlock**](https://github.com/BentoBoxWorld/CaveBlock): Try to live underground!
|
||||
* [**SkyGrid**](https://github.com/BentoBoxWorld/SkyGrid): Survive in world made up of scattered blocks - what an adventure!
|
||||
|
@ -1,10 +1,14 @@
|
||||
package world.bentobox.bentobox;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.AdvancedPie;
|
||||
import org.bstats.charts.SimpleBarChart;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -29,6 +33,13 @@ public class BStats {
|
||||
*/
|
||||
private int islandsCreatedCount = 0;
|
||||
|
||||
/**
|
||||
* Contains the amount of connected players since last data send.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
private final Set<UUID> connectedPlayerSet = new HashSet<>();
|
||||
|
||||
|
||||
BStats(BentoBox plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
@ -53,6 +64,11 @@ public class BStats {
|
||||
// Single Line charts
|
||||
registerIslandsCountChart();
|
||||
registerIslandsCreatedChart();
|
||||
|
||||
// Bar Charts
|
||||
registerAddonsBarChart();
|
||||
registerGameModeAddonsBarChart();
|
||||
registerHooksBarChart();
|
||||
}
|
||||
|
||||
private void registerDefaultLanguageChart() {
|
||||
@ -86,6 +102,15 @@ public class BStats {
|
||||
islandsCreatedCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds given UUID to the connected player set.
|
||||
* @param uuid UUID of a player who logins.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
public void addPlayer(UUID uuid) {
|
||||
this.connectedPlayerSet.add(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the enabled addons (except GameModeAddons) of this server.
|
||||
* @since 1.1
|
||||
@ -132,7 +157,9 @@ public class BStats {
|
||||
*/
|
||||
private void registerPlayersPerServerChart() {
|
||||
metrics.addCustomChart(new SimplePie("playersPerServer", () -> {
|
||||
int players = Bukkit.getOnlinePlayers().size();
|
||||
int players = this.connectedPlayerSet.size();
|
||||
this.connectedPlayerSet.clear();
|
||||
|
||||
if (players <= 0) return "0";
|
||||
else if (players <= 10) return "1-10";
|
||||
else if (players <= 30) return "11-30";
|
||||
@ -164,4 +191,44 @@ public class BStats {
|
||||
return values;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the enabled addons (except GameModeAddons) of this server as bar chart.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
private void registerAddonsBarChart() {
|
||||
metrics.addCustomChart(new SimpleBarChart("addonsBar", () -> {
|
||||
Map<String, Integer> values = new HashMap<>();
|
||||
plugin.getAddonsManager().getEnabledAddons().stream()
|
||||
.filter(addon -> !(addon instanceof GameModeAddon) && addon.getDescription().isMetrics())
|
||||
.forEach(addon -> values.put(addon.getDescription().getName(), 1));
|
||||
return values;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the enabled GameModeAddons of this server as a bar chart.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
private void registerGameModeAddonsBarChart() {
|
||||
metrics.addCustomChart(new SimpleBarChart("gameModeAddonsBar", () -> {
|
||||
Map<String, Integer> values = new HashMap<>();
|
||||
plugin.getAddonsManager().getGameModeAddons().stream()
|
||||
.filter(gameModeAddon -> gameModeAddon.getDescription().isMetrics())
|
||||
.forEach(gameModeAddon -> values.put(gameModeAddon.getDescription().getName(), 1));
|
||||
return values;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the enabled Hooks of this server as a bar chart.
|
||||
* @since 1.17.1
|
||||
*/
|
||||
private void registerHooksBarChart() {
|
||||
metrics.addCustomChart(new SimpleBarChart("hooksBar", () -> {
|
||||
Map<String, Integer> values = new HashMap<>();
|
||||
plugin.getHooks().getHooks().forEach(hook -> values.put(hook.getPluginName(), 1));
|
||||
return values;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package world.bentobox.bentobox.api.flags;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -131,6 +132,7 @@ public class Flag implements Comparable<Flag> {
|
||||
private final Addon addon;
|
||||
private final int cooldown;
|
||||
private final Mode mode;
|
||||
private final Set<Flag> subflags;
|
||||
|
||||
private Flag(Builder builder) {
|
||||
this.id = builder.id;
|
||||
@ -147,6 +149,7 @@ public class Flag implements Comparable<Flag> {
|
||||
this.cooldown = builder.cooldown;
|
||||
this.addon = builder.addon;
|
||||
this.mode = builder.mode;
|
||||
this.subflags = builder.subflags;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
@ -200,6 +203,18 @@ public class Flag implements Comparable<Flag> {
|
||||
.getWorldSettings(world)
|
||||
.getWorldFlags()
|
||||
.put(getID(), setting);
|
||||
|
||||
// Subflag support
|
||||
if (hasSubflags()) {
|
||||
subflags.stream()
|
||||
.filter(subflag -> subflag.getType().equals(Type.WORLD_SETTING) || subflag.getType().equals(Type.PROTECTION))
|
||||
.forEach(subflag -> BentoBox.getInstance()
|
||||
.getIWM()
|
||||
.getWorldSettings(world)
|
||||
.getWorldFlags()
|
||||
.put(subflag.getID(), setting));
|
||||
}
|
||||
|
||||
// Save config file
|
||||
BentoBox.getInstance().getIWM().getAddon(world).ifPresent(GameModeAddon::saveWorldSettings);
|
||||
}
|
||||
@ -208,6 +223,7 @@ public class Flag implements Comparable<Flag> {
|
||||
/**
|
||||
* Set the original status of this flag for locations outside of island spaces.
|
||||
* May be overriden by the the setting for this world.
|
||||
* Does not affect subflags.
|
||||
* @param defaultSetting - true means it is allowed. false means it is not allowed
|
||||
*/
|
||||
public void setDefaultSetting(boolean defaultSetting) {
|
||||
@ -217,6 +233,7 @@ public class Flag implements Comparable<Flag> {
|
||||
/**
|
||||
* Set the status of this flag for locations outside of island spaces for a specific world.
|
||||
* World must exist and be registered before this method can be called.
|
||||
* Does not affect subflags.
|
||||
* @param defaultSetting - true means it is allowed. false means it is not allowed
|
||||
*/
|
||||
public void setDefaultSetting(World world, boolean defaultSetting) {
|
||||
@ -435,6 +452,22 @@ public class Flag implements Comparable<Flag> {
|
||||
return mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the flag has subflags (and therefore is a parent flag)
|
||||
* @since 1.17.0
|
||||
*/
|
||||
public boolean hasSubflags() {
|
||||
return !subflags.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the subflags, an empty Set if none
|
||||
* @since 1.17.0
|
||||
*/
|
||||
public Set<Flag> getSubflags() {
|
||||
return subflags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Flag [id=" + id + "]";
|
||||
@ -480,6 +513,9 @@ public class Flag implements Comparable<Flag> {
|
||||
// Mode
|
||||
private Mode mode = Mode.EXPERT;
|
||||
|
||||
// Subflags
|
||||
private Set<Flag> subflags;
|
||||
|
||||
/**
|
||||
* Builder for making flags
|
||||
* @param id - a unique id that MUST be the same as the enum of the flag
|
||||
@ -488,6 +524,7 @@ public class Flag implements Comparable<Flag> {
|
||||
public Builder(String id, Material icon) {
|
||||
this.id = id;
|
||||
this.icon = icon;
|
||||
this.subflags = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -595,6 +632,19 @@ public class Flag implements Comparable<Flag> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subflags and designate this flag as a parent flag.
|
||||
* Subflags have their state simultaneously changed with the parent flag.
|
||||
* Take extra care to ensure that subflags have the same number of possible values as the parent flag.
|
||||
* @param flags all Flags that are subflags
|
||||
* @return Builder - flag builder
|
||||
* @since 1.17.0
|
||||
*/
|
||||
public Builder subflags(Flag... flags) {
|
||||
this.subflags.addAll(Arrays.asList(flags));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the flag
|
||||
* @return Flag
|
||||
|
@ -90,6 +90,12 @@ public class CycleClick implements PanelItem.ClickHandler {
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_OFF, 1F, 1F);
|
||||
// Fire event
|
||||
Bukkit.getPluginManager().callEvent(new FlagProtectionChangeEvent(island, user.getUniqueId(), flag, island.getFlag(flag)));
|
||||
|
||||
// Subflag support
|
||||
if (flag.hasSubflags()) {
|
||||
// Fire events for all subflags as well
|
||||
flag.getSubflags().forEach(subflag -> Bukkit.getPluginManager().callEvent(new FlagProtectionChangeEvent(island, user.getUniqueId(), subflag, island.getFlag(subflag))));
|
||||
}
|
||||
} else if (click.equals(ClickType.RIGHT)) {
|
||||
if (currentRank <= minRank) {
|
||||
island.setFlag(flag, maxRank);
|
||||
@ -99,6 +105,12 @@ public class CycleClick implements PanelItem.ClickHandler {
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F);
|
||||
// Fire event
|
||||
Bukkit.getPluginManager().callEvent(new FlagProtectionChangeEvent(island, user.getUniqueId(), flag, island.getFlag(flag)));
|
||||
|
||||
// Subflag support
|
||||
if (flag.hasSubflags()) {
|
||||
// Fire events for all subflags as well
|
||||
flag.getSubflags().forEach(subflag -> Bukkit.getPluginManager().callEvent(new FlagProtectionChangeEvent(island, user.getUniqueId(), subflag, island.getFlag(subflag))));
|
||||
}
|
||||
} else if (click.equals(ClickType.SHIFT_LEFT) && user.isOp()) {
|
||||
if (!plugin.getIWM().getHiddenFlags(user.getWorld()).contains(flag.getID())) {
|
||||
plugin.getIWM().getHiddenFlags(user.getWorld()).add(flag.getID());
|
||||
|
@ -77,6 +77,11 @@ public class IslandToggleClick implements ClickHandler {
|
||||
island.setCooldown(flag);
|
||||
// Fire event
|
||||
Bukkit.getPluginManager().callEvent(new FlagSettingChangeEvent(island, user.getUniqueId(), flag, island.isAllowed(flag)));
|
||||
|
||||
if (flag.hasSubflags()) {
|
||||
// Fire events for all subflags as well
|
||||
flag.getSubflags().forEach(subflag -> Bukkit.getPluginManager().callEvent(new FlagSettingChangeEvent(island, user.getUniqueId(), subflag, island.isAllowed(subflag))));
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -61,6 +61,12 @@ public class WorldToggleClick implements ClickHandler {
|
||||
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F);
|
||||
// Fire event
|
||||
Bukkit.getPluginManager().callEvent(new FlagWorldSettingChangeEvent(user.getWorld(), user.getUniqueId(), flag, flag.isSetForWorld(user.getWorld())));
|
||||
|
||||
// Subflag support
|
||||
if (flag.hasSubflags()) {
|
||||
// Fire events for all subflags as well
|
||||
flag.getSubflags().forEach(subflag -> Bukkit.getPluginManager().callEvent(new FlagWorldSettingChangeEvent(user.getWorld(), user.getUniqueId(), subflag, subflag.isSetForWorld(user.getWorld()))));
|
||||
}
|
||||
}
|
||||
|
||||
// Save world settings
|
||||
|
@ -1,6 +1,7 @@
|
||||
package world.bentobox.bentobox.database.objects;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
@ -823,11 +824,28 @@ public class Island implements DataObject, MetaDataAble {
|
||||
|
||||
/**
|
||||
* Set the Island Guard flag rank
|
||||
* This method affects subflags (if the given flag is a parent flag)
|
||||
* @param flag - flag
|
||||
* @param value - Use RanksManager settings, e.g. RanksManager.MEMBER
|
||||
*/
|
||||
public void setFlag(Flag flag, int value) {
|
||||
setFlag(flag, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Island Guard flag rank
|
||||
* Also specify whether subflags are affected by this method call
|
||||
* @param flag - flag
|
||||
* @param value - Use RanksManager settings, e.g. RanksManager.MEMBER
|
||||
* @param doSubflags - whether to set subflags
|
||||
*/
|
||||
public void setFlag(Flag flag, int value, boolean doSubflags) {
|
||||
flags.put(flag, value);
|
||||
// Subflag support
|
||||
if (doSubflags && flag.hasSubflags()) {
|
||||
// Ensure that a subflag isn't a subflag of itself or else we're in trouble!
|
||||
flag.getSubflags().forEach(subflag -> setFlag(subflag, value, true));
|
||||
}
|
||||
setChanged();
|
||||
}
|
||||
|
||||
@ -1075,7 +1093,14 @@ public class Island implements DataObject, MetaDataAble {
|
||||
// Fixes #getLastPlayed() returning 0 when it is the owner's first connection.
|
||||
long lastPlayed = (Bukkit.getServer().getOfflinePlayer(getOwner()).getLastPlayed() != 0) ?
|
||||
Bukkit.getServer().getOfflinePlayer(getOwner()).getLastPlayed() : Bukkit.getServer().getOfflinePlayer(getOwner()).getFirstPlayed();
|
||||
user.sendMessage("commands.admin.info.last-login","[date]", new Date(lastPlayed).toString());
|
||||
String formattedDate;
|
||||
try {
|
||||
String dateTimeFormat = plugin.getLocalesManager().get("commands.admin.info.last-login-date-time-format");
|
||||
formattedDate = new SimpleDateFormat(dateTimeFormat).format(new Date(lastPlayed));
|
||||
} catch (NullPointerException | IllegalArgumentException ignored) {
|
||||
formattedDate = new Date(lastPlayed).toString();
|
||||
}
|
||||
user.sendMessage("commands.admin.info.last-login","[date]", formattedDate);
|
||||
|
||||
user.sendMessage("commands.admin.info.deaths", "[number]", String.valueOf(plugin.getPlayers().getDeaths(getWorld(), getOwner())));
|
||||
String resets = String.valueOf(plugin.getPlayers().getResets(getWorld(), getOwner()));
|
||||
@ -1124,23 +1149,50 @@ public class Island implements DataObject, MetaDataAble {
|
||||
|
||||
/**
|
||||
* Toggles a settings flag
|
||||
* This method affects subflags (if the given flag is a parent flag)
|
||||
* @param flag - flag
|
||||
*/
|
||||
public void toggleFlag(Flag flag) {
|
||||
toggleFlag(flag, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a settings flag
|
||||
* Also specify whether subflags are affected by this method call
|
||||
* @param flag - flag
|
||||
*/
|
||||
public void toggleFlag(Flag flag, boolean doSubflags) {
|
||||
boolean newToggleValue = !isAllowed(flag); // Use for subflags
|
||||
if (flag.getType().equals(Flag.Type.SETTING) || flag.getType().equals(Flag.Type.WORLD_SETTING)) {
|
||||
setSettingsFlag(flag, !isAllowed(flag));
|
||||
setSettingsFlag(flag, newToggleValue, doSubflags);
|
||||
}
|
||||
setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of a settings flag
|
||||
* This method affects subflags (if the given flag is a parent flag)
|
||||
* @param flag - flag
|
||||
* @param state - true or false
|
||||
*/
|
||||
public void setSettingsFlag(Flag flag, boolean state) {
|
||||
setSettingsFlag(flag, state, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of a settings flag
|
||||
* Also specify whether subflags are affected by this method call
|
||||
* @param flag - flag
|
||||
* @param state - true or false
|
||||
*/
|
||||
public void setSettingsFlag(Flag flag, boolean state, boolean doSubflags) {
|
||||
int newState = state ? 1 : -1;
|
||||
if (flag.getType().equals(Flag.Type.SETTING) || flag.getType().equals(Flag.Type.WORLD_SETTING)) {
|
||||
flags.put(flag, state ? 1 : -1);
|
||||
flags.put(flag, newState);
|
||||
if (doSubflags && flag.hasSubflags()) {
|
||||
// If we have circular subflags or a flag is a subflag of itself we are in trouble!
|
||||
flag.getSubflags().forEach(subflag -> setSettingsFlag(subflag, state, true));
|
||||
}
|
||||
}
|
||||
setChanged();
|
||||
}
|
||||
|
@ -102,6 +102,9 @@ public class JoinLeaveListener implements Listener {
|
||||
plugin.getIslands().getMaxMembers(i, RanksManager.TRUSTED_RANK);
|
||||
plugin.getIslands().getMaxHomes(i);
|
||||
});
|
||||
|
||||
// Add a player to the bStats cache.
|
||||
plugin.getMetrics().ifPresent(bStats -> bStats.addPlayer(playerUUID));
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,7 +95,7 @@ public class BlockInteractionListener extends FlagListener {
|
||||
private void checkClickedBlock(Event e, Player player, Location loc, Material type) {
|
||||
// Handle pots
|
||||
if (type.name().startsWith("POTTED")) {
|
||||
checkIsland(e, player, loc, Flags.CONTAINER);
|
||||
checkIsland(e, player, loc, Flags.FLOWER_POT);
|
||||
return;
|
||||
}
|
||||
if (Tag.ANVIL.isTagged(type)) {
|
||||
@ -115,7 +115,7 @@ public class BlockInteractionListener extends FlagListener {
|
||||
return;
|
||||
}
|
||||
if (Tag.SHULKER_BOXES.isTagged(type)) {
|
||||
checkIsland(e, player, loc, Flags.CONTAINER);
|
||||
checkIsland(e, player, loc, Flags.SHULKER_BOX);
|
||||
return;
|
||||
}
|
||||
if (Tag.TRAPDOORS.isTagged(type)) {
|
||||
@ -136,12 +136,20 @@ public class BlockInteractionListener extends FlagListener {
|
||||
checkIsland(e, player, loc, Flags.HIVE);
|
||||
break;
|
||||
case BARREL:
|
||||
checkIsland(e, player, loc, Flags.BARREL);
|
||||
break;
|
||||
case CHEST:
|
||||
case CHEST_MINECART:
|
||||
checkIsland(e, player, loc, Flags.CHEST);
|
||||
break;
|
||||
case TRAPPED_CHEST:
|
||||
checkIsland(e, player, loc, Flags.TRAPPED_CHEST);
|
||||
break;
|
||||
case FLOWER_POT:
|
||||
checkIsland(e, player, loc, Flags.FLOWER_POT);
|
||||
break;
|
||||
case COMPOSTER:
|
||||
checkIsland(e, player, loc, Flags.CONTAINER);
|
||||
checkIsland(e, player, loc, Flags.COMPOSTER);
|
||||
break;
|
||||
case DISPENSER:
|
||||
checkIsland(e, player, loc, Flags.DISPENSER);
|
||||
|
@ -1,15 +1,20 @@
|
||||
package world.bentobox.bentobox.listeners.flags.protection;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Barrel;
|
||||
import org.bukkit.block.Beacon;
|
||||
import org.bukkit.block.BrewingStand;
|
||||
import org.bukkit.block.Chest;
|
||||
import org.bukkit.block.Dispenser;
|
||||
import org.bukkit.block.Dropper;
|
||||
import org.bukkit.block.Furnace;
|
||||
import org.bukkit.block.Hopper;
|
||||
import org.bukkit.block.ShulkerBox;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.NPC;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.minecart.HopperMinecart;
|
||||
import org.bukkit.entity.minecart.StorageMinecart;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
@ -61,6 +66,29 @@ public class InventoryListener extends FlagListener {
|
||||
else if (inventoryHolder instanceof NPC) {
|
||||
checkIsland(e, player, e.getInventory().getLocation(), Flags.TRADING);
|
||||
}
|
||||
else if (inventoryHolder instanceof Barrel) {
|
||||
checkIsland(e, player, e.getInventory().getLocation(), Flags.BARREL);
|
||||
}
|
||||
else if (inventoryHolder instanceof ShulkerBox) {
|
||||
checkIsland(e, player, e.getInventory().getLocation(), Flags.SHULKER_BOX);
|
||||
}
|
||||
else if (inventoryHolder instanceof Chest) {
|
||||
// To differentiate between a Chest and a Trapped Chest we need to get the Block corresponding to the inventory
|
||||
Chest chestInventoryHolder = (Chest) inventoryHolder;
|
||||
try {
|
||||
if (chestInventoryHolder.getBlock().getType() == Material.TRAPPED_CHEST) {
|
||||
checkIsland(e, player, e.getInventory().getLocation(), Flags.TRAPPED_CHEST);
|
||||
} else {
|
||||
checkIsland(e, player, e.getInventory().getLocation(), Flags.CHEST);
|
||||
}
|
||||
} catch (IllegalStateException ignored) {
|
||||
// Thrown if the Chest corresponds to a block that isn't placed (how did we get here?)
|
||||
checkIsland(e, player, e.getInventory().getLocation(), Flags.CHEST);
|
||||
}
|
||||
}
|
||||
else if (inventoryHolder instanceof StorageMinecart) {
|
||||
checkIsland(e, player, e.getInventory().getLocation(), Flags.CHEST);
|
||||
}
|
||||
else if (!(inventoryHolder instanceof Player)) {
|
||||
// All other containers
|
||||
checkIsland(e, player, e.getInventory().getLocation(), Flags.CONTAINER);
|
||||
|
@ -0,0 +1,39 @@
|
||||
package world.bentobox.bentobox.listeners.flags.worldsettings;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import world.bentobox.bentobox.api.flags.FlagListener;
|
||||
import world.bentobox.bentobox.database.objects.Island;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Prevents visitors from losing their items if they
|
||||
* die on an island in which they are a visitor.
|
||||
* Handles {@link world.bentobox.bentobox.lists.Flags#VISITOR_KEEP_INVENTORY}.
|
||||
* @author jstnf
|
||||
* @since 1.17.0
|
||||
*/
|
||||
public class VisitorKeepInventoryListener extends FlagListener {
|
||||
|
||||
@EventHandler (priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onVisitorDeath(PlayerDeathEvent e) {
|
||||
World world = Util.getWorld(e.getEntity().getWorld());
|
||||
if (!getIWM().inWorld(world) || !Flags.VISITOR_KEEP_INVENTORY.isSetForWorld(world)) {
|
||||
// If the player dies outside of the island world, don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Island> island = getIslands().getProtectedIslandAt(e.getEntity().getLocation());
|
||||
if (island.isPresent() && !island.get().getMemberSet().contains(e.getEntity().getUniqueId())) {
|
||||
e.setKeepInventory(true);
|
||||
e.setKeepLevel(true);
|
||||
e.getDrops().clear();
|
||||
e.setDroppedExp(0);
|
||||
}
|
||||
}
|
||||
}
|
@ -62,6 +62,7 @@ import world.bentobox.bentobox.listeners.flags.worldsettings.PistonPushListener;
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.RemoveMobsListener;
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.SpawnerSpawnEggsListener;
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.TreesGrowingOutsideRangeListener;
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.VisitorKeepInventoryListener;
|
||||
import world.bentobox.bentobox.listeners.flags.worldsettings.WitherListener;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
@ -110,7 +111,14 @@ public final class Flags {
|
||||
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).mode(Flag.Mode.ADVANCED).build();
|
||||
public static final Flag CONTAINER = new Flag.Builder("CONTAINER", Material.CHEST).mode(Flag.Mode.BASIC).build();
|
||||
// START CONTAINER split
|
||||
public static final Flag CHEST = new Flag.Builder("CHEST", Material.CHEST).mode(Flag.Mode.ADVANCED).build();
|
||||
public static final Flag BARREL = new Flag.Builder("BARREL", Material.BARREL).mode(Flag.Mode.ADVANCED).build();
|
||||
public static final Flag COMPOSTER = new Flag.Builder("COMPOSTER", Material.COMPOSTER).mode(Flag.Mode.ADVANCED).build();
|
||||
public static final Flag FLOWER_POT = new Flag.Builder("FLOWER_POT", Material.FLOWER_POT).mode(Flag.Mode.ADVANCED).build();
|
||||
public static final Flag SHULKER_BOX = new Flag.Builder("SHULKER_BOX", Material.SHULKER_BOX).mode(Flag.Mode.ADVANCED).build();
|
||||
public static final Flag TRAPPED_CHEST = new Flag.Builder("TRAPPED_CHEST", Material.TRAPPED_CHEST).mode(Flag.Mode.ADVANCED).build();
|
||||
// END CONTAINER split
|
||||
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();
|
||||
@ -129,6 +137,9 @@ public final class Flags {
|
||||
public static final Flag ITEM_FRAME = new Flag.Builder("ITEM_FRAME", Material.ITEM_FRAME).mode(Flag.Mode.ADVANCED).build();
|
||||
public static final Flag CAKE = new Flag.Builder("CAKE", Material.CAKE).build();
|
||||
public static final Flag HIVE = new Flag.Builder("HIVE", Material.HONEY_BOTTLE).type(Type.PROTECTION).build();
|
||||
public static final Flag CONTAINER = new Flag.Builder("CONTAINER", Material.CHEST).mode(Flag.Mode.BASIC)
|
||||
.subflags(BREWING, BARREL, CHEST, COMPOSTER, FLOWER_POT, SHULKER_BOX, TRAPPED_CHEST, FURNACE, JUKEBOX, DISPENSER, DROPPER, HOPPER, ITEM_FRAME, HIVE)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Prevents players from interacting with the Dragon Egg.
|
||||
@ -526,6 +537,13 @@ public final class Flags {
|
||||
*/
|
||||
public static final Flag PETS_STAY_AT_HOME = new Flag.Builder("PETS_STAY_AT_HOME", Material.TROPICAL_FISH).listener(new PetTeleportListener()).type(Type.WORLD_SETTING).defaultSetting(true).build();
|
||||
|
||||
/**
|
||||
* Toggles whether island visitors keep their items if they die on another player's island.
|
||||
* @since 1.17.0
|
||||
* @see VisitorKeepInventoryListener
|
||||
*/
|
||||
public static final Flag VISITOR_KEEP_INVENTORY = new Flag.Builder("VISITOR_KEEP_INVENTORY", Material.TOTEM_OF_UNDYING).listener(new VisitorKeepInventoryListener()).type(Type.WORLD_SETTING).defaultSetting(false).build();
|
||||
|
||||
/**
|
||||
* Provides a list of all the Flag instances contained in this class using reflection.
|
||||
* Deprecated Flags are ignored.
|
||||
|
@ -188,6 +188,7 @@ commands:
|
||||
island-uuid: "UUID: [uuid]"
|
||||
owner: "Owner: [owner] ([uuid])"
|
||||
last-login: "Last login: [date]"
|
||||
last-login-date-time-format: "EEE MMM dd HH:mm:ss zzz yyyy"
|
||||
deaths: "Deaths: [number]"
|
||||
resets-left: "Resets: [number] (Max: [total])"
|
||||
team-members-title: "Team members:"
|
||||
@ -787,15 +788,45 @@ protection:
|
||||
name: "Cakes"
|
||||
hint: "Cake eating disabled"
|
||||
CONTAINER:
|
||||
name: "Containers"
|
||||
name: "All containers"
|
||||
description: |-
|
||||
&a Toggle interaction with chests,
|
||||
&a shulker boxes and flower pots,
|
||||
&a composters and barrels.
|
||||
&a Toggle interaction with all containers.
|
||||
&a Includes: Barrel, bee hive, brewing stand,
|
||||
&a chest, composter, dispenser, dropper,
|
||||
&a flower pot, furnace, hopper, item frame,
|
||||
&a jukebox, minecart chest, shulker box,
|
||||
&a trapped chest.
|
||||
|
||||
&7 Other containers are handled
|
||||
&7 by dedicated flags.
|
||||
&7 Changing individual settings overrides
|
||||
&7 this flag.
|
||||
hint: "Container access disabled"
|
||||
CHEST:
|
||||
name: "Chests and minecart chests"
|
||||
description: |-
|
||||
&a Toggle interaction with chests
|
||||
&a and chest minecarts.
|
||||
&a (does not include trapped chests)
|
||||
hint: "Chest access disabled"
|
||||
BARREL:
|
||||
name: "Barrels"
|
||||
description: "Toggle barrel interaction"
|
||||
hint: "Barrel access disabled"
|
||||
COMPOSTER:
|
||||
name: "Composters"
|
||||
description: "Toggle composter interaction"
|
||||
hint: "Composter interaction disabled"
|
||||
FLOWER_POT:
|
||||
name: "Flower pots"
|
||||
description: "Toggle flower pot interaction"
|
||||
hint: "Flower pot interaction disabled"
|
||||
SHULKER_BOX:
|
||||
name: "Shulker boxes"
|
||||
description: "Toggle shulker box interaction"
|
||||
hint: "Shulker box access disabled"
|
||||
TRAPPED_CHEST:
|
||||
name: "Trapped chests"
|
||||
description: "Toggle trapped chest interaction"
|
||||
hint: "Trapped chest access disabled"
|
||||
DISPENSER:
|
||||
name: "Dispensers"
|
||||
description: "Toggle dispenser interaction"
|
||||
@ -1271,6 +1302,15 @@ protection:
|
||||
&a back to their island using commands
|
||||
&a if they are falling.
|
||||
hint: "&c You cannot do that while falling."
|
||||
VISITOR_KEEP_INVENTORY:
|
||||
name: "Visitors keep inventory on death"
|
||||
description: |-
|
||||
&a Prevent players from losing their
|
||||
&a items and experience if they die on
|
||||
&a an island in which they are a visitor.
|
||||
&a
|
||||
&a Island members still lose their items
|
||||
&a if they die on their own island!
|
||||
WITHER_DAMAGE:
|
||||
name: "Toggle wither damage"
|
||||
description: |-
|
||||
|
@ -24,6 +24,7 @@ softdepend:
|
||||
- LangUtils
|
||||
- WildStacker
|
||||
- LuckPerms
|
||||
- HolographicDisplays
|
||||
|
||||
permissions:
|
||||
bentobox.admin:
|
||||
|
@ -70,14 +70,14 @@ public class BlockInteractionListenerTest extends AbstractCommonSetup {
|
||||
when(Tag.BEDS.isTagged(Material.WHITE_BED)).thenReturn(true);
|
||||
clickedBlocks.put(Material.BREWING_STAND, Flags.BREWING);
|
||||
clickedBlocks.put(Material.CAULDRON, Flags.BREWING);
|
||||
clickedBlocks.put(Material.BARREL, Flags.CONTAINER);
|
||||
clickedBlocks.put(Material.CHEST, Flags.CONTAINER);
|
||||
clickedBlocks.put(Material.CHEST_MINECART, Flags.CONTAINER);
|
||||
clickedBlocks.put(Material.TRAPPED_CHEST, Flags.CONTAINER);
|
||||
clickedBlocks.put(Material.SHULKER_BOX, Flags.CONTAINER);
|
||||
clickedBlocks.put(Material.BARREL, Flags.BARREL);
|
||||
clickedBlocks.put(Material.CHEST, Flags.CHEST);
|
||||
clickedBlocks.put(Material.CHEST_MINECART, Flags.CHEST);
|
||||
clickedBlocks.put(Material.TRAPPED_CHEST, Flags.TRAPPED_CHEST);
|
||||
clickedBlocks.put(Material.SHULKER_BOX, Flags.SHULKER_BOX);
|
||||
when(Tag.SHULKER_BOXES.isTagged(Material.SHULKER_BOX)).thenReturn(true);
|
||||
clickedBlocks.put(Material.FLOWER_POT, Flags.CONTAINER);
|
||||
clickedBlocks.put(Material.COMPOSTER, Flags.CONTAINER);
|
||||
clickedBlocks.put(Material.FLOWER_POT, Flags.FLOWER_POT);
|
||||
clickedBlocks.put(Material.COMPOSTER, Flags.COMPOSTER);
|
||||
clickedBlocks.put(Material.DISPENSER, Flags.DISPENSER);
|
||||
clickedBlocks.put(Material.DROPPER, Flags.DROPPER);
|
||||
clickedBlocks.put(Material.HOPPER, Flags.HOPPER);
|
||||
|
Loading…
Reference in New Issue
Block a user