mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-03-12 22:59:15 +01:00
Implements adding unknown default island flag values in settings. (#2001)
* Implements option to define non-existing flags in WorldSettings. This change adds 2 new methods in WorldSettings: * WorldSettings#getDefaultIslandFlagNames * WorldSettings#getDefaultIslandSettingNames These methods replace getDefaultIslandFlags and getDefaultIslandSettings methods. Default implementation just reads values from replaced methods. Fixes #1830 * Implement conversion from flag id to actual flag object. Replaces flag assignment to new island based on flag id's. Fixes #1830 * Switch from Flag object to String object in Island class. This switch allows to keep flags that are not present in current BentoBox installation. Otherwise, unknown flags may cause an issues. Fixes #1830 * Implement FlagBooleanSerializer. This serializer converts input map of String, Boolean to map of String, Integer. This map is used to read island setting flags, and integer value is not classic boolean values. (0 for true and -1 for false). Fixes #1830
This commit is contained in:
parent
d8fa029ac9
commit
db323390cf
@ -2,6 +2,7 @@ package world.bentobox.bentobox.api.configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@ -31,11 +32,54 @@ public interface WorldSettings extends ConfigObject {
|
||||
|
||||
/**
|
||||
* @return default rank settings for new islands
|
||||
* @deprecated since 1.21
|
||||
* Map of Flag, Integer does not allow to load other plugin/addon flags.
|
||||
* It cannot be replaced with Map of String, Integer due to compatibility issues.
|
||||
* @see WorldSettings#getDefaultIslandFlagNames()
|
||||
*/
|
||||
@Deprecated
|
||||
Map<Flag, Integer> getDefaultIslandFlags();
|
||||
|
||||
/**
|
||||
* Return map of flags ID's linked to default rank for new island.
|
||||
* This is necessary so users could specify any flag names in settings file from other plugins and addons.
|
||||
* Otherwise, Flag reader would mark flag as invalid and remove it.
|
||||
* Default implementation is compatibility layer so GameModes that are not upgraded still works.
|
||||
* @since 1.21
|
||||
* @return default rank settings for new islands.
|
||||
*/
|
||||
default Map<String, Integer> getDefaultIslandFlagNames()
|
||||
{
|
||||
Map<String, Integer> flags = new HashMap<>();
|
||||
this.getDefaultIslandFlags().forEach((key, value) -> flags.put(key.getID(), value));
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return default settings for new
|
||||
* @deprecated since 1.21
|
||||
* Map of Flag, Integer does not allow to load other plugin/addon flags.
|
||||
* It cannot be replaced with Map of String, Integer due to compatibility issues.
|
||||
* @see WorldSettings#getDefaultIslandSettingNames()
|
||||
*/
|
||||
@Deprecated
|
||||
Map<Flag, Integer> getDefaultIslandSettings();
|
||||
|
||||
/**
|
||||
* Return map of flags ID's linked to default settings for new island.
|
||||
* This is necessary so users could specify any flag names in settings file from other plugins and addons.
|
||||
* Otherwise, Flag reader would mark flag as invalid and remove it.
|
||||
* Default implementation is compatibility layer so GameModes that are not upgraded still works.
|
||||
* @since 1.21
|
||||
* @return default settings for new islands.
|
||||
*/
|
||||
default Map<String, Integer> getDefaultIslandSettingNames()
|
||||
{
|
||||
Map<String, Integer> flags = new HashMap<>();
|
||||
this.getDefaultIslandSettings().forEach((key, value) -> flags.put(key.getID(), value));
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the world difficulty
|
||||
* @return difficulty
|
||||
|
@ -39,8 +39,6 @@ import world.bentobox.bentobox.api.metadata.MetaDataAble;
|
||||
import world.bentobox.bentobox.api.metadata.MetaDataValue;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.database.objects.adapters.Adapter;
|
||||
import world.bentobox.bentobox.database.objects.adapters.FlagSerializer;
|
||||
import world.bentobox.bentobox.database.objects.adapters.FlagSerializer3;
|
||||
import world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter;
|
||||
import world.bentobox.bentobox.lists.Flags;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
@ -159,9 +157,8 @@ public class Island implements DataObject, MetaDataAble {
|
||||
private boolean purgeProtected = false;
|
||||
|
||||
//// Protection flags ////
|
||||
@Adapter(FlagSerializer.class)
|
||||
@Expose
|
||||
private Map<Flag, Integer> flags = new HashMap<>();
|
||||
private Map<String, Integer> flags = new HashMap<>();
|
||||
|
||||
//// Island History ////
|
||||
@Adapter(LogEntryListAdapter.class)
|
||||
@ -180,9 +177,8 @@ public class Island implements DataObject, MetaDataAble {
|
||||
/**
|
||||
* Used to store flag cooldowns for this island
|
||||
*/
|
||||
@Adapter(FlagSerializer3.class)
|
||||
@Expose
|
||||
private Map<Flag, Long> cooldowns = new HashMap<>();
|
||||
private Map<String, Long> cooldowns = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Commands and the rank required to use them for this island
|
||||
@ -368,13 +364,13 @@ public class Island implements DataObject, MetaDataAble {
|
||||
* @return flag value
|
||||
*/
|
||||
public int getFlag(@NonNull Flag flag) {
|
||||
return flags.computeIfAbsent(flag, k -> flag.getDefaultRank());
|
||||
return flags.computeIfAbsent(flag.getID(), k -> flag.getDefaultRank());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the flags
|
||||
*/
|
||||
public Map<Flag, Integer> getFlags() {
|
||||
public Map<String, Integer> getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
@ -722,9 +718,7 @@ public class Island implements DataObject, MetaDataAble {
|
||||
*/
|
||||
@NonNull
|
||||
public List<Player> getVisitors() {
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(player -> playerIsVisitor(player))
|
||||
.collect(Collectors.toList());
|
||||
return Bukkit.getOnlinePlayers().stream().filter(this::playerIsVisitor).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -736,7 +730,7 @@ public class Island implements DataObject, MetaDataAble {
|
||||
* @see #getVisitors()
|
||||
*/
|
||||
public boolean hasVisitors() {
|
||||
return Bukkit.getOnlinePlayers().stream().anyMatch(player -> playerIsVisitor(player));
|
||||
return Bukkit.getOnlinePlayers().stream().anyMatch(this::playerIsVisitor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -865,7 +859,7 @@ public class Island implements DataObject, MetaDataAble {
|
||||
* @param doSubflags - whether to set subflags
|
||||
*/
|
||||
public void setFlag(Flag flag, int value, boolean doSubflags) {
|
||||
flags.put(flag, value);
|
||||
flags.put(flag.getID(), value);
|
||||
// Subflag support
|
||||
if (doSubflags && flag.hasSubflags()) {
|
||||
// Ensure that a subflag isn't a subflag of itself or else we're in trouble!
|
||||
@ -877,7 +871,7 @@ public class Island implements DataObject, MetaDataAble {
|
||||
/**
|
||||
* @param flags the flags to set
|
||||
*/
|
||||
public void setFlags(Map<Flag, Integer> flags) {
|
||||
public void setFlags(Map<String, Integer> flags) {
|
||||
this.flags = flags;
|
||||
setChanged();
|
||||
}
|
||||
@ -888,11 +882,13 @@ public class Island implements DataObject, MetaDataAble {
|
||||
*/
|
||||
public void setFlagsDefaults() {
|
||||
BentoBox plugin = BentoBox.getInstance();
|
||||
Map<Flag, Integer> result = new HashMap<>();
|
||||
plugin.getFlagsManager().getFlags().stream().filter(f -> f.getType().equals(Flag.Type.PROTECTION))
|
||||
.forEach(f -> result.put(f, plugin.getIWM().getDefaultIslandFlags(world).getOrDefault(f, f.getDefaultRank())));
|
||||
plugin.getFlagsManager().getFlags().stream().filter(f -> f.getType().equals(Flag.Type.SETTING))
|
||||
.forEach(f -> result.put(f, plugin.getIWM().getDefaultIslandSettings(world).getOrDefault(f, f.getDefaultRank())));
|
||||
Map<String, Integer> result = new HashMap<>();
|
||||
plugin.getFlagsManager().getFlags().stream().
|
||||
filter(f -> f.getType().equals(Flag.Type.PROTECTION)).
|
||||
forEach(f -> result.put(f.getID(), plugin.getIWM().getDefaultIslandFlags(world).getOrDefault(f, f.getDefaultRank())));
|
||||
plugin.getFlagsManager().getFlags().stream().
|
||||
filter(f -> f.getType().equals(Flag.Type.SETTING)).
|
||||
forEach(f -> result.put(f.getID(), plugin.getIWM().getDefaultIslandSettings(world).getOrDefault(f, f.getDefaultRank())));
|
||||
this.setFlags(result);
|
||||
setChanged();
|
||||
}
|
||||
@ -1134,7 +1130,7 @@ public class Island implements DataObject, MetaDataAble {
|
||||
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, newState);
|
||||
flags.put(flag.getID(), 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));
|
||||
@ -1275,10 +1271,10 @@ public class Island implements DataObject, MetaDataAble {
|
||||
* @since 1.6.0
|
||||
*/
|
||||
public boolean isCooldown(Flag flag) {
|
||||
if (cooldowns.containsKey(flag) && cooldowns.get(flag) > System.currentTimeMillis()) {
|
||||
if (cooldowns.containsKey(flag.getID()) && cooldowns.get(flag.getID()) > System.currentTimeMillis()) {
|
||||
return true;
|
||||
}
|
||||
cooldowns.remove(flag);
|
||||
cooldowns.remove(flag.getID());
|
||||
setChanged();
|
||||
return false;
|
||||
}
|
||||
@ -1288,21 +1284,21 @@ public class Island implements DataObject, MetaDataAble {
|
||||
* @param flag - Flag to cooldown
|
||||
*/
|
||||
public void setCooldown(Flag flag) {
|
||||
cooldowns.put(flag, flag.getCooldown() * 1000L + System.currentTimeMillis());
|
||||
cooldowns.put(flag.getID(), flag.getCooldown() * 1000L + System.currentTimeMillis());
|
||||
setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cooldowns
|
||||
*/
|
||||
public Map<Flag, Long> getCooldowns() {
|
||||
public Map<String, Long> getCooldowns() {
|
||||
return cooldowns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cooldowns the cooldowns to set
|
||||
*/
|
||||
public void setCooldowns(Map<Flag, Long> cooldowns) {
|
||||
public void setCooldowns(Map<String, Long> cooldowns) {
|
||||
this.cooldowns = cooldowns;
|
||||
setChanged();
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
package world.bentobox.bentobox.database.objects.adapters;
|
||||
|
||||
|
||||
import org.bukkit.configuration.MemorySection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
|
||||
/**
|
||||
* This Serializer migrates Map of String, Boolean to Map of String, Integer in serialization process.
|
||||
* It is necessary because current implementation requires flags to be mapped to Integer value.
|
||||
* @author BONNe
|
||||
*/
|
||||
public class FlagBooleanSerializer implements AdapterInterface<Map<String, Integer>, Map<String, Boolean>>
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, Integer> deserialize(Object object)
|
||||
{
|
||||
Map<String, Integer> result = new HashMap<>();
|
||||
if (object == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
// For YAML
|
||||
if (object instanceof MemorySection section)
|
||||
{
|
||||
for (String key : section.getKeys(false))
|
||||
{
|
||||
result.put(key, section.getBoolean(key) ? 0 : -1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Entry<String, Boolean> en : ((Map<String, Boolean>) object).entrySet())
|
||||
{
|
||||
result.put(en.getKey(), en.getValue() ? 0 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, Boolean> serialize(Object object)
|
||||
{
|
||||
Map<String, Boolean> result = new HashMap<>();
|
||||
|
||||
if (object == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<String, Integer> flags = (Map<String, Integer>) object;
|
||||
|
||||
for (Entry<String, Integer> en : flags.entrySet())
|
||||
{
|
||||
result.put(en.getKey(), en.getValue() >= 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -171,10 +171,13 @@ public class IslandWorldManager {
|
||||
}
|
||||
|
||||
// Set default island settings
|
||||
plugin.getFlagsManager().getFlags().stream().filter(f -> f.getType().equals(Flag.Type.PROTECTION))
|
||||
.forEach(f -> settings.getDefaultIslandFlags().putIfAbsent(f, f.getDefaultRank()));
|
||||
plugin.getFlagsManager().getFlags().stream().filter(f -> f.getType().equals(Flag.Type.SETTING))
|
||||
.forEach(f -> settings.getDefaultIslandSettings().putIfAbsent(f, f.getDefaultRank()));
|
||||
plugin.getFlagsManager().getFlags().stream().
|
||||
filter(f -> f.getType().equals(Flag.Type.PROTECTION)).
|
||||
forEach(f -> settings.getDefaultIslandFlagNames().putIfAbsent(f.getID(), f.getDefaultRank()));
|
||||
plugin.getFlagsManager().getFlags().stream().
|
||||
filter(f -> f.getType().equals(Flag.Type.SETTING)).
|
||||
forEach(f -> settings.getDefaultIslandSettingNames().putIfAbsent(f.getID(), f.getDefaultRank()));
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
// Set world difficulty
|
||||
Difficulty diff = settings.getDifficulty();
|
||||
@ -477,7 +480,9 @@ public class IslandWorldManager {
|
||||
* @return Friendly name or world name if world is not a game world
|
||||
*/
|
||||
public String getFriendlyName(@NonNull World world) {
|
||||
return gameModes.containsKey(world) ? gameModes.get(world).getWorldSettings().getFriendlyName() : world.getName();
|
||||
return gameModes.containsKey(world) ?
|
||||
gameModes.get(world).getWorldSettings().getFriendlyName() :
|
||||
world.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -699,8 +704,11 @@ public class IslandWorldManager {
|
||||
* @param world - world
|
||||
* @return default rank settings for new islands.
|
||||
*/
|
||||
public Map<Flag, Integer> getDefaultIslandFlags(@NonNull World world) {
|
||||
return gameModes.containsKey(world) ? gameModes.get(world).getWorldSettings().getDefaultIslandFlags() : Collections.emptyMap();
|
||||
public Map<Flag, Integer> getDefaultIslandFlags(@NonNull World world)
|
||||
{
|
||||
return this.gameModes.containsKey(world) ?
|
||||
this.convertToFlags(this.gameModes.get(world).getWorldSettings().getDefaultIslandFlagNames()) :
|
||||
Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -715,12 +723,14 @@ public class IslandWorldManager {
|
||||
/**
|
||||
* Return island setting defaults for world
|
||||
*
|
||||
* @param world
|
||||
* - world
|
||||
* @param world - world
|
||||
* @return default settings for new islands
|
||||
*/
|
||||
public Map<Flag, Integer> getDefaultIslandSettings(@NonNull World world) {
|
||||
return gameModes.containsKey(world) ? gameModes.get(world).getWorldSettings().getDefaultIslandSettings() : Collections.emptyMap();
|
||||
public Map<Flag, Integer> getDefaultIslandSettings(@NonNull World world)
|
||||
{
|
||||
return this.gameModes.containsKey(world) ?
|
||||
this.convertToFlags(this.gameModes.get(world).getWorldSettings().getDefaultIslandSettingNames()) :
|
||||
Collections.emptyMap();
|
||||
}
|
||||
|
||||
public boolean isUseOwnGenerator(@NonNull World world) {
|
||||
@ -921,4 +931,18 @@ public class IslandWorldManager {
|
||||
return gameModes.containsKey(world) && gameModes.get(world).getWorldSettings().isTeleportPlayerToIslandUponIslandCreation();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method migrates Map of String, Integer to Map of Flag, Integer.
|
||||
* @param flagNamesMap Map that contains flag names to their values.
|
||||
* @return Flag objects to their values.
|
||||
* @since 1.21
|
||||
*/
|
||||
private Map<Flag, Integer> convertToFlags(Map<String, Integer> flagNamesMap)
|
||||
{
|
||||
Map<Flag, Integer> flagMap = new HashMap<>();
|
||||
flagNamesMap.forEach((key, value) ->
|
||||
this.plugin.getFlagsManager().getFlag(key).ifPresent(flag -> flagMap.put(flag, value)));
|
||||
return flagMap;
|
||||
}
|
||||
}
|
||||
|
@ -1333,7 +1333,7 @@ public class IslandsManager {
|
||||
} else {
|
||||
// Successful load
|
||||
// Clean any null flags out of the island - these can occur for various reasons
|
||||
island.getFlags().keySet().removeIf(f -> f.getID().startsWith("NULL_FLAG"));
|
||||
island.getFlags().keySet().removeIf(f -> f.startsWith("NULL_FLAG"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1018,7 +1018,7 @@ public class IslandTest {
|
||||
*/
|
||||
@Test
|
||||
public void testSetCooldowns() {
|
||||
i.setCooldowns(Collections.singletonMap(Flags.BREAK_BLOCKS, 123L));
|
||||
i.setCooldowns(Collections.singletonMap(Flags.BREAK_BLOCKS.getID(), 123L));
|
||||
assertFalse(i.getCooldowns().isEmpty());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user