Use WeakReference to store alternative commands (#5572)

Co-authored-by: oop778 <oskardhavel@gmail.com>
This commit is contained in:
Josh Roy 2023-11-27 16:29:20 -05:00 committed by GitHub
parent c68b277782
commit bb7b334ace
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4,6 +4,7 @@ import org.bukkit.command.Command;
import org.bukkit.command.PluginIdentifiableCommand; import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -13,7 +14,7 @@ import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
public class AlternativeCommandsHandler { public class AlternativeCommandsHandler {
private final transient Map<String, List<Command>> altcommands = new HashMap<>(); private final transient Map<String, List<WeakReference<Command>>> altCommands = new HashMap<>();
private final transient Map<String, String> disabledList = new HashMap<>(); private final transient Map<String, String> disabledList = new HashMap<>();
private final transient IEssentials ess; private final transient IEssentials ess;
@ -35,17 +36,30 @@ public class AlternativeCommandsHandler {
final String commandName = commandSplit.length > 1 ? commandSplit[1] : entry.getKey(); final String commandName = commandSplit.length > 1 ? commandSplit[1] : entry.getKey();
final Command command = entry.getValue(); final Command command = entry.getValue();
final List<Command> pluginCommands = altcommands.computeIfAbsent(commandName.toLowerCase(Locale.ENGLISH), k -> new ArrayList<>()); final List<WeakReference<Command>> pluginCommands = altCommands.computeIfAbsent(commandName.toLowerCase(Locale.ENGLISH), k -> new ArrayList<>());
boolean found = false; boolean found = false;
for (final Command pc2 : pluginCommands) {
final Iterator<WeakReference<Command>> pluginCmdIterator = pluginCommands.iterator();
while (pluginCmdIterator.hasNext()) {
final Command cmd = pluginCmdIterator.next().get();
if (cmd == null) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.INFO, "Essentials: Alternative command for " + commandName + " removed due to garbage collection");
}
pluginCmdIterator.remove();
continue;
}
// Safe cast, everything that's added comes from getPluginCommands which already performs the cast check. // Safe cast, everything that's added comes from getPluginCommands which already performs the cast check.
if (((PluginIdentifiableCommand) pc2).getPlugin().equals(plugin)) { if (((PluginIdentifiableCommand) cmd).getPlugin().equals(plugin)) {
found = true; found = true;
break; break;
} }
} }
if (!found) { if (!found) {
pluginCommands.add(command); pluginCommands.add(new WeakReference<>(command));
} }
} }
} }
@ -61,10 +75,19 @@ public class AlternativeCommandsHandler {
} }
public void removePlugin(final Plugin plugin) { public void removePlugin(final Plugin plugin) {
final Iterator<Map.Entry<String, List<Command>>> iterator = altcommands.entrySet().iterator(); final Iterator<Map.Entry<String, List<WeakReference<Command>>>> iterator = altCommands.entrySet().iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
final Map.Entry<String, List<Command>> entry = iterator.next(); final Map.Entry<String, List<WeakReference<Command>>> entry = iterator.next();
entry.getValue().removeIf(pc -> !(pc instanceof PluginIdentifiableCommand) || ((PluginIdentifiableCommand) pc).getPlugin().equals(plugin));
final Iterator<WeakReference<Command>> commands = entry.getValue().iterator();
while (commands.hasNext()) {
final Command pc = commands.next().get();
if (pc instanceof PluginIdentifiableCommand && !((PluginIdentifiableCommand) pc).getPlugin().equals(plugin)) {
continue;
}
commands.remove();
}
if (entry.getValue().isEmpty()) { if (entry.getValue().isEmpty()) {
iterator.remove(); iterator.remove();
} }
@ -72,21 +95,31 @@ public class AlternativeCommandsHandler {
} }
public Command getAlternative(final String label) { public Command getAlternative(final String label) {
final List<Command> commands = altcommands.get(label); final List<WeakReference<Command>> commands = altCommands.get(label);
if (commands == null || commands.isEmpty()) { if (commands == null || commands.isEmpty()) {
return null; return null;
} }
if (commands.size() == 1) { if (commands.size() == 1) {
return commands.get(0); return commands.get(0).get();
} }
// return the first command that is not an alias // return the first command that is not an alias
for (final Command command : commands) { final Iterator<WeakReference<Command>> iterator = commands.iterator();
if (command.getName().equalsIgnoreCase(label)) { while (iterator.hasNext()) {
return command; final Command cmd = iterator.next().get();
if (cmd == null) {
iterator.remove();
continue;
}
if (cmd.getName().equalsIgnoreCase(label)) {
return cmd;
} }
} }
// return the first alias // return the first alias
return commands.get(0); return commands.get(0).get();
} }
public void executed(final String label, final Command pc) { public void executed(final String label, final Command pc) {