Begin work on the Plex API

This commit is contained in:
2026-05-19 12:32:56 -04:00
parent 64c691bb58
commit 9fa8d82217
142 changed files with 1960 additions and 566 deletions
+1
View File
@@ -47,6 +47,7 @@ publishing {
}
dependencies {
implementation(project(":api"))
compileOnly("org.projectlombok:lombok:1.18.46")
annotationProcessor("org.projectlombok:lombok:1.18.46")
compileOnly("org.json:json:20251224")
+5
View File
@@ -6,6 +6,8 @@ import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import dev.plex.api.PlexApi;
import dev.plex.api.impl.DefaultPlexApi;
import dev.plex.config.TomlConfig;
import dev.plex.handlers.ListenerHandler;
import dev.plex.settings.ServerSettings;
@@ -35,6 +37,7 @@ import lombok.Getter;
@Getter
public class Plex
{
public static final int MODULE_API_COMPATIBILITY_VERSION = 1;
private static Plex plugin;
public final ProxyServer server;
@@ -42,6 +45,7 @@ public class Plex
private final File dataFolder;
private TomlConfig config;
private PlexApi api;
@Inject
public Plex(ProxyServer server, Logger logger, @DataDirectory Path folder)
@@ -71,6 +75,7 @@ public class Plex
});
this.config.create(true);
this.config.write(new ServerSettings());
this.api = new DefaultPlexApi(this, MODULE_API_COMPATIBILITY_VERSION);
new ListenerHandler();
}
@@ -0,0 +1,19 @@
package dev.plex.api.impl;
import dev.plex.api.ApiCompatibility;
final class DefaultApiCompatibility implements ApiCompatibility
{
private final int version;
DefaultApiCompatibility(int version)
{
this.version = version;
}
@Override
public int version()
{
return version;
}
}
@@ -0,0 +1,39 @@
package dev.plex.api.impl;
import dev.plex.Plex;
import dev.plex.api.config.ConfigurationApi;
import dev.plex.api.config.PlexConfiguration;
final class DefaultConfigurationApi implements ConfigurationApi
{
private final Plex plugin;
DefaultConfigurationApi(Plex plugin)
{
this.plugin = plugin;
}
@Override
public PlexConfiguration mainConfig()
{
return new DefaultPlexConfiguration(plugin.getConfig());
}
@Override
public PlexConfiguration messages()
{
throw new UnsupportedOperationException("Proxy does not provide messages configuration");
}
@Override
public PlexConfiguration indefiniteBans()
{
throw new UnsupportedOperationException("Proxy does not provide indefinite bans configuration");
}
@Override
public PlexConfiguration toggles()
{
throw new UnsupportedOperationException("Proxy does not provide toggles configuration");
}
}
@@ -0,0 +1,23 @@
package dev.plex.api.impl;
import dev.plex.api.module.ModulesApi;
import dev.plex.module.PlexModuleFile;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
final class DefaultModulesApi implements ModulesApi
{
@Override
public Collection<PlexModuleFile> loadedModules()
{
return List.of();
}
@Override
public Optional<PlexModuleFile> module(String name)
{
return Optional.empty();
}
}
@@ -0,0 +1,48 @@
package dev.plex.api.impl;
import dev.plex.Plex;
import dev.plex.api.ApiCompatibility;
import dev.plex.api.PlexApi;
import dev.plex.api.command.CommandApi;
import dev.plex.api.config.ConfigurationApi;
import dev.plex.api.config.ModuleConfigApi;
import dev.plex.api.listener.ListenerApi;
import dev.plex.api.logging.LoggingApi;
import dev.plex.api.message.MessageApi;
import dev.plex.api.module.ModulesApi;
import dev.plex.api.player.PlayersApi;
import dev.plex.api.punishment.PunishmentsApi;
import dev.plex.api.scheduler.SchedulerApi;
import dev.plex.api.storage.StorageApi;
public final class DefaultPlexApi implements PlexApi
{
private final ApiCompatibility compatibility;
private final ConfigurationApi configuration;
private final ModulesApi modules;
public DefaultPlexApi(Plex plugin, int apiCompatibilityVersion)
{
this.compatibility = new DefaultApiCompatibility(apiCompatibilityVersion);
this.configuration = new DefaultConfigurationApi(plugin);
this.modules = new DefaultModulesApi();
}
@Override public ApiCompatibility compatibility() { return compatibility; }
@Override public ConfigurationApi configuration() { return configuration; }
@Override public ModulesApi modules() { return modules; }
@Override public CommandApi commands() { throw unsupported(); }
@Override public ListenerApi listeners() { throw unsupported(); }
@Override public ModuleConfigApi moduleConfigs() { throw unsupported(); }
@Override public LoggingApi logging() { throw unsupported(); }
@Override public MessageApi messages() { throw unsupported(); }
@Override public PlayersApi players() { throw unsupported(); }
@Override public PunishmentsApi punishments() { throw unsupported(); }
@Override public SchedulerApi scheduler() { throw unsupported(); }
@Override public StorageApi storage() { throw unsupported(); }
private static UnsupportedOperationException unsupported()
{
return new UnsupportedOperationException("This Plex API service is only available on the server platform");
}
}
@@ -0,0 +1,59 @@
package dev.plex.api.impl;
import dev.plex.api.config.PlexConfiguration;
import dev.plex.config.TomlConfig;
import java.util.List;
final class DefaultPlexConfiguration implements PlexConfiguration
{
private final TomlConfig config;
DefaultPlexConfiguration(TomlConfig config)
{
this.config = config;
}
@Override
public String getString(String path)
{
return config.getToml().getString(path);
}
@Override
public boolean getBoolean(String path)
{
return config.getToml().getBoolean(path, false);
}
@Override
public int getInt(String path)
{
Long value = config.getToml().getLong(path, 0L);
return value.intValue();
}
@Override
public List<String> getStringList(String path)
{
return config.getToml().getList(path, List.of());
}
@Override
public void set(String path, Object value)
{
throw new UnsupportedOperationException("Proxy TOML configuration writes are not supported through PlexConfiguration");
}
@Override
public void setComments(String path, List<String> comments)
{
throw new UnsupportedOperationException("Proxy TOML configuration comments are not supported through PlexConfiguration");
}
@Override
public void save()
{
throw new UnsupportedOperationException("Proxy TOML configuration saves are not supported through PlexConfiguration");
}
}
@@ -9,13 +9,12 @@ import dev.plex.Plex;
import dev.plex.command.annotation.CommandParameters;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.command.source.RequiredCommandSource;
import java.util.Arrays;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class PlexCommand implements SimpleCommand
public abstract class ProxyCommand implements SimpleCommand
{
/**
* Returns the instance of the plugin
@@ -36,14 +35,17 @@ public abstract class PlexCommand implements SimpleCommand
*/
private final RequiredCommandSource commandSource;
public PlexCommand()
public ProxyCommand()
{
this.params = getClass().getAnnotation(CommandParameters.class);
this.perms = getClass().getAnnotation(CommandPermissions.class);
this.commandSource = this.perms.source();
CommandMeta.Builder meta = plugin.getServer().getCommandManager().metaBuilder(this.params.name());
meta.aliases(this.params.aliases());
if (!this.params.aliases().isEmpty())
{
meta.aliases(this.params.aliases().split(","));
}
meta.plugin(Plex.get());
plugin.getServer().getCommandManager().register(meta.build(), this);
}
@@ -92,7 +94,7 @@ public abstract class PlexCommand implements SimpleCommand
{
return true;
}
return Arrays.stream(params.aliases()).anyMatch(s -> s.equalsIgnoreCase(label));
return !params.aliases().isEmpty() && java.util.Arrays.stream(params.aliases().split(",")).anyMatch(s -> s.equalsIgnoreCase(label));
}
protected void send(Audience audience, Component component)
@@ -1,39 +0,0 @@
package dev.plex.command.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Storage for a command's parameters
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandParameters
{
/**
* The name
*
* @return Name of the command
*/
String name();
/**
* The description
*
* @return Description of the command
*/
String description() default "";
/**
* The usage (optional)
*
* @return The usage of the command
*/
String usage() default "/<command>";
/**
* The aliases (optional)
*
* @return The aliases of the command
*/
String[] aliases() default {};
}
@@ -1,27 +0,0 @@
package dev.plex.command.annotation;
import dev.plex.command.source.RequiredCommandSource;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Storage for the command's permissions
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandPermissions
{
/**
* Required command source
*
* @return The required command source of the command
* @see RequiredCommandSource
*/
RequiredCommandSource source() default RequiredCommandSource.ANY;
/**
* The permission
*
* @return Permission of the command
*/
String permission() default ""; // No idea what to put here
}
@@ -1,8 +0,0 @@
package dev.plex.command.source;
public enum RequiredCommandSource
{
IN_GAME,
CONSOLE,
ANY
}
@@ -1,7 +1,7 @@
package dev.plex.handlers;
import com.google.common.collect.Lists;
import dev.plex.listener.PlexListener;
import dev.plex.listener.ProxyListener;
import dev.plex.util.PlexLog;
import dev.plex.util.ReflectionsUtil;
import java.lang.reflect.InvocationTargetException;
@@ -12,8 +12,8 @@ public class ListenerHandler
{
public ListenerHandler()
{
Set<Class<? extends PlexListener>> listenerSet = ReflectionsUtil.getClassesBySubType("dev.plex.listener.impl", PlexListener.class);
List<PlexListener> listeners = Lists.newArrayList();
Set<Class<? extends ProxyListener>> listenerSet = ReflectionsUtil.getClassesBySubType("dev.plex.listener.impl", ProxyListener.class);
List<ProxyListener> listeners = Lists.newArrayList();
listenerSet.forEach(clazz ->
{
@@ -2,11 +2,11 @@ package dev.plex.listener;
import dev.plex.Plex;
public class PlexListener
public class ProxyListener
{
protected final Plex plugin = Plex.get();
public PlexListener()
public ProxyListener()
{
Plex.get().getServer().getEventManager().register(Plex.get(), this);
}
@@ -5,11 +5,11 @@ import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.player.ServerConnectedEvent;
import dev.plex.Plex;
import dev.plex.listener.PlexListener;
import dev.plex.listener.ProxyListener;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
public class ConnectionListener extends PlexListener
public class ConnectionListener extends ProxyListener
{
@Subscribe(order = PostOrder.FIRST)
public void onPlayerJoin(ServerConnectedEvent event)
@@ -4,7 +4,7 @@ import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
import com.velocitypowered.api.proxy.server.ServerPing;
import dev.plex.listener.PlexListener;
import dev.plex.listener.ProxyListener;
import dev.plex.settings.ServerSettings;
import dev.plex.util.RandomUtil;
import java.util.UUID;
@@ -15,7 +15,7 @@ import java.util.regex.Pattern;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
public class ServerListener extends PlexListener
public class ServerListener extends ProxyListener
{
@Subscribe(order = PostOrder.FIRST)
public void onPing(ProxyPingEvent event)