mirror of
https://github.com/SimplexDevelopment/FreedomNetworkSuite.git
synced 2025-06-26 19:44:27 +00:00
updates 🎱
This commit is contained in:
@ -16,13 +16,13 @@ import java.util.function.Function;
|
||||
@FunctionalInterface
|
||||
public interface Context<T>
|
||||
{
|
||||
T get();
|
||||
|
||||
default <S> Context<S> map(@NotNull final Function<T, S> mapper)
|
||||
{
|
||||
return () -> mapper.apply(get());
|
||||
}
|
||||
|
||||
T get();
|
||||
|
||||
default @Nullable String asString()
|
||||
{
|
||||
if (get() instanceof String string)
|
||||
@ -56,26 +56,35 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
default @Nullable Integer asInt() {
|
||||
if (get() instanceof Integer integer) {
|
||||
default @Nullable Integer asInt()
|
||||
{
|
||||
if (get() instanceof Integer integer)
|
||||
{
|
||||
return integer;
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
default @Nullable Long asLong() {
|
||||
if (get() instanceof Long longg) {
|
||||
default @Nullable Long asLong()
|
||||
{
|
||||
if (get() instanceof Long longg)
|
||||
{
|
||||
return longg;
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
default @Nullable Float asFloat() {
|
||||
if (get() instanceof Float floatt) {
|
||||
default @Nullable Float asFloat()
|
||||
{
|
||||
if (get() instanceof Float floatt)
|
||||
{
|
||||
return floatt;
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A replacement for {@link net.kyori.adventure.audience.ForwardingAudience} that allows for audiences to be removed & added at will. Not thread safe.
|
||||
* A replacement for {@link net.kyori.adventure.audience.ForwardingAudience} that allows for audiences to be removed
|
||||
* & added at will. Not thread safe.
|
||||
* <p>
|
||||
* This is intended for use in toggleable logging systems, for example, potion spy.
|
||||
*/
|
||||
@ -60,9 +61,9 @@ public class MutableAudienceForwarder implements Audience
|
||||
public @NotNull Audience filterAudience(@NotNull final Predicate<? super Audience> filter)
|
||||
{
|
||||
return audiences.stream()
|
||||
.filter(filter)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
.filter(filter)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,25 +16,23 @@ public class CommonsBase extends JavaPlugin
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
public void onDisable()
|
||||
{
|
||||
getRegistrations().getServiceRegistry().register(this, eventBus);
|
||||
getExecutor().getSync()
|
||||
.execute(() -> getRegistrations()
|
||||
.getServiceRegistry()
|
||||
.startAll());
|
||||
getRegistrations().getServiceRegistry()
|
||||
.stopAll();
|
||||
getRegistrations().getServiceRegistry()
|
||||
.unregister(EventBus.class, eventBus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable()
|
||||
public void onEnable()
|
||||
{
|
||||
getRegistrations().getServiceRegistry().stopAll();
|
||||
getRegistrations().getServiceRegistry().unregister(EventBus.class, eventBus);
|
||||
}
|
||||
|
||||
public Registration getRegistrations()
|
||||
{
|
||||
return registration;
|
||||
getRegistrations().getServiceRegistry()
|
||||
.register(this, eventBus);
|
||||
getExecutor().getSync()
|
||||
.execute(() -> getRegistrations()
|
||||
.getServiceRegistry()
|
||||
.startAll());
|
||||
}
|
||||
|
||||
public FreedomExecutor getExecutor()
|
||||
@ -42,6 +40,11 @@ public class CommonsBase extends JavaPlugin
|
||||
return executor;
|
||||
}
|
||||
|
||||
public Registration getRegistrations()
|
||||
{
|
||||
return registration;
|
||||
}
|
||||
|
||||
public EventBus getEventBus()
|
||||
{
|
||||
return eventBus;
|
||||
|
@ -1,12 +1,11 @@
|
||||
package me.totalfreedom.base;
|
||||
|
||||
import me.totalfreedom.data.GroupRegistry;
|
||||
import me.totalfreedom.data.BanRegistry;
|
||||
import me.totalfreedom.data.ConfigRegistry;
|
||||
import me.totalfreedom.data.EventRegistry;
|
||||
import me.totalfreedom.data.GroupRegistry;
|
||||
import me.totalfreedom.data.ModuleRegistry;
|
||||
import me.totalfreedom.data.ServiceRegistry;
|
||||
import me.totalfreedom.data.UserRegistry;
|
||||
import me.totalfreedom.data.EventRegistry;
|
||||
|
||||
public class Registration
|
||||
{
|
||||
@ -15,7 +14,6 @@ public class Registration
|
||||
private final ServiceRegistry serviceRegistry;
|
||||
private final ModuleRegistry moduleRegistry;
|
||||
private final GroupRegistry groupRegistry;
|
||||
private final BanRegistry banRegistry;
|
||||
private final ConfigRegistry configRegistry;
|
||||
|
||||
public Registration()
|
||||
@ -25,8 +23,7 @@ public class Registration
|
||||
this.serviceRegistry = new ServiceRegistry();
|
||||
this.moduleRegistry = new ModuleRegistry();
|
||||
this.groupRegistry = new GroupRegistry();
|
||||
this.banRegistry = new BanRegistry();
|
||||
this.configRegistry = new ConfigRegistry();
|
||||
this.configRegistry = new ConfigRegistry();
|
||||
}
|
||||
|
||||
public ModuleRegistry getModuleRegistry()
|
||||
@ -54,11 +51,6 @@ public class Registration
|
||||
return groupRegistry;
|
||||
}
|
||||
|
||||
public BanRegistry getBanRegistry()
|
||||
{
|
||||
return banRegistry;
|
||||
}
|
||||
|
||||
public ConfigRegistry getConfigRegistry()
|
||||
{
|
||||
return configRegistry;
|
||||
|
@ -0,0 +1,188 @@
|
||||
package me.totalfreedom.command;
|
||||
|
||||
import me.totalfreedom.api.Context;
|
||||
import me.totalfreedom.command.annotation.Completion;
|
||||
import me.totalfreedom.command.annotation.Subcommand;
|
||||
import me.totalfreedom.provider.ContextProvider;
|
||||
import me.totalfreedom.utils.FreedomLogger;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.command.PluginIdentifiableCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class BukkitDelegate extends Command implements PluginIdentifiableCommand
|
||||
{
|
||||
private final JavaPlugin plugin;
|
||||
private final Commander command;
|
||||
private final boolean noConsole;
|
||||
|
||||
BukkitDelegate(final Commander command)
|
||||
{
|
||||
super(command.getInfo()
|
||||
.name());
|
||||
this.command = command;
|
||||
this.plugin = command.getPlugin();
|
||||
this.setDescription(command.getInfo()
|
||||
.description());
|
||||
this.setUsage(command.getInfo()
|
||||
.usage());
|
||||
this.setPermission(command.getPerms()
|
||||
.perm());
|
||||
this.setAliases(Arrays.asList(command.getInfo()
|
||||
.aliases()));
|
||||
this.permissionMessage(Component.text(command.getPerms()
|
||||
.noPerms()));
|
||||
this.noConsole = command.getPerms()
|
||||
.onlyPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull final CommandSender sender,
|
||||
@NotNull final String commandLabel,
|
||||
@NotNull final String[] args)
|
||||
{
|
||||
if (sender instanceof ConsoleCommandSender && noConsole)
|
||||
{
|
||||
sender.sendMessage(Component.text("This command can only be run by players."));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getPermission() != null && !sender.hasPermission(getPermission()))
|
||||
{
|
||||
Component permissionMessage = permissionMessage();
|
||||
if (permissionMessage == null)
|
||||
permissionMessage = Component.text("You do not have permission to use this command.");
|
||||
sender.sendMessage(permissionMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length > 0)
|
||||
{
|
||||
final ContextProvider provider = new ContextProvider();
|
||||
final Set<Subcommand> nodes = command.getSubcommands()
|
||||
.keySet();
|
||||
for (final Subcommand node : nodes)
|
||||
{
|
||||
processSubCommands(args, sender, provider, node);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (command.getBaseMethod() != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
command.getBaseMethod()
|
||||
.invoke(command, sender);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FreedomLogger.getLogger("Patchwork")
|
||||
.error(ex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void processSubCommands(final @NotNull String @NotNull [] args,
|
||||
final CommandSender sender, final ContextProvider provider,
|
||||
final Subcommand node)
|
||||
{
|
||||
final Class<?>[] argTypes = node.args();
|
||||
if (argTypes.length != args.length)
|
||||
return;
|
||||
|
||||
final Object[] objects = new Object[argTypes.length + 1];
|
||||
|
||||
for (int i = 0; i < argTypes.length; i++)
|
||||
{
|
||||
final Class<?> argType = argTypes[i];
|
||||
final String arg = args[i];
|
||||
|
||||
if (argType == String.class)
|
||||
continue;
|
||||
|
||||
final Context<?> context = () -> provider.fromString(arg, argType);
|
||||
objects[i] = context.get();
|
||||
}
|
||||
try
|
||||
{
|
||||
command.getSubcommands()
|
||||
.get(node)
|
||||
.invoke(command, sender, objects);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FreedomLogger.getLogger("Patchwork")
|
||||
.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(final CommandSender sender, final String alias, final String[] args)
|
||||
{
|
||||
final Set<Completion> completions = command.getCompletions();
|
||||
final List<String> results = new ArrayList<>();
|
||||
for (final Completion completion : completions)
|
||||
{
|
||||
if (completion.index() != args.length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (final String p : completion.args())
|
||||
{
|
||||
switch (p)
|
||||
{
|
||||
case "%player%" -> results.addAll(Bukkit.getOnlinePlayers()
|
||||
.stream()
|
||||
.map(Player::getName)
|
||||
.toList());
|
||||
case "%world%" -> results.addAll(Bukkit.getWorlds()
|
||||
.stream()
|
||||
.map(World::getName)
|
||||
.toList());
|
||||
case "%number%" -> results.addAll(List.of(
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9"));
|
||||
case "%location%" -> results.add("world,x,y,z");
|
||||
default -> results.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results.stream()
|
||||
.filter(s -> s.startsWith(args[args.length - 1]))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Plugin getPlugin()
|
||||
{
|
||||
return this.plugin;
|
||||
}
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
package me.totalfreedom.command;
|
||||
|
||||
import me.totalfreedom.api.Context;
|
||||
import me.totalfreedom.command.annotation.Completion;
|
||||
import me.totalfreedom.command.annotation.Subcommand;
|
||||
import me.totalfreedom.provider.ContextProvider;
|
||||
import me.totalfreedom.utils.FreedomLogger;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.command.PluginIdentifiableCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class BukkitDelegator extends Command implements PluginIdentifiableCommand
|
||||
{
|
||||
private final JavaPlugin plugin;
|
||||
private final CommandBase command;
|
||||
private final boolean noConsole;
|
||||
|
||||
BukkitDelegator(final JavaPlugin plugin, final CommandBase command)
|
||||
{
|
||||
super(command.getInfo().name());
|
||||
this.command = command;
|
||||
this.plugin = command.getPlugin();
|
||||
this.setDescription(command.getInfo().description());
|
||||
this.setUsage(command.getInfo().usage());
|
||||
this.setPermission(command.getPerms().perm());
|
||||
this.setAliases(Arrays.asList(command.getInfo().aliases()));
|
||||
this.permissionMessage(Component.text(command.getPerms().noPerms()));
|
||||
this.noConsole = command.getPerms().onlyPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull final CommandSender sender,
|
||||
@NotNull final String commandLabel,
|
||||
@NotNull final String[] args)
|
||||
{
|
||||
if (commandLabel.isEmpty() || !commandLabel.equalsIgnoreCase(getName()))
|
||||
return false;
|
||||
|
||||
if (sender instanceof ConsoleCommandSender && noConsole)
|
||||
{
|
||||
sender.sendMessage(Component.text("This command can only be run by players."));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getPermission() != null && !sender.hasPermission(getPermission()))
|
||||
{
|
||||
Component permissionMessage = permissionMessage();
|
||||
if (permissionMessage == null)
|
||||
permissionMessage = Component.text("You do not have permission to use this command.");
|
||||
sender.sendMessage(permissionMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length > 0)
|
||||
{
|
||||
final ContextProvider provider = new ContextProvider();
|
||||
final Set<Subcommand> nodes = command.getSubcommands().keySet();
|
||||
for (final Subcommand node : nodes)
|
||||
{
|
||||
final Class<?>[] argTypes = node.args();
|
||||
if (argTypes.length != args.length)
|
||||
continue;
|
||||
|
||||
Object[] objects = new Object[0];
|
||||
|
||||
for (int i = 0; i < argTypes.length; i++)
|
||||
{
|
||||
final Class<?> argType = argTypes[i];
|
||||
final String arg = args[i];
|
||||
if (argType == String.class)
|
||||
continue;
|
||||
|
||||
final Context<?> context = () -> provider.fromString(arg);
|
||||
if (!argType.isInstance(context.get()))
|
||||
{
|
||||
throw new IllegalStateException(); // TODO: Change this.
|
||||
}
|
||||
objects = Arrays.copyOf(objects, objects.length + 1);
|
||||
objects[objects.length - 1] = context.get();
|
||||
}
|
||||
try
|
||||
{
|
||||
command.getSubcommands().get(node).invoke(command, objects);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
FreedomLogger.getLogger("Patchwork")
|
||||
.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (command.getBaseMethodPair() != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
command.getBaseMethodPair().value().invoke(command, sender);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
FreedomLogger.getLogger("Patchwork")
|
||||
.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(final CommandSender sender, final String alias, final String[] args)
|
||||
{
|
||||
final Set<Completion> completions = command.getCompletions();
|
||||
final List<String> results = new ArrayList<>();
|
||||
for (final Completion completion : completions)
|
||||
{
|
||||
if (completion.index() != args.length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (final String p : completion.args())
|
||||
{
|
||||
switch (p)
|
||||
{
|
||||
case "%player%" -> results.addAll(Bukkit.getOnlinePlayers()
|
||||
.stream()
|
||||
.map(Player::getName)
|
||||
.toList());
|
||||
case "%world%" -> results.addAll(Bukkit.getWorlds()
|
||||
.stream()
|
||||
.map(World::getName)
|
||||
.toList());
|
||||
case "%number%" -> results.addAll(List.of(
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9"));
|
||||
case "%location%" -> results.add("world,x,y,z");
|
||||
default -> results.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results.stream().filter(s -> s.startsWith(args[args.length - 1])).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Plugin getPlugin()
|
||||
{
|
||||
return this.plugin;
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
package me.totalfreedom.command;
|
||||
|
||||
import me.totalfreedom.command.annotation.*;
|
||||
import me.totalfreedom.utils.Pair;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class CommandBase
|
||||
{
|
||||
private final JavaPlugin plugin;
|
||||
private final Info info;
|
||||
private final Permissive perms;
|
||||
private final Map<Subcommand, Method> subcommands;
|
||||
private final Set<Completion> completions;
|
||||
private final Pair<Base, Method> baseMethodPair;
|
||||
|
||||
protected CommandBase(final JavaPlugin plugin)
|
||||
{
|
||||
this.info = this.getClass().getDeclaredAnnotation(Info.class);
|
||||
this.perms = this.getClass().getDeclaredAnnotation(Permissive.class);
|
||||
this.plugin = plugin;
|
||||
this.subcommands = new HashMap<>();
|
||||
this.completions = new HashSet<>();
|
||||
|
||||
if (this.getClass().isAnnotationPresent(Base.class))
|
||||
{
|
||||
final Method method = Stream.of(this.getClass().getDeclaredMethods())
|
||||
.filter(m -> m.isAnnotationPresent(Base.class))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Base annotation present but no method found."));
|
||||
|
||||
this.baseMethodPair = new Pair<>(method.getDeclaredAnnotation(Base.class), method);
|
||||
} else
|
||||
{
|
||||
this.baseMethodPair = null;
|
||||
}
|
||||
|
||||
registerAnnotations();
|
||||
}
|
||||
|
||||
private void registerAnnotations()
|
||||
{
|
||||
Stream.of(this.getClass().getDeclaredMethods())
|
||||
.filter(method -> method.isAnnotationPresent(Subcommand.class))
|
||||
.forEach(method -> this.subcommands.put(
|
||||
method.getDeclaredAnnotation(Subcommand.class),
|
||||
method));
|
||||
|
||||
List.of(this.getClass().getDeclaredAnnotationsByType(Completion.class))
|
||||
.stream()
|
||||
.forEach(completions::add);
|
||||
}
|
||||
|
||||
public Pair<Base, Method> getBaseMethodPair()
|
||||
{
|
||||
return baseMethodPair;
|
||||
}
|
||||
|
||||
Info getInfo()
|
||||
{
|
||||
return this.info;
|
||||
}
|
||||
|
||||
Permissive getPerms()
|
||||
{
|
||||
return this.perms;
|
||||
}
|
||||
|
||||
public JavaPlugin getPlugin()
|
||||
{
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
Map<Subcommand, Method> getSubcommands()
|
||||
{
|
||||
return this.subcommands;
|
||||
}
|
||||
|
||||
Set<Completion> getCompletions()
|
||||
{
|
||||
return this.completions;
|
||||
}
|
||||
}
|
@ -12,14 +12,11 @@ public class CommandHandler
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
// TODO: Figure out how to use CommandExecutor and TabCompleter.
|
||||
// We need to find a way to resolve PluginCommands so we can
|
||||
// set the executor and tab completer as necessary.
|
||||
// OR we need to find an alternative way to process tab completions.
|
||||
public <T extends CommandBase> void registerCommand(final T command)
|
||||
public <T extends Commander> void registerCommand(final T command)
|
||||
{
|
||||
final BukkitDelegator delegate = new BukkitDelegator(plugin, command);
|
||||
final BukkitDelegate delegate = new BukkitDelegate(command);
|
||||
|
||||
Bukkit.getCommandMap().register(plugin.getName(), delegate);
|
||||
Bukkit.getCommandMap()
|
||||
.register(plugin.getName(), delegate);
|
||||
}
|
||||
}
|
||||
|
108
Patchwork/src/main/java/me/totalfreedom/command/Commander.java
Normal file
108
Patchwork/src/main/java/me/totalfreedom/command/Commander.java
Normal file
@ -0,0 +1,108 @@
|
||||
package me.totalfreedom.command;
|
||||
|
||||
import me.totalfreedom.command.annotation.Base;
|
||||
import me.totalfreedom.command.annotation.Completion;
|
||||
import me.totalfreedom.command.annotation.Info;
|
||||
import me.totalfreedom.command.annotation.Permissive;
|
||||
import me.totalfreedom.command.annotation.Subcommand;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class Commander
|
||||
{
|
||||
private final JavaPlugin plugin;
|
||||
private final Info info;
|
||||
private final Permissive perms;
|
||||
private final Map<Subcommand, Method> subcommands;
|
||||
private final Set<Completion> completions;
|
||||
private final Method baseMethod;
|
||||
|
||||
protected Commander(final @NotNull JavaPlugin plugin)
|
||||
{
|
||||
this.info = this.getClass()
|
||||
.getDeclaredAnnotation(Info.class);
|
||||
this.perms = this.getClass()
|
||||
.getDeclaredAnnotation(Permissive.class);
|
||||
this.plugin = plugin;
|
||||
this.subcommands = new HashMap<>();
|
||||
this.completions = new HashSet<>();
|
||||
|
||||
if (this.getClass()
|
||||
.isAnnotationPresent(Base.class))
|
||||
{
|
||||
final Method method = Stream.of(this.getClass()
|
||||
.getDeclaredMethods())
|
||||
.filter(m -> m.isAnnotationPresent(Base.class))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException(
|
||||
"Base annotation present but no method found."));
|
||||
|
||||
this.baseMethod = method;
|
||||
} else
|
||||
{
|
||||
this.baseMethod = null;
|
||||
}
|
||||
|
||||
registerAnnotations();
|
||||
}
|
||||
|
||||
private void registerAnnotations()
|
||||
{
|
||||
Stream.of(this.getClass()
|
||||
.getDeclaredMethods())
|
||||
.filter(method -> method.isAnnotationPresent(Subcommand.class))
|
||||
.forEach(method -> this.subcommands.put(
|
||||
method.getDeclaredAnnotation(Subcommand.class),
|
||||
method));
|
||||
|
||||
List.of(this.getClass()
|
||||
.getDeclaredAnnotationsByType(Completion.class))
|
||||
.stream()
|
||||
.forEach(completions::add);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Method getBaseMethod()
|
||||
{
|
||||
return baseMethod;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Info getInfo()
|
||||
{
|
||||
return this.info;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Permissive getPerms()
|
||||
{
|
||||
return this.perms;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JavaPlugin getPlugin()
|
||||
{
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Map<Subcommand, Method> getSubcommands()
|
||||
{
|
||||
return this.subcommands;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Set<Completion> getCompletions()
|
||||
{
|
||||
return this.completions;
|
||||
}
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
package me.totalfreedom.command.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Target(ElementType.METHOD)
|
||||
@Repeatable(Completions.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Completion
|
||||
{
|
||||
|
@ -0,0 +1,13 @@
|
||||
package me.totalfreedom.command.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Completions
|
||||
{
|
||||
Completion[] value();
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
package me.totalfreedom.command.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Subcommand
|
||||
{
|
||||
|
@ -1,34 +0,0 @@
|
||||
package me.totalfreedom.data;
|
||||
|
||||
import me.totalfreedom.security.ban.Ban;
|
||||
import me.totalfreedom.security.ban.BanID;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BanRegistry
|
||||
{
|
||||
private final List<Ban> bansList = new ArrayList<>();
|
||||
|
||||
public boolean addBan(final Ban ban) {
|
||||
return bansList.add(ban);
|
||||
}
|
||||
|
||||
public boolean removeBan(final Ban ban) {
|
||||
return bansList.remove(ban);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Ban getBan(final BanID banID)
|
||||
{
|
||||
for (final Ban ban : bansList)
|
||||
{
|
||||
if (ban.getBanID().matches(banID))
|
||||
{
|
||||
return ban;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -15,26 +15,32 @@ public class GroupRegistry
|
||||
this.groups = new ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean registerGroup(final Group group) {
|
||||
public boolean registerGroup(final Group group)
|
||||
{
|
||||
return groups.add(group);
|
||||
}
|
||||
|
||||
public boolean unregisterGroup(final Group group) {
|
||||
public boolean unregisterGroup(final Group group)
|
||||
{
|
||||
return groups.remove(group);
|
||||
}
|
||||
|
||||
public Group getGroup(final String name) {
|
||||
public Group getGroup(final String name)
|
||||
{
|
||||
final PlainTextComponentSerializer s = PlainTextComponentSerializer.plainText();
|
||||
for (final Group group : groups) {
|
||||
for (final Group group : groups)
|
||||
{
|
||||
final String n = s.serialize(group.getName());
|
||||
if (n.equalsIgnoreCase(name)) {
|
||||
if (n.equalsIgnoreCase(name))
|
||||
{
|
||||
return group;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Group> getGroups() {
|
||||
public List<Group> getGroups()
|
||||
{
|
||||
return groups;
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ public class ModuleRegistry
|
||||
this.plugins.add(plugin);
|
||||
}
|
||||
|
||||
public void removeModule(final JavaPlugin plugin) {
|
||||
public void removeModule(final JavaPlugin plugin)
|
||||
{
|
||||
this.plugins.remove(plugin);
|
||||
}
|
||||
|
||||
|
@ -42,29 +42,34 @@ public class ServiceRegistry
|
||||
public <T extends Service> void register(final Plugin plugin, final T service)
|
||||
{
|
||||
this.services.add(service);
|
||||
if (!service.getClass().isInstance(service))
|
||||
if (!service.getClass()
|
||||
.isInstance(service))
|
||||
{
|
||||
throw new UnknownError("""
|
||||
A critical issue has been encountered:
|
||||
The service %s is not an instance of itself.
|
||||
This is a critical issue and should be reported immediately.
|
||||
""".formatted(service.getClass().getName()));
|
||||
A critical issue has been encountered:
|
||||
The service %s is not an instance of itself.
|
||||
This is a critical issue and should be reported immediately.
|
||||
""".formatted(service.getClass()
|
||||
.getName()));
|
||||
}
|
||||
Bukkit.getServicesManager().register(
|
||||
(Class<T>) service.getClass(),
|
||||
service,
|
||||
plugin,
|
||||
ServicePriority.Normal);
|
||||
Bukkit.getServicesManager()
|
||||
.register(
|
||||
(Class<T>) service.getClass(),
|
||||
service,
|
||||
plugin,
|
||||
ServicePriority.Normal);
|
||||
}
|
||||
|
||||
public <T extends Service> RegisteredServiceProvider<T> getService(final Class<T> clazz)
|
||||
{
|
||||
return Bukkit.getServicesManager().getRegistration(clazz);
|
||||
return Bukkit.getServicesManager()
|
||||
.getRegistration(clazz);
|
||||
}
|
||||
|
||||
public void unregister(final Class<? extends Service> clazz, final Service service)
|
||||
{
|
||||
this.services.remove(service);
|
||||
Bukkit.getServicesManager().unregister(clazz, service);
|
||||
Bukkit.getServicesManager()
|
||||
.unregister(clazz, service);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,121 @@
|
||||
package me.totalfreedom.display;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class AbstractMenu
|
||||
{
|
||||
private static final Map<UUID, AbstractMenu> invByUUID = new HashMap<>();
|
||||
private static final Map<UUID, UUID> openInvs = new HashMap<>();
|
||||
private final Map<Integer, ClickAction> actionMap;
|
||||
private final Displayable displayable;
|
||||
private final UUID displayableUUID;
|
||||
|
||||
protected AbstractMenu(final int size)
|
||||
{
|
||||
actionMap = new HashMap<>();
|
||||
this.displayable = new Displayable(size);
|
||||
this.displayableUUID = UUID.randomUUID();
|
||||
|
||||
invByUUID.put(getDisplayableUUID(), this);
|
||||
}
|
||||
|
||||
public UUID getDisplayableUUID()
|
||||
{
|
||||
return displayableUUID;
|
||||
}
|
||||
|
||||
public static Map<UUID, AbstractMenu> getInvByUUID()
|
||||
{
|
||||
return invByUUID;
|
||||
}
|
||||
|
||||
public static Map<UUID, UUID> getOpenInvs()
|
||||
{
|
||||
return openInvs;
|
||||
}
|
||||
|
||||
public void setItem(final int slot, final @NotNull ItemStack stack)
|
||||
{
|
||||
setItem(slot, stack, null);
|
||||
}
|
||||
|
||||
public void setItem(final int slot, final @NotNull ItemStack stack, final @Nullable ClickAction action)
|
||||
{
|
||||
getDisplayable().setItem(slot, stack);
|
||||
if (action != null)
|
||||
{
|
||||
actionMap.put(slot, action);
|
||||
}
|
||||
}
|
||||
|
||||
public Displayable getDisplayable()
|
||||
{
|
||||
return displayable;
|
||||
}
|
||||
|
||||
public void open(final @NotNull Player player)
|
||||
{
|
||||
player.openInventory(getDisplayable());
|
||||
openInvs.put(player.getUniqueId(), getDisplayableUUID());
|
||||
}
|
||||
|
||||
public void delete()
|
||||
{
|
||||
Bukkit.getOnlinePlayers()
|
||||
.forEach(player ->
|
||||
{
|
||||
if (openInvs.get(player.getUniqueId())
|
||||
.equals(getDisplayableUUID()))
|
||||
{
|
||||
close(player);
|
||||
}
|
||||
});
|
||||
|
||||
invByUUID.remove(getDisplayableUUID());
|
||||
}
|
||||
|
||||
public void close(final @NotNull Player player)
|
||||
{
|
||||
player.closeInventory();
|
||||
openInvs.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
public Map<Integer, ClickAction> getActions()
|
||||
{
|
||||
return actionMap;
|
||||
}
|
||||
|
||||
public ItemStack newItem(final @NotNull Material material, final @NotNull Component name)
|
||||
{
|
||||
return this.newItem(material, name, new Component[0]);
|
||||
}
|
||||
|
||||
public ItemStack newItem(final @NotNull Material material, final @NotNull Component name,
|
||||
final @NotNull Component... lore)
|
||||
{
|
||||
final ItemStack item = new ItemStack(material, 1);
|
||||
final ItemMeta meta = item.getItemMeta();
|
||||
if (meta == null)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
meta.displayName(name);
|
||||
final List<Component> metaLore = Arrays.asList(lore);
|
||||
meta.lore(metaLore);
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package me.totalfreedom.display;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ClickAction
|
||||
{
|
||||
void onClick(final Player player);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package me.totalfreedom.display;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
@ -14,11 +15,11 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
public abstract class Displayable implements Inventory, InventoryHolder
|
||||
public final class Displayable implements Inventory, InventoryHolder
|
||||
{
|
||||
|
||||
private final int size;
|
||||
private final ItemStack[] contents;
|
||||
private ItemStack[] contents;
|
||||
|
||||
protected Displayable(final int size)
|
||||
{
|
||||
@ -27,9 +28,9 @@ public abstract class Displayable implements Inventory, InventoryHolder
|
||||
throw new IllegalArgumentException("Invalid size for Displayable inventory");
|
||||
}
|
||||
|
||||
this.size = (size % 9 == 0)
|
||||
? size
|
||||
: size + (9 - size % 9);
|
||||
// If the size is not a multiple of nine, find the difference to the next highest multiple of 9 and make up
|
||||
// the difference.
|
||||
this.size = (size % 9 == 0) ? size : size + (9 - size % 9);
|
||||
|
||||
this.contents = new ItemStack[size];
|
||||
}
|
||||
@ -78,7 +79,8 @@ public abstract class Displayable implements Inventory, InventoryHolder
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> addItem(final @NotNull ItemStack... items) throws IllegalArgumentException
|
||||
public @NotNull HashMap<Integer, ItemStack> addItem(final @NotNull ItemStack... items)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
final HashMap<Integer, ItemStack> remainingItems = new HashMap<>();
|
||||
|
||||
@ -116,7 +118,8 @@ public abstract class Displayable implements Inventory, InventoryHolder
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> removeItem(final @NotNull ItemStack... items) throws IllegalArgumentException
|
||||
public @NotNull HashMap<Integer, ItemStack> removeItem(final @NotNull ItemStack... items)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
final HashMap<Integer, ItemStack> removedItems = new HashMap<>();
|
||||
|
||||
@ -148,13 +151,21 @@ public abstract class Displayable implements Inventory, InventoryHolder
|
||||
|
||||
if (remainingAmount < item.getAmount())
|
||||
{
|
||||
removedItems.put(removedItems.size(), new ItemStack(item.getType(), item.getAmount() - remainingAmount));
|
||||
removedItems.put(removedItems.size(),
|
||||
new ItemStack(item.getType(), item.getAmount() - remainingAmount));
|
||||
}
|
||||
}
|
||||
|
||||
return removedItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> removeItemAnySlot(final @NotNull ItemStack... items)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
return removeItem(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ItemStack @NotNull [] getContents()
|
||||
{
|
||||
@ -176,39 +187,15 @@ public abstract class Displayable implements Inventory, InventoryHolder
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ListIterator<ItemStack> iterator()
|
||||
public @Nullable ItemStack @NotNull [] getStorageContents()
|
||||
{
|
||||
return iterator(0);
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ListIterator<ItemStack> iterator(final int index)
|
||||
public void setStorageContents(final @Nullable ItemStack @NotNull [] items) throws IllegalArgumentException
|
||||
{
|
||||
return List.of(contents).listIterator(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InventoryType getType()
|
||||
{
|
||||
return InventoryType.CHEST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InventoryHolder getHolder()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InventoryHolder getHolder(final boolean useSnapshot)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<HumanEntity> getViewers()
|
||||
{
|
||||
return new ArrayList<>();
|
||||
this.contents = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -272,7 +259,7 @@ public abstract class Displayable implements Inventory, InventoryHolder
|
||||
if (content != null && content.isSimilar(item))
|
||||
{
|
||||
totalAmount += content.getAmount();
|
||||
if (totalAmount >= amount)
|
||||
if (totalAmount == amount)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -304,7 +291,8 @@ public abstract class Displayable implements Inventory, InventoryHolder
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ? extends ItemStack> all(final @NotNull Material material) throws IllegalArgumentException
|
||||
public @NotNull HashMap<Integer, ? extends ItemStack> all(final @NotNull Material material)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
final HashMap<Integer, ItemStack> matchingItems = new HashMap<>();
|
||||
for (int i = 0; i < size; i++)
|
||||
@ -439,4 +427,53 @@ public abstract class Displayable implements Inventory, InventoryHolder
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<HumanEntity> getViewers()
|
||||
{
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InventoryType getType()
|
||||
{
|
||||
return InventoryType.CHEST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InventoryHolder getHolder()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InventoryHolder getHolder(final boolean useSnapshot)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ListIterator<ItemStack> iterator()
|
||||
{
|
||||
return iterator(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ListIterator<ItemStack> iterator(final int index)
|
||||
{
|
||||
return List.of(contents)
|
||||
.listIterator(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Location getLocation()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getInventory()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,8 @@ public class DisplayableView extends InventoryView
|
||||
private final InventoryType type;
|
||||
private String title;
|
||||
|
||||
public DisplayableView(final Player player, final Displayable top, final Displayable bottom) {
|
||||
public DisplayableView(final Player player, final Displayable top, final Displayable bottom)
|
||||
{
|
||||
this.player = player;
|
||||
this.top = top;
|
||||
this.bottom = bottom;
|
||||
|
@ -6,9 +6,9 @@ public interface EconomicEntityData
|
||||
|
||||
long getBalance();
|
||||
|
||||
void setBalance(final long newBalance);
|
||||
|
||||
long addToBalance(final long amount);
|
||||
|
||||
long removeFromBalance(final long amount);
|
||||
|
||||
void setBalance(final long newBalance);
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
package me.totalfreedom.economy;
|
||||
|
||||
/**
|
||||
* Please ensure that all modifications of {@link MutableTransaction} happen BEFORE it is passed to a {@link Transactor} implementation
|
||||
* Please ensure that all modifications of {@link MutableTransaction} happen BEFORE it is passed to a
|
||||
* {@link Transactor} implementation
|
||||
*/
|
||||
public interface MutableTransaction extends Transaction
|
||||
{
|
||||
|
@ -27,9 +27,10 @@ public class EventBus extends Service
|
||||
public <T extends FEvent> T getEvent(final Class<T> eventClass)
|
||||
{
|
||||
final FEvent e = eventSet.stream()
|
||||
.filter(event -> event.getEventClass().equals(eventClass))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
.filter(event -> event.getEventClass()
|
||||
.equals(eventClass))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
return eventClass.cast(e);
|
||||
}
|
||||
@ -37,10 +38,11 @@ public class EventBus extends Service
|
||||
public <T extends FEvent> EventSubscription<T> subscribe(final Class<T> eventClass, final Callback<T> callback)
|
||||
{
|
||||
final Context<T> eventContext = () -> eventSet.stream()
|
||||
.filter(event -> event.getEventClass().equals(eventClass))
|
||||
.findFirst()
|
||||
.map(eventClass::cast)
|
||||
.orElse(null);
|
||||
.filter(event -> event.getEventClass()
|
||||
.equals(eventClass))
|
||||
.findFirst()
|
||||
.map(eventClass::cast)
|
||||
.orElse(null);
|
||||
|
||||
if (eventContext.get() == null)
|
||||
{
|
||||
|
@ -7,24 +7,32 @@ class SubscriptionBox<T extends FEvent>
|
||||
{
|
||||
private final List<EventSubscription<T>> subscriptions;
|
||||
|
||||
public SubscriptionBox() {
|
||||
public SubscriptionBox()
|
||||
{
|
||||
this.subscriptions = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addSubscription(final EventSubscription<T> subscription) {
|
||||
public void addSubscription(final EventSubscription<T> subscription)
|
||||
{
|
||||
subscriptions.add(subscription);
|
||||
}
|
||||
|
||||
public void removeSubscription(final EventSubscription<?> subscription) {
|
||||
public void removeSubscription(final EventSubscription<?> subscription)
|
||||
{
|
||||
subscriptions.remove(subscription);
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
subscriptions.forEach(s -> {
|
||||
if (!s.event().shouldCall()) return;
|
||||
public void tick()
|
||||
{
|
||||
subscriptions.forEach(s ->
|
||||
{
|
||||
if (!s.event()
|
||||
.shouldCall()) return;
|
||||
|
||||
s.callback().call(s.event());
|
||||
s.event().reset();
|
||||
});
|
||||
s.callback()
|
||||
.call(s.event());
|
||||
s.event()
|
||||
.reset();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,31 @@
|
||||
package me.totalfreedom.particle;
|
||||
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Trail
|
||||
{
|
||||
@NotNull
|
||||
UUID getAssocPlayerUUID();
|
||||
|
||||
// Nullable because the player may not be online and trail selections should be persistent whether they are
|
||||
// active or not.
|
||||
@Nullable
|
||||
Player getAssocPlayer();
|
||||
|
||||
@NotNull
|
||||
TrailType getTrailType();
|
||||
|
||||
@Nullable Color getColor();
|
||||
@NotNull
|
||||
Color getColor();
|
||||
|
||||
void setColor(@NotNull Color color);
|
||||
|
||||
boolean isActive();
|
||||
|
||||
void setActive(boolean active);
|
||||
}
|
||||
|
@ -14,21 +14,22 @@ import java.util.stream.Stream;
|
||||
|
||||
public class ContextProvider
|
||||
{
|
||||
public Object fromString(final String string)
|
||||
public <T> T fromString(final String string, final Class<T> clazz)
|
||||
{
|
||||
return Stream.of(toBoolean(string),
|
||||
toDouble(string),
|
||||
toInt(string),
|
||||
toLong(string),
|
||||
toFloat(string),
|
||||
toPlayer(string),
|
||||
toWorld(string),
|
||||
toLocation(string),
|
||||
toCommandSender(string),
|
||||
toComponent(string))
|
||||
.filter(Objects::nonNull)
|
||||
.findFirst()
|
||||
.orElse(string);
|
||||
toDouble(string),
|
||||
toInt(string),
|
||||
toLong(string),
|
||||
toFloat(string),
|
||||
toPlayer(string),
|
||||
toWorld(string),
|
||||
toLocation(string),
|
||||
toCommandSender(string),
|
||||
toComponent(string))
|
||||
.filter(Objects::nonNull)
|
||||
.findFirst()
|
||||
.map(clazz::cast)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private @Nullable Boolean toBoolean(final String string)
|
||||
@ -36,7 +37,8 @@ public class ContextProvider
|
||||
try
|
||||
{
|
||||
return Boolean.parseBoolean(string);
|
||||
} catch (Exception e)
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -47,7 +49,8 @@ public class ContextProvider
|
||||
try
|
||||
{
|
||||
return Double.parseDouble(string);
|
||||
} catch (Exception e)
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -58,7 +61,8 @@ public class ContextProvider
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(string);
|
||||
} catch (Exception e)
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -69,7 +73,8 @@ public class ContextProvider
|
||||
try
|
||||
{
|
||||
return Long.parseLong(string);
|
||||
} catch (Exception e)
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -80,7 +85,8 @@ public class ContextProvider
|
||||
try
|
||||
{
|
||||
return Float.parseFloat(string);
|
||||
} catch (Exception e)
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -91,20 +97,11 @@ public class ContextProvider
|
||||
return Bukkit.getPlayer(string);
|
||||
}
|
||||
|
||||
private @Nullable CommandSender toCommandSender(final String string)
|
||||
{
|
||||
if (toPlayer(string) == null) return null;
|
||||
|
||||
return toPlayer(string);
|
||||
}
|
||||
|
||||
private @Nullable World toWorld(final String string)
|
||||
{
|
||||
return Bukkit.getWorld(string);
|
||||
}
|
||||
|
||||
// If we decide to, we can "modify" this to use spaces
|
||||
// and adjust our inputs accordingly.
|
||||
/**
|
||||
* When using this method, the input string must be formatted as
|
||||
* <br>
|
||||
@ -127,6 +124,13 @@ public class ContextProvider
|
||||
return new Location(toWorld(split[0]), x, y, z);
|
||||
}
|
||||
|
||||
private @Nullable CommandSender toCommandSender(final String string)
|
||||
{
|
||||
if (toPlayer(string) == null) return null;
|
||||
|
||||
return toPlayer(string);
|
||||
}
|
||||
|
||||
private @NotNull Component toComponent(final String string)
|
||||
{
|
||||
return Component.text(string);
|
||||
|
@ -3,10 +3,10 @@ package me.totalfreedom.security.ban;
|
||||
/**
|
||||
* Represents an ID for a ban. These are formatted either as:
|
||||
* <p>
|
||||
* P-00129381
|
||||
* <br>
|
||||
* T-00128381
|
||||
* <br>
|
||||
* P-00129381
|
||||
* <br>
|
||||
* T-00128381
|
||||
* <br>
|
||||
* </p>
|
||||
* Where P marks a ban as permanent, and T marks a ban as temporary.
|
||||
*/
|
||||
@ -19,6 +19,23 @@ public interface BanID
|
||||
*/
|
||||
String getID();
|
||||
|
||||
/**
|
||||
* Checks the prefix of the Ban ID to see whether if it is permanent.
|
||||
*
|
||||
* @return true if the Ban ID is prefixed with a P, false otherwise.
|
||||
*/
|
||||
boolean isPermanent();
|
||||
|
||||
default boolean matches(BanID other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (getIDPrefix() == other.getIDPrefix())
|
||||
&& (getNumericalTag() == other.getNumericalTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the ban type denominator character for the Ban ID.
|
||||
* This would either be T or P, where T = temporary and P = permanent.
|
||||
@ -34,19 +51,4 @@ public interface BanID
|
||||
* @return The numerical tag of this ban ID.
|
||||
*/
|
||||
int getNumericalTag();
|
||||
|
||||
/**
|
||||
* Checks the prefix of the Ban ID to see whether if it is permanent.
|
||||
*
|
||||
* @return true if the Ban ID is prefixed with a P, false otherwise.
|
||||
*/
|
||||
boolean isPermanent();
|
||||
|
||||
default boolean matches(BanID other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
return (getIDPrefix() == other.getIDPrefix())
|
||||
&& (getNumericalTag() == other.getNumericalTag());
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,7 @@ public interface Node
|
||||
|
||||
boolean isExpired();
|
||||
|
||||
boolean isPermanent();
|
||||
|
||||
boolean isTemporary();
|
||||
|
||||
boolean wildcard();
|
||||
|
||||
boolean negated();
|
||||
}
|
||||
|
@ -13,38 +13,30 @@ public class FreedomExecutor
|
||||
|
||||
public FreedomExecutor()
|
||||
{
|
||||
syncExecutor = r -> Bukkit.getScheduler().runTask(CommonsBase.getInstance(), r);
|
||||
asyncExecutor = r -> Bukkit.getScheduler().runTaskAsynchronously(CommonsBase.getInstance(), r);
|
||||
}
|
||||
|
||||
public Executor getSync()
|
||||
{
|
||||
return syncExecutor;
|
||||
}
|
||||
|
||||
public Executor getAsync()
|
||||
{
|
||||
return asyncExecutor;
|
||||
syncExecutor = r -> Bukkit.getScheduler()
|
||||
.runTask(CommonsBase.getInstance(), r);
|
||||
asyncExecutor = r -> Bukkit.getScheduler()
|
||||
.runTaskAsynchronously(CommonsBase.getInstance(), r);
|
||||
}
|
||||
|
||||
public Executor scheduled(final long delay, final long period)
|
||||
{
|
||||
return r -> Bukkit.getScheduler()
|
||||
.runTaskTimer(
|
||||
CommonsBase.getInstance(),
|
||||
r,
|
||||
delay,
|
||||
period);
|
||||
.runTaskTimer(
|
||||
CommonsBase.getInstance(),
|
||||
r,
|
||||
delay,
|
||||
period);
|
||||
}
|
||||
|
||||
public Executor scheduledAsync(final long delay, final long period)
|
||||
{
|
||||
return r -> Bukkit.getScheduler()
|
||||
.runTaskTimerAsynchronously(
|
||||
CommonsBase.getInstance(),
|
||||
r,
|
||||
delay,
|
||||
period);
|
||||
.runTaskTimerAsynchronously(
|
||||
CommonsBase.getInstance(),
|
||||
r,
|
||||
delay,
|
||||
period);
|
||||
}
|
||||
|
||||
public void runSync(@NotNull final Task task)
|
||||
@ -52,8 +44,18 @@ public class FreedomExecutor
|
||||
getSync().execute(task);
|
||||
}
|
||||
|
||||
public Executor getSync()
|
||||
{
|
||||
return syncExecutor;
|
||||
}
|
||||
|
||||
public void runAsync(@NotNull final Task task)
|
||||
{
|
||||
getAsync().execute(task);
|
||||
}
|
||||
|
||||
public Executor getAsync()
|
||||
{
|
||||
return asyncExecutor;
|
||||
}
|
||||
}
|
||||
|
@ -17,24 +17,24 @@ public abstract class Service
|
||||
{
|
||||
isActive = true;
|
||||
CommonsBase.getInstance()
|
||||
.getExecutor()
|
||||
.getSync()
|
||||
.execute(() ->
|
||||
{
|
||||
while (isActive)
|
||||
{
|
||||
tick();
|
||||
}
|
||||
});
|
||||
.getExecutor()
|
||||
.getSync()
|
||||
.execute(() ->
|
||||
{
|
||||
while (isActive)
|
||||
{
|
||||
tick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public abstract void tick();
|
||||
|
||||
public void stop()
|
||||
{
|
||||
isActive = false;
|
||||
}
|
||||
|
||||
public abstract void tick();
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
|
@ -1,14 +1,11 @@
|
||||
package me.totalfreedom.sql;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface SQL
|
||||
{
|
||||
CompletableFuture<Connection> getConnection(final String url);
|
||||
|
||||
CompletableFuture<PreparedStatement> prepareStatement(final String query, final Object... args);
|
||||
|
||||
CompletableFuture<ResultSet> executeQuery(final String query, final Object... args);
|
||||
|
@ -19,6 +19,15 @@ public interface SQLProperties
|
||||
return properties;
|
||||
}
|
||||
|
||||
default String toURLPlain()
|
||||
{
|
||||
return String.format("jdbc:%s://%s:%s/%s",
|
||||
this.getDriver(),
|
||||
this.getHost(),
|
||||
this.getPort(),
|
||||
this.getDatabase());
|
||||
}
|
||||
|
||||
String getDriver();
|
||||
|
||||
String getHost();
|
||||
@ -27,27 +36,18 @@ public interface SQLProperties
|
||||
|
||||
String getDatabase();
|
||||
|
||||
String getUsername();
|
||||
|
||||
String getPassword();
|
||||
|
||||
default String toURLPlain()
|
||||
{
|
||||
return String.format("jdbc:%s://%s:%s/%s",
|
||||
this.getDriver(),
|
||||
this.getHost(),
|
||||
this.getPort(),
|
||||
this.getDatabase());
|
||||
}
|
||||
|
||||
default String toURLWithLogin()
|
||||
{
|
||||
return String.format("jdbc:%s://%s:%s/%s?user=%s&password=%s",
|
||||
this.getDriver(),
|
||||
this.getHost(),
|
||||
this.getPort(),
|
||||
this.getDatabase(),
|
||||
this.getUsername(),
|
||||
this.getPassword());
|
||||
this.getDriver(),
|
||||
this.getHost(),
|
||||
this.getPort(),
|
||||
this.getDatabase(),
|
||||
this.getUsername(),
|
||||
this.getPassword());
|
||||
}
|
||||
|
||||
String getUsername();
|
||||
|
||||
String getPassword();
|
||||
}
|
||||
|
@ -1,12 +1,18 @@
|
||||
package me.totalfreedom.user;
|
||||
|
||||
import me.totalfreedom.security.perm.PermissionHolder;
|
||||
import me.totalfreedom.economy.EconomicEntity;
|
||||
import me.totalfreedom.economy.EconomicEntityData;
|
||||
import me.totalfreedom.security.perm.PermissionHolder;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public interface User extends PermissionHolder, EconomicEntity
|
||||
{
|
||||
@Override
|
||||
default EconomicEntityData getEconomicData()
|
||||
{
|
||||
return getUserData();
|
||||
}
|
||||
|
||||
// Implement a few EconomicEntity methods in the User interface
|
||||
@Override
|
||||
default String getName()
|
||||
@ -14,12 +20,6 @@ public interface User extends PermissionHolder, EconomicEntity
|
||||
return getUserData().getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
default EconomicEntityData getEconomicData()
|
||||
{
|
||||
return getUserData();
|
||||
}
|
||||
|
||||
UserData getUserData();
|
||||
|
||||
Component getDisplayName();
|
||||
|
@ -1,7 +1,7 @@
|
||||
package me.totalfreedom.user;
|
||||
|
||||
import me.totalfreedom.security.perm.Group;
|
||||
import me.totalfreedom.economy.EconomicEntityData;
|
||||
import me.totalfreedom.security.perm.Group;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -6,27 +6,29 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* This class contains the only reference to plain text component serializer, and allows access to it via wrapper functions.
|
||||
* This class contains the only reference to plain text component serializer, and allows access to it via wrapper
|
||||
* functions.
|
||||
*/
|
||||
public class FreedomAdventure
|
||||
{
|
||||
private static final PlainTextComponentSerializer PLAIN_TEXT_COMPONENT_SERIALIZER =
|
||||
PlainTextComponentSerializer.plainText();
|
||||
|
||||
private FreedomAdventure()
|
||||
{
|
||||
throw new UnsupportedOperationException("Instantiation of a static utility class is not supported.");
|
||||
}
|
||||
|
||||
private static final PlainTextComponentSerializer PLAIN_TEXT_COMPONENT_SERIALIZER = PlainTextComponentSerializer.plainText();
|
||||
public static String toPlainText(final Supplier<Component> supplier)
|
||||
{
|
||||
return toPlainText(supplier.get());
|
||||
}
|
||||
|
||||
public static String toPlainText(final Component component)
|
||||
{
|
||||
return PLAIN_TEXT_COMPONENT_SERIALIZER.serialize(component);
|
||||
}
|
||||
|
||||
public static String toPlainText(final Supplier<Component> supplier)
|
||||
{
|
||||
return toPlainText(supplier.get());
|
||||
}
|
||||
|
||||
public static Supplier<String> supplyPlainText(final Supplier<Component> supplier)
|
||||
{
|
||||
return new StringRepresentationSupplier(supplier.get());
|
||||
|
@ -31,30 +31,6 @@ public class FreedomLogger implements Audience
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log a message to the console.
|
||||
*
|
||||
* @param message The message to send.
|
||||
*/
|
||||
public void info(final String message)
|
||||
{
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log a component to the console.
|
||||
*
|
||||
* @param component The component to send.
|
||||
* @return A plain text representation of the message
|
||||
*/
|
||||
public String infoComponent(final Component component)
|
||||
{
|
||||
final String plainText = FreedomAdventure.toPlainText(component);
|
||||
|
||||
logger.info(plainText);
|
||||
return plainText;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log a message to the console,
|
||||
* while also returning a Component that could be used to
|
||||
@ -80,6 +56,28 @@ public class FreedomLogger implements Audience
|
||||
public String infoComponent(final Supplier<Component> component)
|
||||
{
|
||||
return this.infoComponent(component.get());
|
||||
} /**
|
||||
* This method allows you to log a message to the console.
|
||||
*
|
||||
* @param message The message to send.
|
||||
*/
|
||||
public void info(final String message)
|
||||
{
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log a component to the console.
|
||||
*
|
||||
* @param component The component to send.
|
||||
* @return A plain text representation of the message
|
||||
*/
|
||||
public String infoComponent(final Component component)
|
||||
{
|
||||
final String plainText = FreedomAdventure.toPlainText(component);
|
||||
|
||||
logger.info(plainText);
|
||||
return plainText;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,20 +114,6 @@ public class FreedomLogger implements Audience
|
||||
logger.error(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method logs an error component to the console.
|
||||
*
|
||||
* @param component The message to send.
|
||||
*/
|
||||
public String errorComponent(final Component component)
|
||||
{
|
||||
final String plainText = FreedomAdventure.toPlainText(component);
|
||||
|
||||
logger.error(plainText);
|
||||
|
||||
return plainText;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log an exception directly to the console.
|
||||
*
|
||||
@ -170,28 +154,15 @@ public class FreedomLogger implements Audience
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log a debug message to the console.
|
||||
* This method will only log if debug mode is enabled.
|
||||
* This method logs an error component to the console.
|
||||
*
|
||||
* @param message The message to send.
|
||||
* @param component The message to send.
|
||||
*/
|
||||
public void debug(final String message)
|
||||
{
|
||||
if (debug)
|
||||
logger.debug(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log a debug component to the console.
|
||||
* This method will only log if debug mode is enabled.
|
||||
*
|
||||
* @param component The component to send.
|
||||
*/
|
||||
public String debugComponent(final Component component)
|
||||
public String errorComponent(final Component component)
|
||||
{
|
||||
final String plainText = FreedomAdventure.toPlainText(component);
|
||||
|
||||
this.debug(plainText);
|
||||
logger.error(plainText);
|
||||
|
||||
return plainText;
|
||||
}
|
||||
@ -231,6 +202,35 @@ public class FreedomLogger implements Audience
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log a debug component to the console.
|
||||
* This method will only log if debug mode is enabled.
|
||||
*
|
||||
* @param component The component to send.
|
||||
*/
|
||||
public String debugComponent(final Component component)
|
||||
{
|
||||
final String plainText = FreedomAdventure.toPlainText(component);
|
||||
|
||||
this.debug(plainText);
|
||||
|
||||
return plainText;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows you to log a debug message to the console.
|
||||
* This method will only log if debug mode is enabled.
|
||||
*
|
||||
* @param message The message to send.
|
||||
*/
|
||||
public void debug(final String message)
|
||||
{
|
||||
if (debug)
|
||||
logger.debug(message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull final ComponentLike message)
|
||||
@ -267,6 +267,9 @@ public class FreedomLogger implements Audience
|
||||
@Override
|
||||
public void sendMessage(@NotNull final SignedMessage signedMessage, final ChatType.@NotNull Bound boundChatType)
|
||||
{
|
||||
this.info(signedMessage.message()); // TODO: We might want to investigate whether this logs the ENTIRE message, including unsigned & signed content, or only the signed part. This method was written in the assumption that it provided all content.
|
||||
this.info(
|
||||
signedMessage.message()); // TODO: We might want to investigate whether this logs the ENTIRE message,
|
||||
// including unsigned & signed content, or only the signed part. This method was written in the assumption
|
||||
// that it provided all content.
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,8 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
/**
|
||||
* This class contains different methods to provide {@link ChatType.Bound} instances for sending messages to players in game.
|
||||
* This class contains different methods to provide {@link ChatType.Bound} instances for sending messages to players
|
||||
* in game.
|
||||
* This is now a requirement for all message requests to players due to the new chat signature system.
|
||||
* <br>
|
||||
* Even though Scissors has this feature disabled, upstream (Paper) and Kyori Adventure
|
||||
@ -30,13 +31,6 @@ public final class KyoriConstants
|
||||
{
|
||||
}
|
||||
|
||||
public static ChatType.Bound fromPlugin(final JavaPlugin plugin)
|
||||
{
|
||||
final String name = plugin.getName();
|
||||
final Component component = Component.text(name, NamedTextColor.GOLD);
|
||||
return type.bind(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a Chat Bound for a plugin.
|
||||
* <br>
|
||||
@ -53,6 +47,13 @@ public final class KyoriConstants
|
||||
return fromPlugin(plugin);
|
||||
}
|
||||
|
||||
public static ChatType.Bound fromPlugin(final JavaPlugin plugin)
|
||||
{
|
||||
final String name = plugin.getName();
|
||||
final Component component = Component.text(name, NamedTextColor.GOLD);
|
||||
return type.bind(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a Chat Bound for a player.
|
||||
* Chat bounds are required for sending messages to players.
|
||||
@ -73,6 +74,7 @@ public final class KyoriConstants
|
||||
* <br>
|
||||
* The chat bound is a representation of a validated chat signature,
|
||||
* which is tied directly to the user's account name. In our case, this is the player's name.
|
||||
*
|
||||
* @param sender The console to get the bound for.
|
||||
* @return A ChatType.Bound instance for the console.
|
||||
*/
|
||||
|
@ -20,7 +20,8 @@ public class Shaper
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public List<Location> generate(final int count, final DoubleUnaryOperator x, final DoubleUnaryOperator y, final DoubleUnaryOperator z)
|
||||
public List<Location> generate(final int count, final DoubleUnaryOperator x, final DoubleUnaryOperator y,
|
||||
final DoubleUnaryOperator z)
|
||||
{
|
||||
final double step = (start - end) / (count - 1);
|
||||
final LinkedList<Location> lset = new LinkedList<>();
|
||||
|
Reference in New Issue
Block a user