Adds a cooldown API for flags. (#821)

* Adds a cooldown API for flags.

https://github.com/BentoBoxWorld/BentoBox/issues/754

Added 60 second cooldown to PVP flags

* Added cooldowns to database.

This way, if a cooldown is a long one it will be remembered even if the
server restarts.

* Update src/main/java/world/bentobox/bentobox/database/objects/adapters/FlagSerializer3.java
This commit is contained in:
tastybento 2019-07-06 23:08:16 -07:00 committed by Florian CUNY
parent f44b36267d
commit abd88c0826
8 changed files with 150 additions and 9 deletions

View File

@ -77,6 +77,7 @@ public class Flag implements Comparable<Flag> {
private final boolean subPanel;
private Set<GameModeAddon> gameModes = new HashSet<>();
private final Addon addon;
private final int cooldown;
private Flag(Builder builder) {
this.id = builder.id;
@ -90,6 +91,7 @@ public class Flag implements Comparable<Flag> {
if (builder.gameModeAddon != null) {
this.gameModes.add(builder.gameModeAddon);
}
this.cooldown = builder.cooldown;
this.addon = builder.addon;
}
@ -105,6 +107,13 @@ public class Flag implements Comparable<Flag> {
return Optional.ofNullable(listener);
}
/**
* @return the cooldown
*/
public int getCooldown() {
return cooldown;
}
/**
* Check if a setting is set in this world
* @param world - world
@ -322,6 +331,9 @@ public class Flag implements Comparable<Flag> {
: user.getTranslation("protection.panel.flag-item.setting-disabled");
pib.description(user.getTranslation("protection.panel.flag-item.setting-layout", TextVariables.DESCRIPTION, user.getTranslation(getDescriptionReference())
, "[setting]", islandSetting));
if (this.cooldown > 0 && island.isCooldown(this)) {
pib.description(user.getTranslation("protection.panel.flag-item.setting-cooldown"));
}
}
return pib;
}
@ -384,6 +396,9 @@ public class Flag implements Comparable<Flag> {
private GameModeAddon gameModeAddon;
private Addon addon;
// Cooldown
private int cooldown;
/**
* Builder for making flags
* @param id - a unique id that MUST be the same as the enum of the flag
@ -476,6 +491,17 @@ public class Flag implements Comparable<Flag> {
return this;
}
/**
* Set a cooldown for {@link Type#SETTING} flag. Only applicable for settings.
* @param cooldown in seconds
* @return Builder
* @since 1.6.0
*/
public Builder cooldown(int cooldown) {
this.cooldown = cooldown;
return this;
}
/**
* Build the flag
* @return Flag

View File

@ -61,9 +61,17 @@ public class IslandToggleClick implements ClickHandler {
// Save changes
plugin.getIWM().getAddon(user.getWorld()).ifPresent(GameModeAddon::saveWorldSettings);
} else {
// Check cooldown
if (!user.isOp() && island.isCooldown(flag)) {
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_BEACON_DEACTIVATE, 1F, 1F);
user.notify("protection.panel.flag-item.setting-cooldown");
return;
}
// Toggle flag
island.toggleFlag(flag);
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F);
// Set cooldown
island.setCooldown(flag);
}
// Apply change to panel
panel.getInventory().setItem(slot, flag.toPanelItem(plugin, user, invisible).getItem());

View File

@ -35,6 +35,7 @@ import world.bentobox.bentobox.api.logs.LogEntry;
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.IslandWorldManager;
@ -146,6 +147,13 @@ public class Island implements DataObject {
@Expose
private boolean doNotLoad;
/**
* Used to store flag cooldowns for this island
*/
@Adapter(FlagSerializer3.class)
@Expose
private Map<Flag, Long> cooldowns = new HashMap<>();
public Island() {}
public Island(@NonNull Location location, UUID owner, int protectionRange) {
@ -1049,6 +1057,43 @@ public class Island implements DataObject {
!getCenter().toVector().toLocation(iwm.getEndWorld(getWorld())).getBlock().getType().equals(Material.AIR);
}
/**
* Checks if a flag is on cooldown. Only stored in memory so a server restart will reset the cooldown.
* @param flag - flag
* @return true if on cooldown, false if not
* @since 1.6.0
*/
public boolean isCooldown(Flag flag) {
if (cooldowns.containsKey(flag) && cooldowns.get(flag) > System.currentTimeMillis()) {
return true;
}
cooldowns.remove(flag);
return false;
}
/**
* Sets a cooldown for this flag on this island.
* @param flag - Flag to cooldown
*/
public void setCooldown(Flag flag) {
cooldowns.put(flag, flag.getCooldown() * 1000 + System.currentTimeMillis());
}
/**
* @return the cooldowns
*/
public Map<Flag, Long> getCooldowns() {
return cooldowns;
}
/**
* @param cooldowns the cooldowns to set
*/
public void setCooldowns(Map<Flag, Long> cooldowns) {
this.cooldowns = cooldowns;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@ -1061,4 +1106,6 @@ public class Island implements DataObject {
+ ", purgeProtected=" + purgeProtected + ", flags=" + flags + ", history=" + history
+ ", levelHandicap=" + levelHandicap + ", spawnPoint=" + spawnPoint + ", doNotLoad=" + doNotLoad + "]";
}
}

View File

@ -0,0 +1,57 @@
package world.bentobox.bentobox.database.objects.adapters;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.configuration.MemorySection;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.flags.Flag;
/**
* Serializes the {@link world.bentobox.bentobox.database.objects.Island#getFlags() getFlags()} and
* {@link world.bentobox.bentobox.database.objects.Island#setFlags(Map)} () setFlags()}
* in {@link world.bentobox.bentobox.database.objects.Island}
* @author tastybento
* @since 1.6.0
*/
public class FlagSerializer3 implements AdapterInterface<Map<Flag, Long>, Map<String, Long>> {
@SuppressWarnings("unchecked")
@Override
public Map<Flag, Long> deserialize(Object object) {
Map<Flag, Long> result = new HashMap<>();
if (object == null) {
return result;
}
// For YAML
if (object instanceof MemorySection) {
MemorySection section = (MemorySection) object;
for (String key : section.getKeys(false)) {
BentoBox.getInstance().getFlagsManager().getFlag(key).ifPresent(flag -> result.put(flag, section.getLong(key)));
}
} else {
for (Entry<String, Long> en : ((Map<String, Long>)object).entrySet()) {
BentoBox.getInstance().getFlagsManager().getFlag(en.getKey()).ifPresent(flag -> result.put(flag, en.getValue()));
}
}
return result;
}
@SuppressWarnings("unchecked")
@Override
public Map<String, Long> serialize(Object object) {
Map<String, Long> result = new HashMap<>();
if (object == null) {
return result;
}
Map<Flag, Long> flags = (Map<Flag, Long>)object;
for (Entry<Flag, Long> en: flags.entrySet()) {
if (en != null && en.getKey() != null) {
result.put(en.getKey().getID(), en.getValue());
}
}
return result;
}
}

View File

@ -256,11 +256,11 @@ public final class Flags {
*/
// PVP
public static final Flag PVP_OVERWORLD = new Flag.Builder("PVP_OVERWORLD", Material.ARROW).type(Type.SETTING)
.defaultRank(DISABLED).listener(new PVPListener()).build();
.defaultRank(DISABLED).listener(new PVPListener()).cooldown(60).build();
public static final Flag PVP_NETHER = new Flag.Builder("PVP_NETHER", Material.IRON_AXE).type(Type.SETTING)
.defaultRank(DISABLED).build();
.defaultRank(DISABLED).cooldown(60).build();
public static final Flag PVP_END = new Flag.Builder("PVP_END", Material.END_CRYSTAL).type(Type.SETTING)
.defaultRank(DISABLED).build();
.defaultRank(DISABLED).cooldown(60).build();
// Fire
/**

View File

@ -1053,6 +1053,7 @@ protection:
blocked-rank: "&3- &c"
minimal-rank: "&3- &2"
menu-layout: "&a[description]"
setting-cooldown: "&cSetting is on cooldown"
setting-layout: |
&a[description]

View File

@ -22,7 +22,6 @@ import org.bukkit.Bukkit;
import org.bukkit.plugin.PluginManager;
import org.bukkit.scheduler.BukkitScheduler;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -60,7 +59,8 @@ public class MariaDBDatabaseHandlerTest {
" \"history\": [],\n" +
" \"levelHandicap\": 0,\n" +
" \"spawnPoint\": {},\n" +
" \"doNotLoad\": false\n" +
" \"doNotLoad\": false,\n" +
" \"cooldowns\": {}\n" +
"}";
private MariaDBDatabaseHandler<Island> handler;
private Island instance;
@ -279,7 +279,8 @@ public class MariaDBDatabaseHandlerTest {
" \"history\": [],\n" +
" \"levelHandicap\": 0,\n" +
" \"spawnPoint\": {},\n" +
" \"doNotLoad\": false\n" +
" \"doNotLoad\": false,\n" +
" \"cooldowns\": {}\n" +
"}");
}

View File

@ -22,7 +22,6 @@ import org.bukkit.Bukkit;
import org.bukkit.plugin.PluginManager;
import org.bukkit.scheduler.BukkitScheduler;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -59,7 +58,8 @@ public class MySQLDatabaseHandlerTest {
" \"history\": [],\n" +
" \"levelHandicap\": 0,\n" +
" \"spawnPoint\": {},\n" +
" \"doNotLoad\": false\n" +
" \"doNotLoad\": false,\n" +
" \"cooldowns\": {}\n" +
"}";
private MySQLDatabaseHandler<Island> handler;
private Island instance;
@ -278,7 +278,8 @@ public class MySQLDatabaseHandlerTest {
" \"history\": [],\n" +
" \"levelHandicap\": 0,\n" +
" \"spawnPoint\": {},\n" +
" \"doNotLoad\": false\n" +
" \"doNotLoad\": false,\n" +
" \"cooldowns\": {}\n" +
"}");
}