Merge pull request #7 from PlexDevelopment/reflection

Use Google's reflection library to register commands
This commit is contained in:
Telesphoreo 2022-03-18 22:44:18 -05:00 committed by GitHub
commit 172080576c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 97 additions and 41 deletions

View file

@ -0,0 +1,7 @@
package dev.plex.command.annotation;
public @interface System
{
String value();
}

View file

@ -5,6 +5,7 @@ import dev.plex.cache.DataUtils;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.annotation.System;
import dev.plex.command.exception.ConsoleOnlyException; import dev.plex.command.exception.ConsoleOnlyException;
import dev.plex.command.exception.PlayerNotFoundException; import dev.plex.command.exception.PlayerNotFoundException;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
@ -27,6 +28,7 @@ import org.jetbrains.annotations.Nullable;
@CommandPermissions(level = Rank.OP, source = RequiredCommandSource.ANY) @CommandPermissions(level = Rank.OP, source = RequiredCommandSource.ANY)
@CommandParameters(name = "admin", usage = "/<command> <add <player> | remove <player> | setrank <player> <rank> | list>", aliases = "saconfig,slconfig,adminconfig,adminmanage", description = "Manage all admins") @CommandParameters(name = "admin", usage = "/<command> <add <player> | remove <player> | setrank <player> <rank> | list>", aliases = "saconfig,slconfig,adminconfig,adminmanage", description = "Manage all admins")
@System("ranks")
public class AdminCMD extends PlexCommand public class AdminCMD extends PlexCommand
{ {
//TODO: Better return messages //TODO: Better return messages

View file

@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.annotation.System;
import dev.plex.rank.enums.Rank; import dev.plex.rank.enums.Rank;
import dev.plex.util.PlexLog; import dev.plex.util.PlexLog;
import dev.plex.util.PlexUtils; import dev.plex.util.PlexUtils;
@ -19,6 +20,7 @@ import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "pdebug", description = "Plex's debug command", usage = "/<command> <redis-reset <player> | gamerules>") @CommandParameters(name = "pdebug", description = "Plex's debug command", usage = "/<command> <redis-reset <player> | gamerules>")
@CommandPermissions(level = Rank.EXECUTIVE, permission = "plex.debug") @CommandPermissions(level = Rank.EXECUTIVE, permission = "plex.debug")
@System("debug")
public class DebugCMD extends PlexCommand public class DebugCMD extends PlexCommand
{ {
@Override @Override

View file

@ -3,6 +3,7 @@ package dev.plex.command.impl;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.annotation.System;
import dev.plex.rank.enums.Rank; import dev.plex.rank.enums.Rank;
import dev.plex.util.PlexUtils; import dev.plex.util.PlexUtils;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -14,6 +15,7 @@ import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "deopall", description = "Deop everyone on the server", aliases = "deopa") @CommandParameters(name = "deopall", description = "Deop everyone on the server", aliases = "deopa")
@CommandPermissions(level = Rank.ADMIN) @CommandPermissions(level = Rank.ADMIN)
@System("ranks")
public class DeopAllCMD extends PlexCommand public class DeopAllCMD extends PlexCommand
{ {
@Override @Override

View file

@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.annotation.System;
import dev.plex.rank.enums.Rank; import dev.plex.rank.enums.Rank;
import dev.plex.util.PlexUtils; import dev.plex.util.PlexUtils;
import java.util.List; import java.util.List;
@ -15,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "deop", description = "Deop a player on the server", usage = "/<command> <player>") @CommandParameters(name = "deop", description = "Deop a player on the server", usage = "/<command> <player>")
@CommandPermissions(level = Rank.ADMIN, permission = "plex.deop") @CommandPermissions(level = Rank.ADMIN, permission = "plex.deop")
@System("ranks")
public class DeopCMD extends PlexCommand public class DeopCMD extends PlexCommand
{ {
@Override @Override

View file

@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.annotation.System;
import dev.plex.rank.enums.Rank; import dev.plex.rank.enums.Rank;
import java.util.List; import java.util.List;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -16,6 +17,7 @@ import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "list", description = "Show a list of all online players") @CommandParameters(name = "list", description = "Show a list of all online players")
@CommandPermissions(level = Rank.OP, permission = "plex.list") @CommandPermissions(level = Rank.OP, permission = "plex.list")
@System("ranks")
public class ListCMD extends PlexCommand public class ListCMD extends PlexCommand
{ {
@Override @Override

View file

@ -3,6 +3,7 @@ package dev.plex.command.impl;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.annotation.System;
import dev.plex.rank.enums.Rank; import dev.plex.rank.enums.Rank;
import dev.plex.util.PlexUtils; import dev.plex.util.PlexUtils;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -14,6 +15,7 @@ import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "opall", description = "Op everyone on the server", aliases = "opa") @CommandParameters(name = "opall", description = "Op everyone on the server", aliases = "opa")
@CommandPermissions(level = Rank.ADMIN) @CommandPermissions(level = Rank.ADMIN)
@System("ranks")
public class OpAllCMD extends PlexCommand public class OpAllCMD extends PlexCommand
{ {
@Override @Override

View file

@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.annotation.System;
import dev.plex.rank.enums.Rank; import dev.plex.rank.enums.Rank;
import dev.plex.util.PlexUtils; import dev.plex.util.PlexUtils;
import java.util.List; import java.util.List;
@ -15,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
@CommandParameters(name = "op", description = "Op a player on the server", usage = "/<command> <player>") @CommandParameters(name = "op", description = "Op a player on the server", usage = "/<command> <player>")
@CommandPermissions(level = Rank.OP) @CommandPermissions(level = Rank.OP)
@System("ranks")
public class OpCMD extends PlexCommand public class OpCMD extends PlexCommand
{ {
@Override @Override

View file

@ -3,6 +3,7 @@ package dev.plex.command.impl;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandParameters; import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.annotation.System;
import dev.plex.command.exception.CommandFailException; import dev.plex.command.exception.CommandFailException;
import dev.plex.command.source.RequiredCommandSource; import dev.plex.command.source.RequiredCommandSource;
import dev.plex.rank.enums.Rank; import dev.plex.rank.enums.Rank;
@ -14,6 +15,7 @@ import org.jetbrains.annotations.Nullable;
@CommandPermissions(level = Rank.OP, permission = "plex.rank", source = RequiredCommandSource.ANY) @CommandPermissions(level = Rank.OP, permission = "plex.rank", source = RequiredCommandSource.ANY)
@CommandParameters(name = "rank", description = "Displays your rank") @CommandParameters(name = "rank", description = "Displays your rank")
@System("ranks")
public class RankCMD extends PlexCommand public class RankCMD extends PlexCommand
{ {
@Override @Override

View file

@ -3,55 +3,39 @@ package dev.plex.handlers;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import dev.plex.PlexBase; import dev.plex.PlexBase;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
import dev.plex.command.impl.*; import dev.plex.command.annotation.System;
import dev.plex.util.PlexLog; import dev.plex.util.PlexLog;
import dev.plex.util.PlexUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.List; import java.util.List;
import java.util.Set;
// TODO: Switch to Reflections API
public class CommandHandler extends PlexBase public class CommandHandler extends PlexBase
{ {
public CommandHandler() public CommandHandler()
{ {
Set<Class<? extends PlexCommand>> commandSet = PlexUtils.getClassesBySubType("dev.plex.command.impl", PlexCommand.class);
List<PlexCommand> commands = Lists.newArrayList(); List<PlexCommand> commands = Lists.newArrayList();
if (plugin.getSystem().equalsIgnoreCase("ranks"))
commandSet.forEach(clazz ->
{ {
commands.add(new AdminCMD()); try
commands.add(new DeopAllCMD()); {
commands.add(new DeopCMD()); System annotation = clazz.getDeclaredAnnotation(System.class);
commands.add(new ListCMD()); if (annotation != null && annotation.value().equalsIgnoreCase(plugin.getSystem()))
commands.add(new OpAllCMD()); {
commands.add(new OpCMD()); commands.add(clazz.getConstructor().newInstance());
commands.add(new RankCMD()); return;
} }
if (plugin.config.getBoolean("debug"))
{ commands.add(clazz.getConstructor().newInstance());
commands.add(new DebugCMD()); }
} catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException ex)
commands.add(new AdminChatCMD()); {
commands.add(new AdminworldCMD()); PlexLog.log("Failed to register " + clazz.getSimpleName() + " as a command!");
commands.add(new AdventureCMD()); }
commands.add(new BanCMD()); });
commands.add(new CommandSpyCMD());
commands.add(new CreativeCMD()); PlexLog.log(String.format("Registered %s commands from %s classes!", commands.size(), commandSet.size()));
commands.add(new FlatlandsCMD());
commands.add(new FreezeCMD());
commands.add(new KickCMD());
commands.add(new LocalSpawnCMD());
commands.add(new LockupCMD());
commands.add(new MasterbuilderworldCMD());
commands.add(new MuteCMD());
commands.add(new NameHistoryCMD());
commands.add(new PlexCMD());
commands.add(new PunishmentsCMD());
commands.add(new RawSayCMD());
commands.add(new SpectatorCMD());
commands.add(new SurvivalCMD());
commands.add(new TagCMD());
commands.add(new TempbanCMD());
commands.add(new UnbanCMD());
commands.add(new UnfreezeCMD());
commands.add(new UnmuteCMD());
commands.add(new WorldCMD());
PlexLog.log(String.format("Registered %s commands!", commands.size()));
} }
} }

View file

@ -1,5 +1,7 @@
package dev.plex.util; package dev.plex.util;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.ClassPath;
import dev.plex.Plex; import dev.plex.Plex;
import dev.plex.PlexBase; import dev.plex.PlexBase;
import dev.plex.config.Config; import dev.plex.config.Config;
@ -15,12 +17,15 @@ import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -320,6 +325,50 @@ public class PlexUtils extends PlexBase
return UUID.fromString(uuidString); return UUID.fromString(uuidString);
} }
@SuppressWarnings("UnstableApiUsage")
public static Set<Class<?>> getClassesFrom(String packageName)
{
Set<Class<?>> classes = new HashSet<>();
try
{
ClassPath path = ClassPath.from(Plex.class.getClassLoader());
ImmutableSet<ClassPath.ClassInfo> infoSet = path.getTopLevelClasses(packageName);
infoSet.forEach(info ->
{
try
{
Class<?> clazz = Class.forName(info.getName());
classes.add(clazz);
}
catch (ClassNotFoundException ex)
{
PlexLog.error("Unable to find class " + info.getName() + " in " + packageName);
}
});
}
catch (IOException ex)
{
PlexLog.error("Something went wrong while fetching classes from " + packageName);
throw new RuntimeException(ex);
}
return Collections.unmodifiableSet(classes);
}
@SuppressWarnings("unchecked")
public static <T> Set<Class<? extends T>> getClassesBySubType(String packageName, Class<T> subType)
{
Set<Class<?>> loadedClasses = getClassesFrom(packageName);
Set<Class<? extends T>> classes = new HashSet<>();
loadedClasses.forEach(clazz ->
{
if (clazz.getSuperclass() == subType || Arrays.asList(clazz.getInterfaces()).contains(subType))
{
classes.add((Class<? extends T>)clazz);
}
});
return Collections.unmodifiableSet(classes);
}
public static int randomNum() public static int randomNum()
{ {
return ThreadLocalRandom.current().nextInt(); return ThreadLocalRandom.current().nextInt();