Create Cladis (NetworkManager Hook)

Signed-off-by: Paul Reilly <pawereus@gmail.com>
This commit is contained in:
Paul Reilly 2023-08-11 14:08:49 -05:00
parent 8e5c52d0e8
commit bbaa325ad6
10 changed files with 621 additions and 6 deletions

42
Cladis/.gitignore vendored Normal file
View File

@ -0,0 +1,42 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

25
Cladis/build.gradle Normal file
View File

@ -0,0 +1,25 @@
plugins {
id 'java'
}
group = 'fns.cladis'
version = '1.0.0'
repositories {
mavenCentral()
maven {
url 'https://repo.networkmanager.xyz/repository/maven-public/'
}
}
dependencies {
compileOnly project(":Patchwork")
compileOnly 'nl.chimpgamer.networkmanager:api:2.13.1'
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
}
test {
useJUnitPlatform()
}

View File

@ -0,0 +1,45 @@
package fns.cladis;
import fns.cladis.command.OpCommand;
import fns.patchwork.base.Registration;
import fns.patchwork.command.CommandHandler;
import org.bukkit.plugin.java.JavaPlugin;
public class Cladis extends JavaPlugin
{
private NMLink nmLink;
@Override
public void onEnable()
{
if (this.getServer().getPluginManager().getPlugin("NetworkManager") == null)
{
getLogger().severe("NetworkManager not found! Disabling Cladis...");
this.getServer().getPluginManager().disablePlugin(this);
return;
}
this.nmLink = new NMLink(this);
new CommandHandler(this).registerCommands(OpCommand.class);
Registration.getModuleRegistry()
.addModule(this);
getLogger().info("Cladis enabled!");
}
@Override
public void onDisable()
{
Registration.getModuleRegistry()
.removeModule(this);
getLogger().info("Cladis disabled!");
}
public NMLink getNMLink()
{
return this.nmLink;
}
}

View File

@ -0,0 +1,118 @@
package fns.cladis;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import nl.chimpgamer.networkmanager.api.NetworkManagerPlugin;
import nl.chimpgamer.networkmanager.api.NetworkManagerProvider;
import nl.chimpgamer.networkmanager.api.cache.CacheManager;
import nl.chimpgamer.networkmanager.api.models.permissions.Group;
import nl.chimpgamer.networkmanager.api.models.permissions.PermissionPlayer;
import nl.chimpgamer.networkmanager.api.models.player.Player;
public class NMLink
{
private NetworkManagerPlugin networkManager;
public NMLink(final Cladis plugin)
{
this.networkManager = NetworkManagerProvider.Companion.get();
plugin.getSLF4JLogger().info("NetworkManager successfully linked!");
}
public CacheManager getCacheManager()
{
return this.networkManager.getCacheManager();
}
public Optional<Player> getPlayer(final UUID uuid)
{
return getCacheManager().getCachedPlayers().getPlayerSafe(uuid);
}
public PermissionPlayer getPermissionsPlayer(final UUID uuid)
{
return networkManager.getPermissionManager().getPermissionPlayer(uuid);
}
public List<Group> getPlayerGroups(final UUID uuid)
{
return getPermissionsPlayer(uuid).getGroups();
}
public Map<Integer, Group> getLoadedGroups()
{
return networkManager.getPermissionManager().getGroups();
}
public Optional<Group> locateGroup(final String name)
{
return Optional.of(networkManager.getPermissionManager().getGroup(name));
}
public Group opGroup()
{
return locateGroup("fake_op").orElse(null);
}
public Group deopGroup()
{
return locateGroup("fake_deop").orElse(null);
}
public Group masterBuilderGroup()
{
return locateGroup("master_builder").orElse(null);
}
public Group adminGroup()
{
return locateGroup("admin").orElse(null);
}
public Group seniorGroup()
{
return locateGroup("senior").orElse(null);
}
public Group devGroup()
{
return locateGroup("developer").orElse(null);
}
public Group execGroup()
{
return locateGroup("executive").orElse(null);
}
public boolean isOp(final UUID uuid)
{
return getPlayerGroups(uuid).contains(opGroup());
}
public boolean isDeop(final UUID uuid)
{
return getPlayerGroups(uuid).contains(deopGroup());
}
public boolean isAdmin(final UUID uuid)
{
return getPlayerGroups(uuid).contains(seniorGroup()) || getPlayerGroups(uuid).contains(adminGroup());
}
public boolean isSenior(final UUID uuid)
{
return getPlayerGroups(uuid).contains(seniorGroup());
}
public boolean isDev(final UUID uuid)
{
return getPlayerGroups(uuid).contains(devGroup());
}
public boolean isExec(final UUID uuid)
{
return getPlayerGroups(uuid).contains(execGroup());
}
}

