Addon reloading: adds parameter to register flag

Addons need to declare themseves when they register a flag so that the
flag listener can be reset. Note that this is not mandatory unless the
flag declares a listener
This commit is contained in:
tastybento 2019-05-10 15:18:13 -07:00
parent 779c370b6a
commit 8ce47772c2
4 changed files with 93 additions and 59 deletions

View File

@ -6,6 +6,7 @@ import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.flags.clicklisteners.CycleClick;
@ -74,24 +75,9 @@ public class Flag implements Comparable<Flag> {
private final PanelItem.ClickHandler clickHandler;
private final boolean subPanel;
private Set<GameModeAddon> gameModes = new HashSet<>();
private final Addon addon;
/**
* {@link Flag.Builder} should be used instead. This is only used for testing.
*/
Flag(String id, Material icon, Listener listener, Type type, int defaultRank, PanelItem.ClickHandler clickListener, boolean subPanel, GameModeAddon gameModeAddon) {
this.id = id;
this.icon = icon;
this.listener = listener;
this.type = type;
this.defaultRank = defaultRank;
this.clickHandler = clickListener;
this.subPanel = subPanel;
if (gameModeAddon != null) {
this.gameModes.add(gameModeAddon);
}
}
private Flag(Builder builder) {
private Flag(Builder builder) {
this.id = builder.id;
this.icon = builder.icon;
this.listener = builder.listener;
@ -103,6 +89,7 @@ public class Flag implements Comparable<Flag> {
if (builder.gameModeAddon != null) {
this.gameModes.add(builder.gameModeAddon);
}
this.addon = builder.addon;
}
public String getID() {
@ -184,6 +171,15 @@ public class Flag implements Comparable<Flag> {
public boolean hasSubPanel() {
return subPanel;
}
/**
* Get the addon that made this flag
* @return the addon
* @since 1.5.0
*/
public Addon getAddon() {
return addon;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
@ -347,16 +343,13 @@ public class Flag implements Comparable<Flag> {
return pib;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Flag [id=" + id + ", icon=" + icon + ", listener=" + listener + ", type=" + type + ", defaultSetting="
+ setting + ", defaultRank=" + defaultRank + ", clickHandler=" + clickHandler + ", subPanel=" + subPanel + "]";
}
@Override
public String toString() {
return "Flag [id=" + id + "]";
}
@Override
public int compareTo(Flag o) {
return getID().compareTo(o.getID());
}
@ -388,6 +381,7 @@ public class Flag implements Comparable<Flag> {
// GameModeAddon
private GameModeAddon gameModeAddon;
private Addon addon;
/**
* Builder for making flags
@ -463,12 +457,23 @@ public class Flag implements Comparable<Flag> {
/**
* Make this flag specific to this gameMode
* @param gameModeAddon
* @return
* @return Builder
*/
public Builder setGameMode(GameModeAddon gameModeAddon) {
this.gameModeAddon = gameModeAddon;
return this;
}
/**
* The addon registering this flag. Ensure this is set to enable the addon to be reloaded.
* @param addon
* @return Builder
* @since 1.5.0
*/
public Builder addon(Addon addon) {
this.addon = addon;
return this;
}
/**
* Build the flag

View File

@ -1,22 +1,5 @@
package world.bentobox.bentobox.managers;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.generator.ChunkGenerator;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.AddonClassLoader;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonFormatException;
import world.bentobox.bentobox.api.configuration.ConfigObject;
import world.bentobox.bentobox.api.events.addon.AddonEvent;
import world.bentobox.bentobox.database.objects.DataObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@ -35,6 +18,24 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.generator.ChunkGenerator;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.AddonClassLoader;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonFormatException;
import world.bentobox.bentobox.api.configuration.ConfigObject;
import world.bentobox.bentobox.api.events.addon.AddonEvent;
import world.bentobox.bentobox.database.objects.DataObject;
/**
* @author tastybento, ComminQ
*/
@ -48,7 +49,7 @@ public class AddonsManager {
private final Map<String, Class<?>> classes;
private BentoBox plugin;
private @NonNull Map<@NonNull String, @Nullable GameModeAddon> worldNames;
private @NonNull Map<Addon, List<Listener>> listeners;
private @NonNull Map<@NonNull Addon, @NonNull List<Listener>> listeners;
public AddonsManager(@NonNull BentoBox plugin) {
this.plugin = plugin;
@ -401,7 +402,7 @@ public class AddonsManager {
* @param addon - the addon registering
* @param listener - listener
*/
public void registerListener(Addon addon, Listener listener) {
public void registerListener(@NonNull Addon addon, @NonNull Listener listener) {
Bukkit.getPluginManager().registerEvents(listener, BentoBox.getInstance());
listeners.computeIfAbsent(addon, k -> new ArrayList<>()).add(listener);
}
@ -410,12 +411,14 @@ public class AddonsManager {
* Disables an addon
* @param addon - addon
*/
private void disable(Addon addon) {
private void disable(@NonNull Addon addon) {
// Clear listeners
if (listeners.containsKey(addon)) {
listeners.get(addon).forEach(HandlerList::unregisterAll);
listeners.remove(addon);
}
// Unregister flags
plugin.getFlagsManager().unregister(addon);
// Disable
if (addon.isEnabled()) {
addon.onDisable();
@ -446,4 +449,5 @@ public class AddonsManager {
.filter(c -> !ConfigObject.class.isAssignableFrom(c))
.collect(Collectors.toList());
}
}

View File

@ -7,10 +7,13 @@ import java.util.Map;
import java.util.Optional;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.lists.Flags;
@ -21,7 +24,7 @@ import world.bentobox.bentobox.lists.Flags;
public class FlagsManager {
private @NonNull BentoBox plugin;
private List<@NonNull Flag> flags = new ArrayList<>();
private Map<@NonNull Flag, @Nullable Addon> flags = new HashMap<>();
/**
* Stores the flag listeners that have already been registered into Bukkit's API to avoid duplicates.
@ -35,27 +38,39 @@ public class FlagsManager {
this.plugin = plugin;
// Register default flags
Flags.values().forEach(this::registerFlag);
Flags.values().forEach(f -> registerFlag(null, f));
}
/**
* Register a new flag
* Register a new flag.
* @param flag flag to be registered
* @return true if successfully registered, false if not, e.g., because one with the same ID already exists
* @see Consider using {@link #registerFlag(Addon, Flag)} instead if your flag declares a listener
*/
public boolean registerFlag(@NonNull Flag flag) {
return registerFlag(null, flag);
}
/**
* Register a new flag.
* @param addon - addon that is registering this flag
* @param flag flag to be registered
* @return true if successfully registered, false if not, e.g., because one with the same ID already exists
* @since 1.5.0
*/
public boolean registerFlag(@Nullable Addon addon, @NonNull Flag flag) {
// Check in case the flag id or icon already exists
for (Flag fl : flags) {
for (Flag fl : flags.keySet()) {
if (fl.getID().equals(flag.getID())) {
return false;
}
}
flags.add(flag);
flags.put(flag, addon);
// If there is a listener which is not already registered, register it into Bukkit if the plugin is fully loaded
flag.getListener().ifPresent(this::registerListener);
return true;
}
/**
* Register any unregistered listeners.
* This helps to make sure each flag listener is correctly loaded.
@ -81,7 +96,7 @@ public class FlagsManager {
*/
@NonNull
public List<Flag> getFlags() {
return flags;
return new ArrayList<>(flags.keySet());
}
/**
@ -92,6 +107,20 @@ public class FlagsManager {
*/
@NonNull
public Optional<Flag> getFlag(@NonNull String id) {
return flags.stream().filter(flag -> flag.getID().equals(id)).findFirst();
return flags.keySet().stream().filter(flag -> flag.getID().equals(id)).findFirst();
}
/**
* Unregister flags for addon
* @param addon - addon
* @since 1.5.0
*/
public void unregister(@NonNull Addon addon) {
// Unregister listeners
flags.entrySet().stream().filter(e -> addon.equals(e.getValue())).map(Map.Entry::getKey)
.forEach(f -> f.getListener().ifPresent(HandlerList::unregisterAll));
// Remove flags
flags.values().removeIf(addon::equals);
}
}

View File

@ -363,11 +363,7 @@ public class FlagTest {
*/
@Test
public void testToString() {
assertTrue(f.toString().startsWith("Flag [id=flagID, icon=ACACIA_PLANKS, listener=listener, type=PROTECTION, "
+ "defaultSetting=false, defaultRank=500, "
+ "clickHandler="));
// Handler changes so check start and end
assertTrue(f.toString().endsWith(", subPanel=false]"));
assertEquals("Flag [id=flagID]", f.toString());
}
/**