Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use WeakReference to store alternative commands #5572

Merged
merged 2 commits into from
Nov 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.plugin.Plugin;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
Expand All @@ -13,7 +14,7 @@
import java.util.logging.Level;

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 IEssentials ess;

Expand All @@ -35,17 +36,30 @@ public final void addPlugin(final Plugin plugin) {
final String commandName = commandSplit.length > 1 ? commandSplit[1] : entry.getKey();
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;
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.
if (((PluginIdentifiableCommand) pc2).getPlugin().equals(plugin)) {
if (((PluginIdentifiableCommand) cmd).getPlugin().equals(plugin)) {
found = true;
break;
}
}

if (!found) {
pluginCommands.add(command);
pluginCommands.add(new WeakReference<>(command));
}
}
}
Expand All @@ -61,32 +75,51 @@ private Map<String, Command> getPluginCommands(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()) {
final Map.Entry<String, List<Command>> entry = iterator.next();
entry.getValue().removeIf(pc -> !(pc instanceof PluginIdentifiableCommand) || ((PluginIdentifiableCommand) pc).getPlugin().equals(plugin));
final Map.Entry<String, List<WeakReference<Command>>> entry = iterator.next();

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()) {
iterator.remove();
}
}
}

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()) {
return null;
}

if (commands.size() == 1) {
return commands.get(0);
return commands.get(0).get();
}

// return the first command that is not an alias
for (final Command command : commands) {
if (command.getName().equalsIgnoreCase(label)) {
return command;
final Iterator<WeakReference<Command>> iterator = commands.iterator();
while (iterator.hasNext()) {
final Command cmd = iterator.next().get();
if (cmd == null) {
iterator.remove();
continue;
}

if (cmd.getName().equalsIgnoreCase(label)) {
return cmd;
}
}

// return the first alias
return commands.get(0);
return commands.get(0).get();
}

public void executed(final String label, final Command pc) {
Expand Down