View File

@ -0,0 +1,64 @@
package fns.cladis.command;
import fns.cladis.Cladis;
import fns.cladis.NMLink;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import nl.chimpgamer.networkmanager.api.models.permissions.Group;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(
name = "deop",
description = "Deop a player.",
usage = "/deop <player>"
)
@Permissive(perm = "cladis.deop")
@Completion(index = 0, args = {"%player%"})
public class DeopCommand extends Commander
{
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
protected DeopCommand(@NotNull final JavaPlugin plugin)
{
super(plugin);
}
@Subcommand(permission = "cladis.deop", args = {Player.class})
public void deop(final CommandSender sender, final Player player)
{
final NMLink nmLink = Shortcuts.provideModule(Cladis.class).getNMLink();
final Group opGroup = nmLink.deopGroup();
if (opGroup == null)
{
sender.sendPlainMessage("Unable to deop player. Please contact an administrator.");
return;
}
if (nmLink.isDeop(player.getUniqueId()))
{
sender.sendPlainMessage("Player is not op.");
return;
}
nmLink.getPlayerGroups(player.getUniqueId()).remove(opGroup);
sender.sendPlainMessage("Player deopped.");
player.sendPlainMessage("You have been deopped!");
}
}

View File

@ -0,0 +1,217 @@
package fns.cladis.command;
import fns.cladis.Cladis;
import fns.cladis.NMLink;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Base;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import java.util.Map;
import nl.chimpgamer.networkmanager.api.models.permissions.Group;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(
name = "modstaff",
description = "Mod a player.",
usage = """
/modstaff
/modstaff info <player>
/modstaff <add | remove> <player> <group>
/modstaff <promote | demote> <player>
""",
aliases = {"ms", "saconfig", "adminlist", "al"}
)
@Permissive(perm = "cladis.modstaff")
@Completion(index = 0, args = {"info", "add", "remove", "promote", "demote"})
@Completion(index = 1, args = {"%player%"})
@Completion(index = 2, args = {"<group>"})
public class ModStaffCommand extends Commander
{
public static final String USER_NOT_FOUND = "That user does not exist!";
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public ModStaffCommand(@NotNull final JavaPlugin plugin)
{
super(plugin);
}
@Base
public void base(final CommandSender sender)
{
final NMLink nmLink = Shortcuts.provideModule(Cladis.class).getNMLink();
final StringBuilder stringBuilder = new StringBuilder();
nmLink.getCacheManager()
.getCachedPlayers()
.getPlayers()
.forEach((u, p) ->
{
if (nmLink.isAdmin(u) || nmLink.isSenior(u))
{
stringBuilder.append(nmLink.getPermissionsPlayer(u)
.getPrimaryGroup()
.getPrefixes()
.values()
.stream()
.findFirst()
.orElseGet(() -> "[Admin]"))
.append(" ")
.append(p.getName()).append(", ");
}
});
sender.sendPlainMessage(stringBuilder.toString());
}
@Subcommand(permission = "cladis.modstaff.info", args = {String.class, Player.class})
public void info(final CommandSender sender, final String info, final Player player)
{
if (!info.equalsIgnoreCase("info"))
return;
final NMLink nmLink = Shortcuts.provideModule(Cladis.class).getNMLink();
final StringBuilder stringBuilder = new StringBuilder();
final nl.chimpgamer.networkmanager.api.models.player.Player nmPlayer =
nmLink.getPlayer(player.getUniqueId()).orElse(null);
if (nmPlayer == null)
{
sender.sendPlainMessage(USER_NOT_FOUND);
return;
}
stringBuilder.append("Player: ")
.append(player.getName())
.append("\n");
stringBuilder.append("UUID: ")
.append(nmPlayer.getUuid())
.append("\n");
stringBuilder.append("Rank: ")
.append(nmLink.getPermissionsPlayer(player.getUniqueId()).getPrimaryGroup().getName())
.append("\n");
stringBuilder.append("IP: ")
.append(nmPlayer.getIp())
.append("\n");
stringBuilder.append("Playtime: ")
.append(nmPlayer.getPlaytime())
.append("\n");
stringBuilder.append("Last Online: ")
.append(nmPlayer.getLastlogin())
.append("\n");
sender.sendPlainMessage(stringBuilder.toString());
}
@Subcommand(permission = "cladis.modstaff.modify", args = {String.class, Player.class, String.class})
public void modify(final CommandSender sender, final String arg, final Player target, final String group)
{
final NMLink nmLink = Shortcuts.provideModule(Cladis.class).getNMLink();
final nl.chimpgamer.networkmanager.api.models.player.Player nmPlayer =
nmLink.getPlayer(target.getUniqueId()).orElse(null);
if (nmPlayer == null)
{
sender.sendPlainMessage(USER_NOT_FOUND);
return;
}
final Map.Entry<Integer, Group> g =
nmLink.getLoadedGroups().entrySet().stream().filter(e -> e.getValue().getName().equalsIgnoreCase(group))
.findFirst().orElse(null);
if (g == null)
{
sender.sendPlainMessage("That group does not exist!");
return;
}
if (sender instanceof Player player && (nmLink.getPermissionsPlayer(player.getUniqueId())
.getPrimaryGroup()
.getId() <= g.getKey()))
{
sender.sendPlainMessage("You cannot modify a player to a higher rank than yourself!");
return;
}
if (arg.equalsIgnoreCase("add"))
{
nmLink.getPermissionsPlayer(target.getUniqueId()).getGroups().add(g.getValue());
sender.sendPlainMessage("Added " + target.getName() + " to " + group);
}
else if (arg.equalsIgnoreCase("remove"))
{
nmLink.getPermissionsPlayer(target.getUniqueId()).getGroups().remove(g.getValue());
sender.sendPlainMessage("Removed " + target.getName() + " from " + group);
}
else
{
sender.sendPlainMessage("Invalid argument!");
}
}
@Subcommand(permission = "cladis.modstaff.track", args = {String.class, Player.class})
public void track(final CommandSender sender, final String arg, final Player target)
{
final NMLink nmLink = Shortcuts.provideModule(Cladis.class).getNMLink();
final nl.chimpgamer.networkmanager.api.models.player.Player nmPlayer =
nmLink.getPlayer(target.getUniqueId()).orElse(null);
if (nmPlayer == null)
{
sender.sendPlainMessage(USER_NOT_FOUND);
return;
}
final Group primary = nmLink.getPermissionsPlayer(target.getUniqueId()).getPrimaryGroup();
final int groupLevel = primary.getId();
if (arg.equalsIgnoreCase("promote"))
{
final Group promo = nmLink.getLoadedGroups().get(groupLevel + 1);
if (promo == null)
{
sender.sendPlainMessage("That user is already at the highest rank!");
return;
}
nmLink.getPermissionsPlayer(target.getUniqueId()).getGroups().remove(primary);
nmLink.getPermissionsPlayer(target.getUniqueId())
.getGroups()
.add(promo);
sender.sendPlainMessage("Promoted " + target.getName());
}
else if (arg.equalsIgnoreCase("demote"))
{
final Group demo = nmLink.getLoadedGroups().get(groupLevel - 1);
if (demo == null)
{
sender.sendPlainMessage("That user is already at the lowest rank!");
return;
}
nmLink.getPermissionsPlayer(target.getUniqueId()).getGroups().remove(primary);
nmLink.getPermissionsPlayer(target.getUniqueId())
.getGroups()
.add(demo);
sender.sendPlainMessage("Demoted " + target.getName());
}
else
{
sender.sendPlainMessage("Invalid argument!");
}
}
}

