Skip to content

Commit

Permalink
added new help generator, started working on new java support, bump t…
Browse files Browse the repository at this point in the history
…o 2.1.6
  • Loading branch information
vaperion committed Mar 12, 2022
1 parent 00f4c09 commit 02f126e
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 66 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Maven
<dependency>
<groupId>com.github.vaperion</groupId>
<artifactId>blade</artifactId>
<version>2.1.5</version>
<version>2.1.6</version>
<scope>compile</scope>
</dependency>
</dependencies>
Expand All @@ -40,7 +40,7 @@ allprojects {
}
dependencies {
implementation 'com.github.vaperion:blade:2.1.5'
implementation 'com.github.vaperion:blade:2.1.6'
}
```

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>me.vaperion</groupId>
<artifactId>blade</artifactId>
<version>2.1.5</version>
<version>2.1.6</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/me/vaperion/blade/Blade.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
import me.vaperion.blade.bindings.Binding;
import me.vaperion.blade.container.ContainerCreator;
import me.vaperion.blade.help.HelpGenerator;
import me.vaperion.blade.help.impl.BukkitHelpGenerator;
import me.vaperion.blade.permissions.PermissionPredicate;
import me.vaperion.blade.service.BladeCommandRegistrar;
import me.vaperion.blade.service.BladeCommandService;
import me.vaperion.blade.tabcompleter.TabCompleter;
import me.vaperion.blade.utils.ClassUtil;
import org.jetbrains.annotations.NotNull;

import java.lang.annotation.Annotation;
Expand Down Expand Up @@ -103,6 +105,8 @@ public Blade build() {

if (blade.helpGenerator != null)
blade.commandService.setHelpGenerator(blade.helpGenerator);
else if (ClassUtil.classExists("org.bukkit.Bukkit"))
blade.commandService.setHelpGenerator(new BukkitHelpGenerator());

if (blade.asyncExecutor != null) {
blade.commandService.setAsyncExecutor(blade.asyncExecutor);
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/me/vaperion/blade/command/BladeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public BladeCommand(BladeCommandService commandService, Object instance, Method
this.senderType = this.senderParameter ? method.getParameterTypes()[0] : null;

if (method != null) {
method.setAccessible(true);

int i = 0;
for (Parameter parameter : method.getParameters()) {
if (i == 0 && senderParameter) {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/me/vaperion/blade/command/UsageMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@

public interface UsageMessage {
void sendTo(@NotNull BladeContext context);
@NotNull String toString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,10 @@ public BukkitUsageMessage(BladeCommand command) {
public void sendTo(@NotNull BladeContext context) {
messageBuilder.sendTo((CommandSender) context.sender().getBackingSender());
}

@NotNull
@Override
public String toString() {
return messageBuilder.toStringFormat();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;

Expand All @@ -34,16 +33,14 @@ public class BukkitCommandContainer extends Command implements CommandContainer
private static final String UNKNOWN_COMMAND_MESSAGE;

static {
Class<?> spigotConfigClass = null;
Field mapField = null, commandsField = null, unknownCommandField = null;
Field mapField = null, commandsField = null;
String unknownCommandMessage = ChatColor.WHITE + "Unknown command. Type \"/help\" for help.";

try {
spigotConfigClass = Class.forName("org.spigotmc.SpigotConfig");
Class<?> spigotConfigClass = Class.forName("org.spigotmc.SpigotConfig");
Field unknownCommandField = spigotConfigClass.getDeclaredField("unknownCommandMessage");

unknownCommandField = spigotConfigClass.getDeclaredField("unknownCommandMessage");
unknownCommandField.setAccessible(true);

unknownCommandMessage = ChatColor.WHITE + (String) unknownCommandField.get(null);
} catch (Exception ex) {
System.err.println("Failed to grab unknown command message from SpigotConfig.");
Expand All @@ -52,15 +49,10 @@ public class BukkitCommandContainer extends Command implements CommandContainer

try {
mapField = SimplePluginManager.class.getDeclaredField("commandMap");
mapField.setAccessible(true);
commandsField = SimpleCommandMap.class.getDeclaredField("knownCommands");
commandsField.setAccessible(true);

Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);

modifiers.setInt(mapField, modifiers.getInt(mapField) & ~Modifier.FINAL);
modifiers.setInt(commandsField, modifiers.getInt(commandsField) & ~Modifier.FINAL);
mapField.setAccessible(true);
commandsField.setAccessible(true);
} catch (Exception ex) {
System.err.println("Failed to grab commandMap from the plugin manager.");
ex.printStackTrace();
Expand All @@ -86,13 +78,17 @@ private BukkitCommandContainer(@NotNull BladeCommandService service, @NotNull Bl

if (service.isOverrideCommands()) {
Map<String, Command> knownCommands = (Map<String, Command>) KNOWN_COMMANDS.get(simpleCommandMap);
for (Command registeredCommand : new ArrayList<>(knownCommands.values())) {
Iterator<Map.Entry<String, Command>> iterator = knownCommands.entrySet().iterator();

while (iterator.hasNext()) {
Map.Entry<String, Command> entry = iterator.next();
Command registeredCommand = entry.getValue();

if (doesBukkitCommandConflict(registeredCommand, alias, command)) {
registeredCommand.unregister(simpleCommandMap);
knownCommands.remove(registeredCommand.getName().toLowerCase(Locale.ENGLISH));
iterator.remove();
}
}
KNOWN_COMMANDS.set(simpleCommandMap, knownCommands);
}

simpleCommandMap.register(fallbackPrefix, this);
Expand Down Expand Up @@ -197,6 +193,10 @@ public boolean execute(@NotNull CommandSender sender, @NotNull String alias, @No
final BladeCommand finalCommand = command;
final String finalResolvedAlias = resolvedAlias;

if (finalCommand.getMethod() == null) {
throw new BladeExitMessage("The command " + finalResolvedAlias + " is a root command and cannot be executed.");
}

Runnable runnable = () -> {
try {
List<Object> parsed;
Expand All @@ -207,7 +207,6 @@ public boolean execute(@NotNull CommandSender sender, @NotNull String alias, @No
if (finalCommand.isSenderParameter()) parsed.add(0, sender);
}

finalCommand.getMethod().setAccessible(true);
finalCommand.getMethod().invoke(finalCommand.getInstance(), parsed.toArray(new Object[0]));
} catch (BladeUsageMessage ex) {
sendUsageMessage(context, finalCommand);
Expand Down
60 changes: 60 additions & 0 deletions src/main/java/me/vaperion/blade/help/impl/BukkitHelpGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package me.vaperion.blade.help.impl;

import me.vaperion.blade.command.BladeCommand;
import me.vaperion.blade.command.impl.BukkitUsageMessage;
import me.vaperion.blade.context.BladeContext;
import me.vaperion.blade.help.HelpGenerator;
import me.vaperion.blade.utils.PaginatedOutput;
import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.stream.Collectors;

public class BukkitHelpGenerator implements HelpGenerator {

@NotNull
@Override
public List<String> generate(@NotNull BladeContext context, @NotNull List<BladeCommand> commands) {
commands = commands.stream().distinct().filter(c -> !c.isHidden()).collect(Collectors.toList());

return new PaginatedOutput<BladeCommand>(10) {
@Override
public String formatErrorMessage(Error error, Object... args) {
switch (error) {
case NO_RESULTS:
return ChatColor.RED + "No results found.";
case PAGE_OUT_OF_BOUNDS:
return ChatColor.RED + String.format("Page %d does not exist, valid range is 1 to %d.", args);
}
return null;
}

@Override
public String getHeader(int page, int totalPages) {
return ChatColor.AQUA + "==== " + ChatColor.YELLOW + "Help for /" + context.alias() + ChatColor.AQUA + " ====";
}

@Override
public String getFooter(int page, int totalPages) {
return ChatColor.AQUA + "==== " + ChatColor.YELLOW + "Page " + page + "/" + totalPages + ChatColor.AQUA + " ====";
}

@Override
public String formatLine(BladeCommand result, int index) {
return ChatColor.AQUA + " - " +
ChatColor.YELLOW + ChatColor.stripColor(result.getUsageMessage().ensureGetOrLoad(() -> new BukkitUsageMessage(result)).toString().replace("Usage: ", "")) +
(result.getDescription().isEmpty() ? "" : (" - " + ChatColor.GRAY + result.getDescription()));
}
}.generatePage(commands, parsePage(context.argument(0)));
}

private int parsePage(String argument) {
if (argument == null) return 1;
try {
return Integer.parseInt(argument);
} catch (NumberFormatException e) {
return 1;
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import me.vaperion.blade.container.CommandContainer;
import me.vaperion.blade.container.ContainerCreator;
import me.vaperion.blade.help.HelpGenerator;
import me.vaperion.blade.help.impl.DefaultHelpGenerator;
import me.vaperion.blade.help.impl.NoOpHelpGenerator;
import me.vaperion.blade.permissions.PermissionPredicate;
import me.vaperion.blade.tabcompleter.TabCompleter;
import me.vaperion.blade.tabcompleter.impl.DefaultTabCompleter;
Expand All @@ -31,7 +31,7 @@ public class BladeCommandService {
@Setter @Getter private boolean overrideCommands = false;
@Setter @Getter private ContainerCreator<?> containerCreator = ContainerCreator.NONE;
@Setter @Getter private TabCompleter tabCompleter = new DefaultTabCompleter();
@Setter @Getter private HelpGenerator helpGenerator = new DefaultHelpGenerator();
@Setter @Getter private HelpGenerator helpGenerator = new NoOpHelpGenerator();
@Setter @Getter private Consumer<Runnable> asyncExecutor = Runnable::run;
@Setter @Getter private long executionTimeWarningThreshold = 5;
@Setter @Getter private String defaultPermissionMessage = "You don't have permission to perform this command.";
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/me/vaperion/blade/utils/ClassUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
@UtilityClass
public class ClassUtil {

public boolean classExists(@NotNull String className) {
try {
Class.forName(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}

@NotNull
public List<Class<?>> getClassesInPackage(@NotNull Class<?> clazz, @NotNull String packageName) {
List<Class<?>> classes = new ArrayList<>();
Expand Down
47 changes: 47 additions & 0 deletions src/main/java/me/vaperion/blade/utils/PaginatedOutput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package me.vaperion.blade.utils;

import lombok.RequiredArgsConstructor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RequiredArgsConstructor
public abstract class PaginatedOutput<T> {

private final int resultsPerPage;

public abstract String formatErrorMessage(Error error, Object... args);

public abstract String getHeader(int page, int totalPages);

public abstract String getFooter(int page, int totalPages);

public abstract String formatLine(T result, int index);

public final List<String> generatePage(List<T> results, int page) {
if (results.size() == 0) {
return Collections.singletonList(formatErrorMessage(Error.NO_RESULTS));
}

int totalPages = results.size() / resultsPerPage + (results.size() % resultsPerPage == 0 ? 0 : 1);
if (page < 1 || page > totalPages) {
return Collections.singletonList(formatErrorMessage(Error.PAGE_OUT_OF_BOUNDS, page, totalPages));
}

int startIndex = (page - 1) * resultsPerPage;
int endIndex = Math.min(startIndex + resultsPerPage, results.size());

List<String> lines = new ArrayList<>();
lines.add(getHeader(page, totalPages));
results.subList(startIndex, endIndex).forEach(result -> lines.add(formatLine(result, startIndex + lines.size())));
lines.add(getFooter(page, totalPages));
return lines;
}

public enum Error {
NO_RESULTS,
PAGE_OUT_OF_BOUNDS
}

}

0 comments on commit 02f126e

Please sign in to comment.