Skip to content

Commit

Permalink
Merge pull request #18 from TheNextLvl-net/wildcard
Browse files Browse the repository at this point in the history
Wildcard support
  • Loading branch information
NonSwag authored Aug 10, 2024
2 parents b95150e + 7e6c87a commit 3e1cb11
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 41 deletions.
26 changes: 26 additions & 0 deletions api/src/main/java/net/thenextlvl/commander/CommandFinder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package net.thenextlvl.commander;

import java.util.Set;
import java.util.stream.Stream;

/**
* The CommandFinder interface defines methods for finding commands based on a given input.
*/
public interface CommandFinder {
/**
* Finds commands based on the given input.
*
* @param input The input used to search for commands.
* @return A set of strings representing the found commands.
*/
Set<String> findCommands(String input);

/**
* This method finds commands based on a given input.
*
* @param commands The stream of commands to search for.
* @param input The input used to search for commands.
* @return A set of strings representing the found commands.
*/
Set<String> findCommands(Stream<String> commands, String input);
}
6 changes: 6 additions & 0 deletions api/src/main/java/net/thenextlvl/commander/Commander.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

@MethodsReturnNotNullByDefault
public interface Commander {
/**
* Retrieves the CommandFinder instance associated with the Commander.
*
* @return the CommandFinder instance
*/
CommandFinder commandFinder();

/**
* Retrieves the ComponentBundle associated with the Commander.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.thenextlvl.commander.Commander;
import net.thenextlvl.commander.paper.command.CommanderCommand;
import net.thenextlvl.commander.paper.implementation.PaperCommandFinder;
import net.thenextlvl.commander.paper.implementation.PaperCommandRegistry;
import net.thenextlvl.commander.paper.implementation.PaperPermissionOverride;
import net.thenextlvl.commander.paper.listener.CommandListener;
Expand Down Expand Up @@ -38,6 +39,7 @@ public class CommanderPlugin extends JavaPlugin implements Commander {
Placeholder.component("prefix", bundle.component(Locale.US, "prefix"))
)).build());

private final PaperCommandFinder commandFinder = new PaperCommandFinder(this);
private final PaperCommandRegistry commandRegistry = new PaperCommandRegistry(this);
private final PaperPermissionOverride permissionOverride = new PaperPermissionOverride(this);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ class CommandSuggestionProvider implements SuggestionProvider<CommandSourceStack

@Override
public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) {
Bukkit.getCommandMap().getKnownCommands().values().stream()
.map(Command::getLabel)
.filter(s -> !plugin.commandRegistry().isUnregistered(s))
.map(StringArgumentType::escapeIfRequired)
.filter(s -> s.contains(builder.getRemaining()))
.forEach(builder::suggest);
Bukkit.getCommandMap().getKnownCommands().values().stream()
.map(Command::getLabel)
.filter(s -> !plugin.commandRegistry().isUnregistered(s))
.map(StringArgumentType::escapeIfRequired)
.filter(s -> s.contains(builder.getRemaining()))
.forEach(builder::suggest);
return builder.buildFuture();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.thenextlvl.commander.paper.implementation;

import lombok.RequiredArgsConstructor;
import net.thenextlvl.commander.CommandFinder;
import net.thenextlvl.commander.paper.CommanderPlugin;

import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RequiredArgsConstructor
public class PaperCommandFinder implements CommandFinder {
private final CommanderPlugin plugin;

public Set<String> findCommands(String input) {
return findCommands(plugin.getServer().getCommandMap().getKnownCommands().entrySet()
.stream().mapMulti((entry, consumer) -> {
consumer.accept(entry.getKey());
entry.getValue().getAliases().forEach(consumer);
}), input);
}

public Set<String> findCommands(Stream<String> commands, String input) {
var pattern = Pattern.compile(input.replace("*", ".*"));
return commands.filter(command ->
pattern.matcher(command).matches()
).collect(Collectors.toSet());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import core.file.format.GsonFile;
import core.io.IO;
import lombok.Getter;
import net.thenextlvl.commander.paper.CommanderPlugin;
import net.thenextlvl.commander.CommandRegistry;
import net.thenextlvl.commander.paper.CommanderPlugin;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;

Expand All @@ -20,32 +20,35 @@ public class PaperCommandRegistry implements CommandRegistry {
private final Map<String, Command> commands = new HashMap<>();
private final FileIO<Set<String>> hiddenFile;
private final FileIO<Set<String>> unregisteredFile;
private final CommanderPlugin plugin;

public PaperCommandRegistry(CommanderPlugin plugin) {
this.hiddenFile = new GsonFile<Set<String>>(
IO.of(plugin.getDataFolder(), "hidden-commands.json"),
new HashSet<>(), new TypeToken<>() {
}).saveIfAbsent();
}).reload().saveIfAbsent();
this.unregisteredFile = new GsonFile<Set<String>>(
IO.of(plugin.getDataFolder(), "removed-commands.json"),
new HashSet<>(), new TypeToken<>() {
}).saveIfAbsent();
}).reload().saveIfAbsent();
this.plugin = plugin;
}

@Override
public Set<String> hiddenCommands() {
return Set.copyOf(hiddenFile.getRoot());
return new HashSet<>(hiddenFile.getRoot());
}

@Override
public Set<String> unregisteredCommands() {
return Set.copyOf(unregisteredFile.getRoot());
return new HashSet<>(unregisteredFile.getRoot());
}

@Override
public boolean hide(String command) {
return Bukkit.getCommandMap().getKnownCommands().containsKey(command)
&& hiddenFile.getRoot().add(command);
return !plugin.commandFinder().findCommands(command).stream()
.filter(hiddenFile.getRoot()::add)
.toList().isEmpty();
}

@Override
Expand All @@ -60,22 +63,33 @@ public boolean isUnregistered(String command) {

@Override
public boolean register(String command) {
return unregisteredFile.getRoot().remove(command) && internalRegister(command);
return !plugin.commandFinder().findCommands(new HashSet<>(commands.keySet()).stream(), command).stream()
.filter(unregisteredFile.getRoot()::remove)
.filter(this::internalRegister)
.toList().isEmpty();
}

@Override
public boolean reveal(String command) {
return hiddenFile.getRoot().remove(command);
return !plugin.commandFinder().findCommands(new HashSet<>(hiddenFile.getRoot()).stream(), command).stream()
.filter(hiddenFile.getRoot()::remove)
.toList().isEmpty();
}

@Override
public boolean unregister(String command) {
return unregisteredFile.getRoot().add(command) && internalUnregister(command);
return !plugin.commandFinder().findCommands(command).stream()
.filter(s -> !s.equals("commander:command"))
.filter(unregisteredFile.getRoot()::add)
.filter(this::internalUnregister)
.toList().isEmpty();
}

@Override
public void unregisterCommands() {
unregisteredCommands().forEach(this::internalUnregister);
unregisteredCommands().stream()
.filter(command -> !command.equals("commander:command"))
.forEach(this::internalUnregister);
}

private boolean internalRegister(String command) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,34 @@
import org.bukkit.Bukkit;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;

@Getter
@RequiredArgsConstructor
public class PaperPermissionOverride implements PermissionOverride {
private final Map<String, @Nullable String> originalPermissions = new HashMap<>();
private final FileIO<Map<String, @Nullable String>> overridesFile;
private final CommanderPlugin plugin;

public PaperPermissionOverride(CommanderPlugin plugin) {
this.overridesFile = new GsonFile<Map<String, @Nullable String>>(
IO.of(plugin.getDataFolder(), "permission-overrides.json"),
new HashMap<>(), new TypeToken<>() {
}).saveIfAbsent();
}).reload().saveIfAbsent();
this.plugin = plugin;
}

@Override
public Map<String, @Nullable String> overrides() {
return Map.copyOf(overridesFile.getRoot());
return new HashMap<>(overridesFile.getRoot());
}

@Override
public Map<String, @Nullable String> originalPermissions() {
return Map.copyOf(originalPermissions);
return new HashMap<>(originalPermissions);
}

@Override
Expand All @@ -53,15 +58,20 @@ public boolean isOverridden(String command) {

@Override
public boolean override(String command, @Nullable String permission) {
overridesFile.getRoot().put(command, permission);
return internalOverride(command, permission);
var commands = plugin.commandFinder().findCommands(command).stream()
.filter(s -> internalOverride(s, permission))
.toList();
commands.forEach(s -> overridesFile.getRoot().put(s, permission));
return !commands.isEmpty();
}

@Override
public boolean reset(String command) {
if (!isOverridden(command)) return false;
overridesFile.getRoot().remove(command);
return internalReset(command);
var commands = plugin.commandFinder().findCommands(new HashSet<>(overridesFile.getRoot().keySet()).stream(), command);
commands.forEach(overridesFile.getRoot()::remove);
return !commands.stream()
.filter(this::internalReset)
.toList().isEmpty();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.thenextlvl.commander.Commander;
import net.thenextlvl.commander.velocity.command.CommanderCommand;
import net.thenextlvl.commander.velocity.implementation.ProxyCommandFinder;
import net.thenextlvl.commander.velocity.implementation.ProxyCommandRegistry;
import net.thenextlvl.commander.velocity.implementation.ProxyPermissionOverride;
import net.thenextlvl.commander.velocity.listener.CommandListener;
Expand All @@ -39,6 +40,7 @@
public class CommanderPlugin implements Commander {
private final CommanderVersionChecker versionChecker = new CommanderVersionChecker(this);
private final ComponentBundle bundle;
private final ProxyCommandFinder commandFinder;
private final ProxyCommandRegistry commandRegistry;
private final ProxyPermissionOverride permissionOverride;
private final Metrics.Factory metricsFactory;
Expand All @@ -60,6 +62,7 @@ public CommanderPlugin(ProxyServer server, Logger logger, @DataDirectory Path da
TagResolver.standard(),
Placeholder.component("prefix", bundle.component(Locale.US, "prefix"))
)).build());
this.commandFinder = new ProxyCommandFinder(this);
this.commandRegistry = new ProxyCommandRegistry(this);
this.permissionOverride = new ProxyPermissionOverride(this);
checkVersionUpdate();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package net.thenextlvl.commander.velocity.implementation;

import lombok.RequiredArgsConstructor;
import net.thenextlvl.commander.CommandFinder;
import net.thenextlvl.commander.velocity.CommanderPlugin;

import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RequiredArgsConstructor
public class ProxyCommandFinder implements CommandFinder {
private final CommanderPlugin plugin;

@Override
public Set<String> findCommands(String input) {
return findCommands(plugin.server().getCommandManager().getAliases().stream(), input);
}

@Override
public Set<String> findCommands(Stream<String> commands, String input) {
var pattern = Pattern.compile(input.replace("*", ".*"));
return commands.filter(command ->
pattern.matcher(command).matches()
).collect(Collectors.toSet());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,29 @@ public ProxyCommandRegistry(CommanderPlugin plugin) {
this.hiddenFile = new GsonFile<Set<String>>(
IO.of(plugin.dataFolder().toFile(), "hidden-commands.json"),
new HashSet<>(), new TypeToken<>() {
}).saveIfAbsent();
}).reload().saveIfAbsent();
this.unregisteredFile = new GsonFile<Set<String>>(
IO.of(plugin.dataFolder().toFile(), "removed-commands.json"),
new HashSet<>(), new TypeToken<>() {
}).saveIfAbsent();
}).reload().saveIfAbsent();
this.plugin = plugin;
}

@Override
public Set<String> hiddenCommands() {
return Set.copyOf(hiddenFile.getRoot());
return new HashSet<>(hiddenFile.getRoot());
}

@Override
public Set<String> unregisteredCommands() {
return Set.copyOf(unregisteredFile.getRoot());
return new HashSet<>(unregisteredFile.getRoot());
}

@Override
public boolean hide(String command) {
return hiddenFile.getRoot().add(command);
return !plugin.commandFinder().findCommands(command).stream()
.filter(hiddenFile.getRoot()::add)
.toList().isEmpty();
}

@Override
Expand All @@ -56,18 +58,26 @@ public boolean isUnregistered(String command) {

@Override
public boolean register(String command) {
return unregisteredFile.getRoot().remove(command);
return !plugin.commandFinder().findCommands(new HashSet<>(unregisteredFile.getRoot()).stream(), command).stream()
.filter(unregisteredFile.getRoot()::remove)
.toList().isEmpty();
}

@Override
public boolean reveal(String command) {
return hiddenFile.getRoot().remove(command);
return !plugin.commandFinder().findCommands(new HashSet<>(hiddenFile.getRoot()).stream(), command).stream()
.filter(hiddenFile.getRoot()::remove)
.toList().isEmpty();
}

@Override
public boolean unregister(String command) {
if (!plugin.server().getCommandManager().hasCommand(command)) return false;
return unregisteredFile.getRoot().add(command) && internalUnregister(command);
return !plugin.commandFinder().findCommands(command).stream()
.filter(s -> !s.equals("commandv"))
.filter(plugin.server().getCommandManager()::hasCommand)
.filter(unregisteredFile.getRoot()::add)
.filter(this::internalUnregister)
.toList().isEmpty();
}

@Override
Expand Down
Loading

0 comments on commit 3e1cb11

Please sign in to comment.