View File

@ -0,0 +1,65 @@
package fns.cladis.command;
import fns.cladis.Cladis;
import fns.cladis.NMLink;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import nl.chimpgamer.networkmanager.api.models.permissions.Group;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(
name = "op",
description = "Op a player.",
usage = "/op <player>"
)
@Permissive(perm = "cladis.op")
@Completion(index = 0, args = {"%player%"})
public class OpCommand extends Commander
{
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public OpCommand(@NotNull final JavaPlugin plugin)
{
super(plugin);
}
@Subcommand(permission = "cladis.op", args = {Player.class})
public void op(@NotNull final CommandSender sender, final Player player)
{
final NMLink nmLink = Shortcuts.provideModule(Cladis.class).getNMLink();
final Group opGroup = nmLink.locateGroup("fake_op").orElse(null);
if (opGroup == null)
{
sender.sendPlainMessage("Unable to op player. Please contact an administrator.");
return;
}
if (nmLink.isOp(player.getUniqueId()))
{
sender.sendPlainMessage("Player is already op.");
return;
}
nmLink.getPermissionsPlayer(player.getUniqueId()).getGroups().add(opGroup);
sender.sendPlainMessage("You have opped " + player.getName() + ".");
player.sendPlainMessage("You have been opped.");
}
}

View File

@ -23,9 +23,11 @@
package fns.patchwork.command; package fns.patchwork.command;
import java.util.Objects;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandMap; import org.bukkit.command.CommandMap;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.reflections.Reflections;
/** /**
* Handles the registration of commands. The plugin which initializes this class should be the plugin that is * Handles the registration of commands. The plugin which initializes this class should be the plugin that is
@ -64,4 +66,32 @@ public class CommandHandler
Bukkit.getCommandMap() Bukkit.getCommandMap()
.register(plugin.getName(), delegate); .register(plugin.getName(), delegate);
} }
/**
* Registers all commands in the specified package that contains the provided class. This method will automatically
* delegate the command information to the Bukkit API and register with the {@link CommandMap}.
*
* @param commandClass The class to register commands from.
* @param <T> The type of the command.
*/
public <T extends Commander> void registerCommands(final Class<T> commandClass)
{
final Reflections reflections = new Reflections(commandClass.getPackageName());
reflections.getSubTypesOf(commandClass)
.stream()
.map(c ->
{
try
{
return c.getDeclaredConstructor(JavaPlugin.class).newInstance(this);
}
catch (ReflectiveOperationException ex)
{
plugin.getSLF4JLogger().error("Unable to register command: " + c.getName(), ex);
return null;
}
})
.filter(Objects::nonNull)
.forEach(this::registerCommand);
}
} }

View File

@ -23,8 +23,6 @@
package fns.patchwork.provider; package fns.patchwork.provider;
import fns.patchwork.command.BukkitDelegate;
import fns.patchwork.command.annotation.Subcommand;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -33,8 +31,8 @@ import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -65,12 +63,13 @@ public class ContextProvider
public <T> T fromString(final String string, final Class<T> clazz) public <T> T fromString(final String string, final Class<T> clazz)
{ {
return Stream.of(toBoolean(string, clazz), return Stream.of(toBoolean(string, clazz),
toLong(string, clazz),
toDouble(string, clazz), toDouble(string, clazz),
toInt(string, clazz), toInt(string, clazz),
toLong(string, clazz),
toFloat(string, clazz), toFloat(string, clazz),
toMaterial(string, clazz), toMaterial(string, clazz),
toPlayer(string, clazz), toPlayer(string, clazz),
toOfflinePlayer(string, clazz),
toWorld(string, clazz), toWorld(string, clazz),
toLocation(string, clazz), toLocation(string, clazz),
toComponent(string, clazz)) toComponent(string, clazz))
@ -127,7 +126,7 @@ public class ContextProvider
private @Nullable Long toLong(final String string, final Class<?> clazz) private @Nullable Long toLong(final String string, final Class<?> clazz)
{ {
if (clazz != Long.class) if (clazz != Long.class || string.endsWith("L"))
return null; return null;
try try
@ -169,6 +168,16 @@ public class ContextProvider
return Bukkit.getPlayer(string); return Bukkit.getPlayer(string);
} }
private OfflinePlayer toOfflinePlayer(final String string, final Class<?> clazz)
{
if (clazz != OfflinePlayer.class)
{
return null;
}
return Bukkit.getOfflinePlayer(string);
}
private @Nullable World toWorld(final String string, final Class<?> clazz) private @Nullable World toWorld(final String string, final Class<?> clazz)
{ {
if (clazz != World.class) if (clazz != World.class)

View File

@ -3,4 +3,4 @@ include 'Patchwork'
include 'Datura' include 'Datura'
include 'Fossil' include 'Fossil'
include 'Corvo' include 'Corvo'
include 'Cladis'