Add Javadocs

This commit is contained in:
2026-05-19 19:21:18 -04:00
parent 66476fe110
commit d58365f93f
35 changed files with 1199 additions and 0 deletions
@@ -6,6 +6,8 @@ package dev.plex.api;
public interface ApiCompatibility public interface ApiCompatibility
{ {
/** /**
* Returns the module API compatibility version.
*
* @return the provided module API compatibility version * @return the provided module API compatibility version
*/ */
int version(); int version();
@@ -22,37 +22,93 @@ import dev.plex.api.storage.StorageApi;
public interface PlexApi public interface PlexApi
{ {
/** /**
* Returns module API compatibility information for this Plex build.
*
* @return module API compatibility information for this Plex build * @return module API compatibility information for this Plex build
*/ */
ApiCompatibility compatibility(); ApiCompatibility compatibility();
/** /**
* Returns access to shared Plex configuration files.
*
* @return safe access to shared Plex configuration files * @return safe access to shared Plex configuration files
*/ */
ConfigurationApi configuration(); ConfigurationApi configuration();
/** /**
* Returns access to module metadata and module-related operations.
*
* @return safe access to module metadata and module-related operations * @return safe access to module metadata and module-related operations
*/ */
ModulesApi modules(); ModulesApi modules();
/**
* Returns command registration operations.
*
* @return command registration operations for Plex commands
*/
CommandApi commands(); CommandApi commands();
/**
* Returns listener registration operations.
*
* @return listener registration operations for Bukkit listeners
*/
ListenerApi listeners(); ListenerApi listeners();
/**
* Returns module configuration creation operations.
*
* @return module configuration creation operations
*/
ModuleConfigApi moduleConfigs(); ModuleConfigApi moduleConfigs();
/**
* Returns logging operations.
*
* @return Plex logging operations
*/
LoggingApi logging(); LoggingApi logging();
/**
* Returns message formatting and broadcast operations.
*
* @return message formatting and broadcast operations
*/
MessageApi messages(); MessageApi messages();
/**
* Returns player lookup operations.
*
* @return player lookup operations
*/
PlayersApi players(); PlayersApi players();
/**
* Returns punishment lookup and creation operations.
*
* @return punishment lookup and creation operations
*/
PunishmentsApi punishments(); PunishmentsApi punishments();
/**
* Returns CoreProtect rollback operations.
*
* @return CoreProtect rollback operations
*/
RollbackApi rollback(); RollbackApi rollback();
/**
* Returns Paper and Folia scheduler operations.
*
* @return Paper and Folia scheduler operations
*/
SchedulerApi scheduler(); SchedulerApi scheduler();
/**
* Returns SQL storage access operations.
*
* @return SQL storage access operations
*/
StorageApi storage(); StorageApi storage();
} }
@@ -2,9 +2,22 @@ package dev.plex.api.command;
import dev.plex.command.PlexCommand; import dev.plex.command.PlexCommand;
/**
* Registers and unregisters Plex commands with the running platform.
*/
public interface CommandApi public interface CommandApi
{ {
/**
* Registers a command with Plex.
*
* @param command command to register
*/
void register(PlexCommand command); void register(PlexCommand command);
/**
* Unregisters a command from Plex.
*
* @param command command to unregister
*/
void unregister(PlexCommand command); void unregister(PlexCommand command);
} }
@@ -5,11 +5,31 @@ package dev.plex.api.config;
*/ */
public interface ConfigurationApi public interface ConfigurationApi
{ {
/**
* Returns the main Plex configuration.
*
* @return the main Plex configuration
*/
PlexConfiguration mainConfig(); PlexConfiguration mainConfig();
/**
* Returns the shared message configuration.
*
* @return the shared message configuration
*/
PlexConfiguration messages(); PlexConfiguration messages();
/**
* Returns the indefinite ban configuration.
*
* @return the indefinite ban configuration
*/
PlexConfiguration indefiniteBans(); PlexConfiguration indefiniteBans();
/**
* Returns the toggle configuration.
*
* @return the toggle configuration
*/
PlexConfiguration toggles(); PlexConfiguration toggles();
} }
@@ -2,7 +2,18 @@ package dev.plex.api.config;
import dev.plex.module.PlexModule; import dev.plex.module.PlexModule;
/**
* Creates configuration files owned by Plex modules.
*/
public interface ModuleConfigApi public interface ModuleConfigApi
{ {
/**
* Creates or opens a module configuration.
*
* @param module module that owns the configuration
* @param from resource path to copy defaults from
* @param to destination file path relative to the module data folder
* @return module configuration wrapper
*/
ModuleConfiguration create(PlexModule module, String from, String to); ModuleConfiguration create(PlexModule module, String from, String to);
} }
@@ -2,8 +2,25 @@ package dev.plex.api.config;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
/**
* Mutable YAML configuration owned by a Plex module.
*/
public abstract class ModuleConfiguration extends YamlConfiguration public abstract class ModuleConfiguration extends YamlConfiguration
{ {
/**
* Creates a module configuration.
*/
public ModuleConfiguration()
{
}
/**
* Loads the configuration from disk, merging defaults when the implementation supports it.
*/
public abstract void load(); public abstract void load();
/**
* Saves the configuration to disk.
*/
public abstract void save(); public abstract void save();
} }
@@ -7,25 +7,92 @@ import java.util.List;
*/ */
public interface PlexConfiguration public interface PlexConfiguration
{ {
/**
* Reads a string value.
*
* @param path configuration path
* @return configured string, or {@code null} if absent
*/
String getString(String path); String getString(String path);
/**
* Reads a string value with a fallback.
*
* @param path configuration path
* @param fallback value returned when the path is absent
* @return configured string or fallback
*/
String getString(String path, String fallback); String getString(String path, String fallback);
/**
* Reads a boolean value.
*
* @param path configuration path
* @return configured boolean, or the underlying configuration default
*/
boolean getBoolean(String path); boolean getBoolean(String path);
/**
* Reads a boolean value with a fallback.
*
* @param path configuration path
* @param fallback value returned when the path is absent
* @return configured boolean or fallback
*/
boolean getBoolean(String path, boolean fallback); boolean getBoolean(String path, boolean fallback);
/**
* Reads an integer value.
*
* @param path configuration path
* @return configured integer, or the underlying configuration default
*/
int getInt(String path); int getInt(String path);
/**
* Reads an integer value with a fallback.
*
* @param path configuration path
* @param fallback value returned when the path is absent
* @return configured integer or fallback
*/
int getInt(String path, int fallback); int getInt(String path, int fallback);
/**
* Reads a string list.
*
* @param path configuration path
* @return configured string list
*/
List<String> getStringList(String path); List<String> getStringList(String path);
/**
* Reads a string list with a fallback.
*
* @param path configuration path
* @param fallback value returned when the path is absent
* @return configured string list or fallback
*/
List<String> getStringList(String path, List<String> fallback); List<String> getStringList(String path, List<String> fallback);
/**
* Sets a configuration value.
*
* @param path configuration path
* @param value value to write
*/
void set(String path, Object value); void set(String path, Object value);
/**
* Sets comments above a configuration path.
*
* @param path configuration path
* @param comments comments to write
*/
void setComments(String path, List<String> comments); void setComments(String path, List<String> comments);
/**
* Saves pending configuration changes to disk.
*/
void save(); void save();
} }
@@ -2,9 +2,22 @@ package dev.plex.api.listener;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
/**
* Registers and unregisters Bukkit event listeners for modules.
*/
public interface ListenerApi public interface ListenerApi
{ {
/**
* Registers a listener with Plex.
*
* @param listener listener to register
*/
void register(Listener listener); void register(Listener listener);
/**
* Unregisters a listener from Bukkit handler lists.
*
* @param listener listener to unregister
*/
void unregister(Listener listener); void unregister(Listener listener);
} }
@@ -1,9 +1,39 @@
package dev.plex.api.logging; package dev.plex.api.logging;
/**
* Logging facade exposed through the Plex API.
*/
public interface LoggingApi public interface LoggingApi
{ {
/**
* Writes an informational log message.
*
* @param message message template
* @param args template arguments
*/
void info(String message, Object... args); void info(String message, Object... args);
/**
* Writes a debug log message.
*
* @param message message template
* @param args template arguments
*/
void debug(String message, Object... args); void debug(String message, Object... args);
/**
* Writes a warning log message.
*
* @param message message template
* @param args template arguments
*/
void warn(String message, Object... args); void warn(String message, Object... args);
/**
* Writes an error log message.
*
* @param message message template
* @param args template arguments
*/
void error(String message, Object... args); void error(String message, Object... args);
} }
@@ -3,13 +3,64 @@ package dev.plex.api.message;
import java.util.List; import java.util.List;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
/**
* Formats configured messages and broadcasts Adventure components.
*/
public interface MessageApi public interface MessageApi
{ {
/**
* Resolves a configured message entry into a component.
*
* @param entry message key
* @param objects replacement values
* @return resolved component
*/
Component messageComponent(String entry, Object... objects); Component messageComponent(String entry, Object... objects);
/**
* Resolves a configured message entry into a component using component replacements.
*
* @param entry message key
* @param objects component replacement values
* @return resolved component
*/
Component messageComponent(String entry, Component... objects); Component messageComponent(String entry, Component... objects);
/**
* Resolves a configured message entry into a plain string.
*
* @param entry message key
* @param objects replacement values
* @return resolved message string
*/
String messageString(String entry, Object... objects); String messageString(String entry, Object... objects);
/**
* Deserializes MiniMessage input into a component.
*
* @param input MiniMessage input
* @return deserialized component
*/
Component miniMessage(String input); Component miniMessage(String input);
/**
* Broadcasts a MiniMessage string to online players.
*
* @param miniMessage MiniMessage input to broadcast
*/
void broadcast(String miniMessage); void broadcast(String miniMessage);
/**
* Broadcasts a component to online players.
*
* @param component component to broadcast
*/
void broadcast(Component component); void broadcast(Component component);
/**
* Returns the names of currently online players.
*
* @return names of currently online players
*/
List<String> onlinePlayerNames(); List<String> onlinePlayerNames();
} }
@@ -11,6 +11,8 @@ import java.util.Optional;
public interface ModulesApi public interface ModulesApi
{ {
/** /**
* Returns metadata for all currently discovered modules.
*
* @return immutable metadata for all currently discovered modules * @return immutable metadata for all currently discovered modules
*/ */
Collection<PlexModuleFile> loadedModules(); Collection<PlexModuleFile> loadedModules();
@@ -4,9 +4,31 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
/**
* Looks up Plex players through read-only API views.
*/
public interface PlayersApi public interface PlayersApi
{ {
/**
* Looks up a player by UUID.
*
* @param uuid player UUID
* @return player view, if known
*/
Optional<? extends PlexPlayerView> byUuid(UUID uuid); Optional<? extends PlexPlayerView> byUuid(UUID uuid);
/**
* Looks up a player by name.
*
* @param name player name
* @return player view, if known
*/
Optional<? extends PlexPlayerView> byName(String name); Optional<? extends PlexPlayerView> byName(String name);
/**
* Returns the names of currently online players.
*
* @return names of currently online players
*/
List<String> onlineNames(); List<String> onlineNames();
} }
@@ -5,14 +5,64 @@ import java.util.UUID;
import dev.plex.api.punishment.PunishmentView; import dev.plex.api.punishment.PunishmentView;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
/**
* Read-only view of a Plex player.
*/
public interface PlexPlayerView public interface PlexPlayerView
{ {
/**
* Returns the player's UUID.
*
* @return player UUID
*/
UUID uuid(); UUID uuid();
/**
* Returns the current or last known player name.
*
* @return current or last known player name
*/
String name(); String name();
/**
* Returns known IP addresses.
*
* @return immutable copy of known IP addresses
*/
List<String> ips(); List<String> ips();
/**
* Returns the player's punishment history.
*
* @return punishment history for the player
*/
List<? extends PunishmentView> punishments(); List<? extends PunishmentView> punishments();
/**
* Returns whether the player is currently frozen.
*
* @return whether the player is currently frozen
*/
boolean frozen(); boolean frozen();
/**
* Returns whether the player is currently muted.
*
* @return whether the player is currently muted
*/
boolean muted(); boolean muted();
/**
* Returns whether the player is currently locked up.
*
* @return whether the player is currently locked up
*/
boolean lockedUp(); boolean lockedUp();
/**
* Returns the Bukkit player instance.
*
* @return Bukkit player instance, or {@code null} when the player is offline
*/
Player bukkitPlayer(); Player bukkitPlayer();
} }
@@ -3,10 +3,36 @@ package dev.plex.api.punishment;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
/**
* Read-only view of an indefinite ban entry.
*/
public interface IndefiniteBanView public interface IndefiniteBanView
{ {
/**
* Returns usernames covered by the ban.
*
* @return usernames covered by the ban
*/
List<String> usernames(); List<String> usernames();
/**
* Returns UUIDs covered by the ban.
*
* @return UUIDs covered by the ban
*/
List<UUID> uuids(); List<UUID> uuids();
/**
* Returns IP addresses covered by the ban.
*
* @return IP addresses covered by the ban
*/
List<String> ips(); List<String> ips();
/**
* Returns the ban reason.
*
* @return ban reason
*/
String reason(); String reason();
} }
@@ -3,6 +3,20 @@ package dev.plex.api.punishment;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.UUID; import java.util.UUID;
/**
* Request payload used to create a punishment for a player.
*
* @param punished UUID of the player being punished
* @param punisher UUID of the actor issuing the punishment
* @param punisherName display name of the actor issuing the punishment
* @param ip IP address associated with the punished player
* @param punishedUsername username of the punished player
* @param type punishment type to apply
* @param reason punishment reason
* @param customTime whether the punishment uses a custom duration
* @param active whether the punishment should start active
* @param endDate punishment end date, or {@code null} for punishments without an end date
*/
public record PunishmentRequest(UUID punished, UUID punisher, String punisherName, String ip, public record PunishmentRequest(UUID punished, UUID punisher, String punisherName, String ip,
String punishedUsername, PunishmentType type, String reason, String punishedUsername, PunishmentType type, String reason,
boolean customTime, boolean active, ZonedDateTime endDate) boolean customTime, boolean active, ZonedDateTime endDate)
@@ -1,11 +1,37 @@
package dev.plex.api.punishment; package dev.plex.api.punishment;
/**
* Supported punishment types exposed through the API.
*/
public enum PunishmentType public enum PunishmentType
{ {
/**
* Prevents chat or other messaging actions.
*/
MUTE, MUTE,
/**
* Freezes player movement.
*/
FREEZE, FREEZE,
/**
* Permanently bans a player.
*/
BAN, BAN,
/**
* Temporarily bans a player until an end date.
*/
TEMPBAN, TEMPBAN,
/**
* Kicks a player from the server.
*/
KICK, KICK,
/**
* Applies the smite action to a player.
*/
SMITE SMITE
} }
@@ -3,17 +3,85 @@ package dev.plex.api.punishment;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.UUID; import java.util.UUID;
/**
* Read-only view of a Plex punishment.
*/
public interface PunishmentView public interface PunishmentView
{ {
/**
* Returns the UUID of the punished player.
*
* @return UUID of the punished player
*/
UUID punished(); UUID punished();
/**
* Returns the UUID of the actor who issued the punishment.
*
* @return UUID of the actor who issued the punishment
*/
UUID punisher(); UUID punisher();
/**
* Returns the display name of the actor who issued the punishment.
*
* @return display name of the actor who issued the punishment
*/
String punisherName(); String punisherName();
/**
* Returns the IP address associated with the punished player.
*
* @return IP address associated with the punished player
*/
String ip(); String ip();
/**
* Returns the username of the punished player.
*
* @return username of the punished player
*/
String punishedUsername(); String punishedUsername();
/**
* Returns the punishment type.
*
* @return punishment type
*/
PunishmentType type(); PunishmentType type();
/**
* Returns the punishment reason.
*
* @return punishment reason
*/
String reason(); String reason();
/**
* Returns whether the punishment uses a custom duration.
*
* @return whether the punishment uses a custom duration
*/
boolean customTime(); boolean customTime();
/**
* Returns whether the punishment is currently active.
*
* @return whether the punishment is currently active
*/
boolean active(); boolean active();
/**
* Returns the date and time when the punishment was issued.
*
* @return date and time when the punishment was issued
*/
ZonedDateTime issueDate(); ZonedDateTime issueDate();
/**
* Returns the punishment end date.
*
* @return punishment end date, or {@code null} for punishments without an end date
*/
ZonedDateTime endDate(); ZonedDateTime endDate();
} }
@@ -5,9 +5,31 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import dev.plex.api.player.PlexPlayerView; import dev.plex.api.player.PlexPlayerView;
/**
* Reads and creates Plex punishments.
*/
public interface PunishmentsApi public interface PunishmentsApi
{ {
/**
* Returns current indefinite bans.
*
* @return current indefinite bans
*/
List<? extends IndefiniteBanView> indefiniteBans(); List<? extends IndefiniteBanView> indefiniteBans();
/**
* Looks up an indefinite ban by UUID.
*
* @param uuid UUID to look up
* @return matching indefinite ban, if one exists
*/
Optional<? extends IndefiniteBanView> indefiniteBanByUuid(UUID uuid); Optional<? extends IndefiniteBanView> indefiniteBanByUuid(UUID uuid);
/**
* Applies a punishment to a player.
*
* @param player player to punish
* @param punishment punishment details
*/
void punish(PlexPlayerView player, PunishmentRequest punishment); void punish(PlexPlayerView player, PunishmentRequest punishment);
} }
@@ -2,12 +2,35 @@ package dev.plex.api.rollback;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
/**
* CoreProtect rollback operations exposed to modules.
*/
public interface RollbackApi public interface RollbackApi
{ {
/**
* Returns whether rollback support is currently available.
*
* @return whether rollback support is currently available
*/
boolean isAvailable(); boolean isAvailable();
/**
* Rolls back changes made by a player.
*
* @param sender command sender receiving rollback output
* @param playerName player name to roll back
* @param seconds number of seconds to roll back
* @return {@code true} when the rollback was accepted
*/
boolean rollback(CommandSender sender, String playerName, int seconds); boolean rollback(CommandSender sender, String playerName, int seconds);
/**
* Rolls back the last 24 hours of changes made by a player.
*
* @param sender command sender receiving rollback output
* @param playerName player name to roll back
* @return {@code true} when the rollback was accepted
*/
default boolean rollbackLastDay(CommandSender sender, String playerName) default boolean rollbackLastDay(CommandSender sender, String playerName)
{ {
return rollback(sender, playerName, 86400); return rollback(sender, playerName, 86400);
@@ -11,12 +11,17 @@ import org.bukkit.World;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/**
* Scheduling facade for Paper and Folia-safe task execution.
*/
public interface SchedulerApi public interface SchedulerApi
{ {
/** /**
* Executor backed by Paper's async scheduler. * Executor backed by Paper's async scheduler.
* Use it for blocking I/O and CPU work that does not touch Bukkit world, * Use it for blocking I/O and CPU work that does not touch Bukkit world,
* entity, inventory, or command state. * entity, inventory, or command state.
*
* @return async scheduler executor
*/ */
Executor asyncExecutor(); Executor asyncExecutor();
@@ -25,16 +30,27 @@ public interface SchedulerApi
* Use the global region for state owned by Folia's global region, such as * Use the global region for state owned by Folia's global region, such as
* console command dispatch, world time, weather, game rules, and plugin-level * console command dispatch, world time, weather, game rules, and plugin-level
* coordination work. * coordination work.
*
* @param task task to execute
*/ */
void executeGlobal(Runnable task); void executeGlobal(Runnable task);
/** /**
* Runs work on the next global-region tick. * Runs work on the next global-region tick.
* *
* @param task task consumer receiving the scheduled task
* @return scheduled task handle
* @see #executeGlobal(Runnable) * @see #executeGlobal(Runnable)
*/ */
ScheduledTask runGlobal(Consumer<ScheduledTask> task); ScheduledTask runGlobal(Consumer<ScheduledTask> task);
/**
* Runs work on the next global-region tick.
*
* @param task task to run
* @return scheduled task handle
* @see #runGlobal(Consumer)
*/
default ScheduledTask runGlobal(Runnable task) default ScheduledTask runGlobal(Runnable task)
{ {
return runGlobal(scheduledTask -> task.run()); return runGlobal(scheduledTask -> task.run());
@@ -43,10 +59,21 @@ public interface SchedulerApi
/** /**
* Runs work on the global region after a tick delay. * Runs work on the global region after a tick delay.
* *
* @param task task consumer receiving the scheduled task
* @param delayTicks delay in server ticks
* @return scheduled task handle
* @see #executeGlobal(Runnable) * @see #executeGlobal(Runnable)
*/ */
ScheduledTask runGlobalLater(Consumer<ScheduledTask> task, long delayTicks); ScheduledTask runGlobalLater(Consumer<ScheduledTask> task, long delayTicks);
/**
* Runs work on the global region after a tick delay.
*
* @param task task to run
* @param delayTicks delay in server ticks
* @return scheduled task handle
* @see #runGlobalLater(Consumer, long)
*/
default ScheduledTask runGlobalLater(Runnable task, long delayTicks) default ScheduledTask runGlobalLater(Runnable task, long delayTicks)
{ {
return runGlobalLater(scheduledTask -> task.run(), delayTicks); return runGlobalLater(scheduledTask -> task.run(), delayTicks);
@@ -55,10 +82,23 @@ public interface SchedulerApi
/** /**
* Runs repeating work on the global region. * Runs repeating work on the global region.
* *
* @param task task consumer receiving the scheduled task
* @param delayTicks initial delay in server ticks
* @param periodTicks repeat interval in server ticks
* @return scheduled task handle
* @see #executeGlobal(Runnable) * @see #executeGlobal(Runnable)
*/ */
ScheduledTask runGlobalTimer(Consumer<ScheduledTask> task, long delayTicks, long periodTicks); ScheduledTask runGlobalTimer(Consumer<ScheduledTask> task, long delayTicks, long periodTicks);
/**
* Runs repeating work on the global region.
*
* @param task task to run
* @param delayTicks initial delay in server ticks
* @param periodTicks repeat interval in server ticks
* @return scheduled task handle
* @see #runGlobalTimer(Consumer, long, long)
*/
default ScheduledTask runGlobalTimer(Runnable task, long delayTicks, long periodTicks) default ScheduledTask runGlobalTimer(Runnable task, long delayTicks, long periodTicks)
{ {
return runGlobalTimer(scheduledTask -> task.run(), delayTicks, periodTicks); return runGlobalTimer(scheduledTask -> task.run(), delayTicks, periodTicks);
@@ -67,9 +107,19 @@ public interface SchedulerApi
/** /**
* Runs work on Paper's async scheduler. * Runs work on Paper's async scheduler.
* Do not touch Bukkit world, entity, inventory, or command state here. * Do not touch Bukkit world, entity, inventory, or command state here.
*
* @param task task consumer receiving the scheduled task
* @return scheduled task handle
*/ */
ScheduledTask runAsync(Consumer<ScheduledTask> task); ScheduledTask runAsync(Consumer<ScheduledTask> task);
/**
* Runs work on Paper's async scheduler.
*
* @param task task to run
* @return scheduled task handle
* @see #runAsync(Consumer)
*/
default ScheduledTask runAsync(Runnable task) default ScheduledTask runAsync(Runnable task)
{ {
return runAsync(scheduledTask -> task.run()); return runAsync(scheduledTask -> task.run());
@@ -78,10 +128,23 @@ public interface SchedulerApi
/** /**
* Runs async work after a wall-clock delay. * Runs async work after a wall-clock delay.
* *
* @param task task consumer receiving the scheduled task
* @param delay delay amount
* @param unit delay time unit
* @return scheduled task handle
* @see #runAsync(Consumer) * @see #runAsync(Consumer)
*/ */
ScheduledTask runAsyncLater(Consumer<ScheduledTask> task, long delay, TimeUnit unit); ScheduledTask runAsyncLater(Consumer<ScheduledTask> task, long delay, TimeUnit unit);
/**
* Runs async work after a wall-clock delay.
*
* @param task task to run
* @param delay delay amount
* @param unit delay time unit
* @return scheduled task handle
* @see #runAsyncLater(Consumer, long, TimeUnit)
*/
default ScheduledTask runAsyncLater(Runnable task, long delay, TimeUnit unit) default ScheduledTask runAsyncLater(Runnable task, long delay, TimeUnit unit)
{ {
return runAsyncLater(scheduledTask -> task.run(), delay, unit); return runAsyncLater(scheduledTask -> task.run(), delay, unit);
@@ -90,10 +153,25 @@ public interface SchedulerApi
/** /**
* Runs repeating async work on a wall-clock interval. * Runs repeating async work on a wall-clock interval.
* *
* @param task task consumer receiving the scheduled task
* @param delay initial delay amount
* @param period repeat interval amount
* @param unit delay and period time unit
* @return scheduled task handle
* @see #runAsync(Consumer) * @see #runAsync(Consumer)
*/ */
ScheduledTask runAsyncTimer(Consumer<ScheduledTask> task, long delay, long period, TimeUnit unit); ScheduledTask runAsyncTimer(Consumer<ScheduledTask> task, long delay, long period, TimeUnit unit);
/**
* Runs repeating async work on a wall-clock interval.
*
* @param task task to run
* @param delay initial delay amount
* @param period repeat interval amount
* @param unit delay and period time unit
* @return scheduled task handle
* @see #runAsyncTimer(Consumer, long, long, TimeUnit)
*/
default ScheduledTask runAsyncTimer(Runnable task, long delay, long period, TimeUnit unit) default ScheduledTask runAsyncTimer(Runnable task, long delay, long period, TimeUnit unit)
{ {
return runAsyncTimer(scheduledTask -> task.run(), delay, period, unit); return runAsyncTimer(scheduledTask -> task.run(), delay, period, unit);
@@ -102,22 +180,41 @@ public interface SchedulerApi
/** /**
* Executes work on the region that owns the supplied location. * Executes work on the region that owns the supplied location.
* Use this for block, chunk, and location-bound world access. * Use this for block, chunk, and location-bound world access.
*
* @param location location whose owning region should run the task
* @param task task to execute
*/ */
void executeRegion(Location location, Runnable task); void executeRegion(Location location, Runnable task);
/** /**
* Executes work on the region that owns the supplied chunk. * Executes work on the region that owns the supplied chunk.
* Use this for block, chunk, and location-bound world access. * Use this for block, chunk, and location-bound world access.
*
* @param world world containing the chunk
* @param chunkX chunk X coordinate
* @param chunkZ chunk Z coordinate
* @param task task to execute
*/ */
void executeRegion(World world, int chunkX, int chunkZ, Runnable task); void executeRegion(World world, int chunkX, int chunkZ, Runnable task);
/** /**
* Runs work on the next tick of the region that owns the supplied location. * Runs work on the next tick of the region that owns the supplied location.
* *
* @param location location whose owning region should run the task
* @param task task consumer receiving the scheduled task
* @return scheduled task handle
* @see #executeRegion(Location, Runnable) * @see #executeRegion(Location, Runnable)
*/ */
ScheduledTask runRegion(Location location, Consumer<ScheduledTask> task); ScheduledTask runRegion(Location location, Consumer<ScheduledTask> task);
/**
* Runs work on the next tick of the region that owns the supplied location.
*
* @param location location whose owning region should run the task
* @param task task to run
* @return scheduled task handle
* @see #runRegion(Location, Consumer)
*/
default ScheduledTask runRegion(Location location, Runnable task) default ScheduledTask runRegion(Location location, Runnable task)
{ {
return runRegion(location, scheduledTask -> task.run()); return runRegion(location, scheduledTask -> task.run());
@@ -126,10 +223,25 @@ public interface SchedulerApi
/** /**
* Runs work on the next tick of the region that owns the supplied chunk. * Runs work on the next tick of the region that owns the supplied chunk.
* *
* @param world world containing the chunk
* @param chunkX chunk X coordinate
* @param chunkZ chunk Z coordinate
* @param task task consumer receiving the scheduled task
* @return scheduled task handle
* @see #executeRegion(World, int, int, Runnable) * @see #executeRegion(World, int, int, Runnable)
*/ */
ScheduledTask runRegion(World world, int chunkX, int chunkZ, Consumer<ScheduledTask> task); ScheduledTask runRegion(World world, int chunkX, int chunkZ, Consumer<ScheduledTask> task);
/**
* Runs work on the next tick of the region that owns the supplied chunk.
*
* @param world world containing the chunk
* @param chunkX chunk X coordinate
* @param chunkZ chunk Z coordinate
* @param task task to run
* @return scheduled task handle
* @see #runRegion(World, int, int, Consumer)
*/
default ScheduledTask runRegion(World world, int chunkX, int chunkZ, Runnable task) default ScheduledTask runRegion(World world, int chunkX, int chunkZ, Runnable task)
{ {
return runRegion(world, chunkX, chunkZ, scheduledTask -> task.run()); return runRegion(world, chunkX, chunkZ, scheduledTask -> task.run());
@@ -138,10 +250,23 @@ public interface SchedulerApi
/** /**
* Runs work on a location's owning region after a tick delay. * Runs work on a location's owning region after a tick delay.
* *
* @param location location whose owning region should run the task
* @param task task consumer receiving the scheduled task
* @param delayTicks delay in server ticks
* @return scheduled task handle
* @see #executeRegion(Location, Runnable) * @see #executeRegion(Location, Runnable)
*/ */
ScheduledTask runRegionLater(Location location, Consumer<ScheduledTask> task, long delayTicks); ScheduledTask runRegionLater(Location location, Consumer<ScheduledTask> task, long delayTicks);
/**
* Runs work on a location's owning region after a tick delay.
*
* @param location location whose owning region should run the task
* @param task task to run
* @param delayTicks delay in server ticks
* @return scheduled task handle
* @see #runRegionLater(Location, Consumer, long)
*/
default ScheduledTask runRegionLater(Location location, Runnable task, long delayTicks) default ScheduledTask runRegionLater(Location location, Runnable task, long delayTicks)
{ {
return runRegionLater(location, scheduledTask -> task.run(), delayTicks); return runRegionLater(location, scheduledTask -> task.run(), delayTicks);
@@ -150,10 +275,27 @@ public interface SchedulerApi
/** /**
* Runs work on a chunk's owning region after a tick delay. * Runs work on a chunk's owning region after a tick delay.
* *
* @param world world containing the chunk
* @param chunkX chunk X coordinate
* @param chunkZ chunk Z coordinate
* @param task task consumer receiving the scheduled task
* @param delayTicks delay in server ticks
* @return scheduled task handle
* @see #executeRegion(World, int, int, Runnable) * @see #executeRegion(World, int, int, Runnable)
*/ */
ScheduledTask runRegionLater(World world, int chunkX, int chunkZ, Consumer<ScheduledTask> task, long delayTicks); ScheduledTask runRegionLater(World world, int chunkX, int chunkZ, Consumer<ScheduledTask> task, long delayTicks);
/**
* Runs work on a chunk's owning region after a tick delay.
*
* @param world world containing the chunk
* @param chunkX chunk X coordinate
* @param chunkZ chunk Z coordinate
* @param task task to run
* @param delayTicks delay in server ticks
* @return scheduled task handle
* @see #runRegionLater(World, int, int, Consumer, long)
*/
default ScheduledTask runRegionLater(World world, int chunkX, int chunkZ, Runnable task, long delayTicks) default ScheduledTask runRegionLater(World world, int chunkX, int chunkZ, Runnable task, long delayTicks)
{ {
return runRegionLater(world, chunkX, chunkZ, scheduledTask -> task.run(), delayTicks); return runRegionLater(world, chunkX, chunkZ, scheduledTask -> task.run(), delayTicks);
@@ -162,10 +304,25 @@ public interface SchedulerApi
/** /**
* Runs repeating work on a location's owning region. * Runs repeating work on a location's owning region.
* *
* @param location location whose owning region should run the task
* @param task task consumer receiving the scheduled task
* @param delayTicks initial delay in server ticks
* @param periodTicks repeat interval in server ticks
* @return scheduled task handle
* @see #executeRegion(Location, Runnable) * @see #executeRegion(Location, Runnable)
*/ */
ScheduledTask runRegionTimer(Location location, Consumer<ScheduledTask> task, long delayTicks, long periodTicks); ScheduledTask runRegionTimer(Location location, Consumer<ScheduledTask> task, long delayTicks, long periodTicks);
/**
* Runs repeating work on a location's owning region.
*
* @param location location whose owning region should run the task
* @param task task to run
* @param delayTicks initial delay in server ticks
* @param periodTicks repeat interval in server ticks
* @return scheduled task handle
* @see #runRegionTimer(Location, Consumer, long, long)
*/
default ScheduledTask runRegionTimer(Location location, Runnable task, long delayTicks, long periodTicks) default ScheduledTask runRegionTimer(Location location, Runnable task, long delayTicks, long periodTicks)
{ {
return runRegionTimer(location, scheduledTask -> task.run(), delayTicks, periodTicks); return runRegionTimer(location, scheduledTask -> task.run(), delayTicks, periodTicks);
@@ -174,10 +331,29 @@ public interface SchedulerApi
/** /**
* Runs repeating work on a chunk's owning region. * Runs repeating work on a chunk's owning region.
* *
* @param world world containing the chunk
* @param chunkX chunk X coordinate
* @param chunkZ chunk Z coordinate
* @param task task consumer receiving the scheduled task
* @param delayTicks initial delay in server ticks
* @param periodTicks repeat interval in server ticks
* @return scheduled task handle
* @see #executeRegion(World, int, int, Runnable) * @see #executeRegion(World, int, int, Runnable)
*/ */
ScheduledTask runRegionTimer(World world, int chunkX, int chunkZ, Consumer<ScheduledTask> task, long delayTicks, long periodTicks); ScheduledTask runRegionTimer(World world, int chunkX, int chunkZ, Consumer<ScheduledTask> task, long delayTicks, long periodTicks);
/**
* Runs repeating work on a chunk's owning region.
*
* @param world world containing the chunk
* @param chunkX chunk X coordinate
* @param chunkZ chunk Z coordinate
* @param task task to run
* @param delayTicks initial delay in server ticks
* @param periodTicks repeat interval in server ticks
* @return scheduled task handle
* @see #runRegionTimer(World, int, int, Consumer, long, long)
*/
default ScheduledTask runRegionTimer(World world, int chunkX, int chunkZ, Runnable task, long delayTicks, long periodTicks) default ScheduledTask runRegionTimer(World world, int chunkX, int chunkZ, Runnable task, long delayTicks, long periodTicks)
{ {
return runRegionTimer(world, chunkX, chunkZ, scheduledTask -> task.run(), delayTicks, periodTicks); return runRegionTimer(world, chunkX, chunkZ, scheduledTask -> task.run(), delayTicks, periodTicks);
@@ -190,10 +366,23 @@ public interface SchedulerApi
* Paper runs the retired callback if the entity is removed before the task * Paper runs the retired callback if the entity is removed before the task
* can execute. * can execute.
* *
* @param entity entity whose scheduler should run the task
* @param task task to execute
* @param retired callback run if the entity retires before execution
* @param delayTicks delay in server ticks
* @return true if Paper accepted the task * @return true if Paper accepted the task
*/ */
boolean executeEntity(Entity entity, Runnable task, @Nullable Runnable retired, long delayTicks); boolean executeEntity(Entity entity, Runnable task, @Nullable Runnable retired, long delayTicks);
/**
* Executes work on the region that currently owns the entity.
*
* @param entity entity whose scheduler should run the task
* @param task task to execute
* @param delayTicks delay in server ticks
* @return {@code true} if Paper accepted the task
* @see #executeEntity(Entity, Runnable, Runnable, long)
*/
default boolean executeEntity(Entity entity, Runnable task, long delayTicks) default boolean executeEntity(Entity entity, Runnable task, long delayTicks)
{ {
return executeEntity(entity, task, null, delayTicks); return executeEntity(entity, task, null, delayTicks);
@@ -202,11 +391,23 @@ public interface SchedulerApi
/** /**
* Runs work on the next tick of the entity's owning region. * Runs work on the next tick of the entity's owning region.
* *
* @param entity entity whose scheduler should run the task
* @param task task consumer receiving the scheduled task
* @param retired callback run if the entity retires before execution
* @return scheduled task handle, or {@code null} if the entity is retired
* @see #executeEntity(Entity, Runnable, Runnable, long) * @see #executeEntity(Entity, Runnable, Runnable, long)
*/ */
@Nullable @Nullable
ScheduledTask runEntity(Entity entity, Consumer<ScheduledTask> task, @Nullable Runnable retired); ScheduledTask runEntity(Entity entity, Consumer<ScheduledTask> task, @Nullable Runnable retired);
/**
* Runs work on the next tick of the entity's owning region.
*
* @param entity entity whose scheduler should run the task
* @param task task to run
* @return scheduled task handle, or {@code null} if the entity is retired
* @see #runEntity(Entity, Consumer, Runnable)
*/
default @Nullable ScheduledTask runEntity(Entity entity, Runnable task) default @Nullable ScheduledTask runEntity(Entity entity, Runnable task)
{ {
return runEntity(entity, scheduledTask -> task.run(), null); return runEntity(entity, scheduledTask -> task.run(), null);
@@ -215,11 +416,25 @@ public interface SchedulerApi
/** /**
* Runs work on the entity's owning region after a tick delay. * Runs work on the entity's owning region after a tick delay.
* *
* @param entity entity whose scheduler should run the task
* @param task task consumer receiving the scheduled task
* @param retired callback run if the entity retires before execution
* @param delayTicks delay in server ticks
* @return scheduled task handle, or {@code null} if the entity is retired
* @see #executeEntity(Entity, Runnable, Runnable, long) * @see #executeEntity(Entity, Runnable, Runnable, long)
*/ */
@Nullable @Nullable
ScheduledTask runEntityLater(Entity entity, Consumer<ScheduledTask> task, @Nullable Runnable retired, long delayTicks); ScheduledTask runEntityLater(Entity entity, Consumer<ScheduledTask> task, @Nullable Runnable retired, long delayTicks);
/**
* Runs work on the entity's owning region after a tick delay.
*
* @param entity entity whose scheduler should run the task
* @param task task to run
* @param delayTicks delay in server ticks
* @return scheduled task handle, or {@code null} if the entity is retired
* @see #runEntityLater(Entity, Consumer, Runnable, long)
*/
default @Nullable ScheduledTask runEntityLater(Entity entity, Runnable task, long delayTicks) default @Nullable ScheduledTask runEntityLater(Entity entity, Runnable task, long delayTicks)
{ {
return runEntityLater(entity, scheduledTask -> task.run(), null, delayTicks); return runEntityLater(entity, scheduledTask -> task.run(), null, delayTicks);
@@ -228,11 +443,27 @@ public interface SchedulerApi
/** /**
* Runs repeating work on the entity's owning region. * Runs repeating work on the entity's owning region.
* *
* @param entity entity whose scheduler should run the task
* @param task task consumer receiving the scheduled task
* @param retired callback run if the entity retires before execution
* @param delayTicks initial delay in server ticks
* @param periodTicks repeat interval in server ticks
* @return scheduled task handle, or {@code null} if the entity is retired
* @see #executeEntity(Entity, Runnable, Runnable, long) * @see #executeEntity(Entity, Runnable, Runnable, long)
*/ */
@Nullable @Nullable
ScheduledTask runEntityTimer(Entity entity, Consumer<ScheduledTask> task, @Nullable Runnable retired, long delayTicks, long periodTicks); ScheduledTask runEntityTimer(Entity entity, Consumer<ScheduledTask> task, @Nullable Runnable retired, long delayTicks, long periodTicks);
/**
* Runs repeating work on the entity's owning region.
*
* @param entity entity whose scheduler should run the task
* @param task task to run
* @param delayTicks initial delay in server ticks
* @param periodTicks repeat interval in server ticks
* @return scheduled task handle, or {@code null} if the entity is retired
* @see #runEntityTimer(Entity, Consumer, Runnable, long, long)
*/
default @Nullable ScheduledTask runEntityTimer(Entity entity, Runnable task, long delayTicks, long periodTicks) default @Nullable ScheduledTask runEntityTimer(Entity entity, Runnable task, long delayTicks, long periodTicks)
{ {
return runEntityTimer(entity, scheduledTask -> task.run(), null, delayTicks, periodTicks); return runEntityTimer(entity, scheduledTask -> task.run(), null, delayTicks, periodTicks);
@@ -3,13 +3,36 @@ package dev.plex.api.storage;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
/**
* Provides controlled access to Plex SQL storage.
*/
public interface StorageApi public interface StorageApi
{ {
/**
* Opens a SQL connection for the supplied callback and closes it afterwards.
*
* @param function callback that uses the connection
* @param <T> callback result type
* @return callback result
* @throws SQLException if a connection or callback SQL operation fails
*/
<T> T withConnection(SqlFunction<T> function) throws SQLException; <T> T withConnection(SqlFunction<T> function) throws SQLException;
/**
* SQL callback used by {@link #withConnection(SqlFunction)}.
*
* @param <T> callback result type
*/
@FunctionalInterface @FunctionalInterface
interface SqlFunction<T> interface SqlFunction<T>
{ {
/**
* Uses a SQL connection.
*
* @param connection open SQL connection
* @return callback result
* @throws SQLException if the callback cannot complete its SQL work
*/
T apply(Connection connection) throws SQLException; T apply(Connection connection) throws SQLException;
} }
} }
@@ -13,8 +13,19 @@ import java.util.List;
*/ */
public interface PlexCommand public interface PlexCommand
{ {
/**
* Builds the Brigadier command tree for this command.
*
* @return root literal command node
*/
LiteralCommandNode<CommandSourceStack> buildCommand(); LiteralCommandNode<CommandSourceStack> buildCommand();
/**
* Reads command parameter metadata from {@link CommandParameters}.
*
* @return command parameter metadata
* @throws IllegalStateException if the command class is missing {@link CommandParameters}
*/
default CommandParameters parameters() default CommandParameters parameters()
{ {
CommandParameters parameters = getClass().getAnnotation(CommandParameters.class); CommandParameters parameters = getClass().getAnnotation(CommandParameters.class);
@@ -25,6 +36,12 @@ public interface PlexCommand
return parameters; return parameters;
} }
/**
* Reads command permission metadata from {@link CommandPermissions}.
*
* @return command permission metadata
* @throws IllegalStateException if the command class is missing {@link CommandPermissions}
*/
default CommandPermissions permissions() default CommandPermissions permissions()
{ {
CommandPermissions permissions = getClass().getAnnotation(CommandPermissions.class); CommandPermissions permissions = getClass().getAnnotation(CommandPermissions.class);
@@ -35,31 +52,61 @@ public interface PlexCommand
return permissions; return permissions;
} }
/**
* Returns the primary command name.
*
* @return primary command name
*/
default String getName() default String getName()
{ {
return parameters().name(); return parameters().name();
} }
/**
* Returns the command description.
*
* @return command description
*/
default String getDescription() default String getDescription()
{ {
return parameters().description(); return parameters().description();
} }
/**
* Returns command usage text.
*
* @return command usage text with {@code <command>} replaced by the command name
*/
default String getUsage() default String getUsage()
{ {
return parameters().usage().replace("<command>", getName()); return parameters().usage().replace("<command>", getName());
} }
/**
* Returns the permission node required to use the command.
*
* @return permission node required to use the command
*/
default String getPermission() default String getPermission()
{ {
return permissions().permission(); return permissions().permission();
} }
/**
* Returns the command source required to run the command.
*
* @return command source required to run the command
*/
default RequiredCommandSource getRequiredSource() default RequiredCommandSource getRequiredSource()
{ {
return permissions().source(); return permissions().source();
} }
/**
* Returns command aliases as a trimmed list.
*
* @return comma-separated aliases from {@link CommandParameters#aliases()} as a trimmed list
*/
default List<String> getAliases() default List<String> getAliases()
{ {
String aliases = parameters().aliases(); String aliases = parameters().aliases();
@@ -3,11 +3,37 @@ package dev.plex.command.annotation;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
/**
* Declares display and invocation metadata for a Plex command.
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface CommandParameters public @interface CommandParameters
{ {
/**
* Returns the primary command name.
*
* @return primary command name
*/
String name(); String name();
/**
* Returns the short command description.
*
* @return short command description
*/
String description() default ""; String description() default "";
/**
* Returns the command usage text.
*
* @return command usage text; {@code <command>} is replaced with the command name
*/
String usage() default "/<command>"; String usage() default "/<command>";
/**
* Returns comma-separated command aliases.
*
* @return comma-separated command aliases
*/
String aliases() default ""; String aliases() default "";
} }
@@ -4,9 +4,23 @@ import dev.plex.command.source.RequiredCommandSource;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
/**
* Declares permission and command-source requirements for a Plex command.
*/
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface CommandPermissions public @interface CommandPermissions
{ {
/**
* Returns the permission node required to use the command.
*
* @return permission node required to use the command
*/
String permission() default ""; String permission() default "";
/**
* Returns the command source required to run the command.
*
* @return command source required to run the command
*/
RequiredCommandSource source() default RequiredCommandSource.ANY; RequiredCommandSource source() default RequiredCommandSource.ANY;
} }
@@ -1,12 +1,23 @@
package dev.plex.command.exception; package dev.plex.command.exception;
/**
* Signals that command execution failed with a user-facing message.
*/
public class CommandFailException extends RuntimeException public class CommandFailException extends RuntimeException
{ {
/**
* Creates an exception with the default command failure marker message.
*/
public CommandFailException() public CommandFailException()
{ {
super("CommandFailException"); super("CommandFailException");
} }
/**
* Creates an exception with a custom user-facing failure message.
*
* @param message failure message
*/
public CommandFailException(String message) public CommandFailException(String message)
{ {
super(message); super(message);
@@ -1,12 +1,23 @@
package dev.plex.command.exception; package dev.plex.command.exception;
/**
* Signals that the console must supply a target player for a command.
*/
public class ConsoleMustDefinePlayerException extends RuntimeException public class ConsoleMustDefinePlayerException extends RuntimeException
{ {
/**
* Creates an exception with the default console target marker message.
*/
public ConsoleMustDefinePlayerException() public ConsoleMustDefinePlayerException()
{ {
super("ConsoleMustDefinePlayerException"); super("ConsoleMustDefinePlayerException");
} }
/**
* Creates an exception with a custom user-facing message.
*
* @param message failure message
*/
public ConsoleMustDefinePlayerException(String message) public ConsoleMustDefinePlayerException(String message)
{ {
super(message); super(message);
@@ -1,12 +1,23 @@
package dev.plex.command.exception; package dev.plex.command.exception;
/**
* Signals that a command can only be run from the console.
*/
public class ConsoleOnlyException extends RuntimeException public class ConsoleOnlyException extends RuntimeException
{ {
/**
* Creates an exception with the default console-only marker message.
*/
public ConsoleOnlyException() public ConsoleOnlyException()
{ {
super("ConsoleOnlyException"); super("ConsoleOnlyException");
} }
/**
* Creates an exception with a custom user-facing message.
*
* @param message failure message
*/
public ConsoleOnlyException(String message) public ConsoleOnlyException(String message)
{ {
super(message); super(message);
@@ -1,12 +1,23 @@
package dev.plex.command.exception; package dev.plex.command.exception;
/**
* Signals that a command expected a banned player but none was found.
*/
public class PlayerNotBannedException extends RuntimeException public class PlayerNotBannedException extends RuntimeException
{ {
/**
* Creates an exception with the default player-not-banned marker message.
*/
public PlayerNotBannedException() public PlayerNotBannedException()
{ {
super("PlayerNotBannedException"); super("PlayerNotBannedException");
} }
/**
* Creates an exception with a custom user-facing message.
*
* @param message failure message
*/
public PlayerNotBannedException(String message) public PlayerNotBannedException(String message)
{ {
super(message); super(message);
@@ -1,12 +1,23 @@
package dev.plex.command.exception; package dev.plex.command.exception;
/**
* Signals that a command could not find the requested player.
*/
public class PlayerNotFoundException extends RuntimeException public class PlayerNotFoundException extends RuntimeException
{ {
/**
* Creates an exception with the default player-not-found marker message.
*/
public PlayerNotFoundException() public PlayerNotFoundException()
{ {
super("PlayerNotFoundException"); super("PlayerNotFoundException");
} }
/**
* Creates an exception with a custom user-facing message.
*
* @param message failure message
*/
public PlayerNotFoundException(String message) public PlayerNotFoundException(String message)
{ {
super(message); super(message);
@@ -1,8 +1,22 @@
package dev.plex.command.source; package dev.plex.command.source;
/**
* Source restrictions for command execution.
*/
public enum RequiredCommandSource public enum RequiredCommandSource
{ {
/**
* Allows both player and console sources.
*/
ANY, ANY,
/**
* Allows only in-game player sources.
*/
IN_GAME, IN_GAME,
/**
* Allows only console sources.
*/
CONSOLE CONSOLE
} }
@@ -11,11 +11,24 @@ public class ModuleConfig extends ModuleConfiguration
private static Factory factory; private static Factory factory;
private final ModuleConfiguration delegate; private final ModuleConfiguration delegate;
/**
* Installs the platform factory used to create module configurations.
*
* @param factory module configuration factory
*/
public static void setFactory(Factory factory) public static void setFactory(Factory factory)
{ {
ModuleConfig.factory = factory; ModuleConfig.factory = factory;
} }
/**
* Creates or opens a module configuration through the installed platform factory.
*
* @param module module that owns the configuration
* @param from resource path to copy defaults from
* @param to destination file path relative to the module data folder
* @throws IllegalStateException if Plex has not installed a factory yet
*/
public ModuleConfig(PlexModule module, String from, String to) public ModuleConfig(PlexModule module, String from, String to)
{ {
if (factory == null) if (factory == null)
@@ -25,99 +38,155 @@ public class ModuleConfig extends ModuleConfiguration
this.delegate = factory.create(module, from, to); this.delegate = factory.create(module, from, to);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void load() public void load()
{ {
delegate.load(); delegate.load();
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void save() public void save()
{ {
delegate.save(); delegate.save();
} }
/**
* {@inheritDoc}
*/
@Override @Override
public Object get(String path) public Object get(String path)
{ {
return delegate.get(path); return delegate.get(path);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public Object get(String path, Object def) public Object get(String path, Object def)
{ {
return delegate.get(path, def); return delegate.get(path, def);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public String getString(String path) public String getString(String path)
{ {
return delegate.getString(path); return delegate.getString(path);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public String getString(String path, String def) public String getString(String path, String def)
{ {
return delegate.getString(path, def); return delegate.getString(path, def);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public int getInt(String path) public int getInt(String path)
{ {
return delegate.getInt(path); return delegate.getInt(path);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public int getInt(String path, int def) public int getInt(String path, int def)
{ {
return delegate.getInt(path, def); return delegate.getInt(path, def);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public boolean getBoolean(String path) public boolean getBoolean(String path)
{ {
return delegate.getBoolean(path); return delegate.getBoolean(path);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public boolean getBoolean(String path, boolean def) public boolean getBoolean(String path, boolean def)
{ {
return delegate.getBoolean(path, def); return delegate.getBoolean(path, def);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public long getLong(String path) public long getLong(String path)
{ {
return delegate.getLong(path); return delegate.getLong(path);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public long getLong(String path, long def) public long getLong(String path, long def)
{ {
return delegate.getLong(path, def); return delegate.getLong(path, def);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public double getDouble(String path) public double getDouble(String path)
{ {
return delegate.getDouble(path); return delegate.getDouble(path);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public double getDouble(String path, double def) public double getDouble(String path, double def)
{ {
return delegate.getDouble(path, def); return delegate.getDouble(path, def);
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void set(String path, Object value) public void set(String path, Object value)
{ {
delegate.set(path, value); delegate.set(path, value);
} }
/**
* Factory installed by the platform to create module configuration delegates.
*/
@FunctionalInterface @FunctionalInterface
public interface Factory public interface Factory
{ {
/**
* Creates or opens a module configuration.
*
* @param module module that owns the configuration
* @param from resource path to copy defaults from
* @param to destination file path relative to the module data folder
* @return created configuration
*/
ModuleConfiguration create(PlexModule module, String from, String to); ModuleConfiguration create(PlexModule module, String from, String to);
} }
} }
@@ -2,8 +2,14 @@ package dev.plex.listener;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
/**
* Base type for Plex listeners.
*/
public abstract class PlexListener implements Listener public abstract class PlexListener implements Listener
{ {
/**
* Creates a listener instance.
*/
protected PlexListener() protected PlexListener()
{ {
} }
@@ -35,23 +35,49 @@ public abstract class PlexModule
private File dataFolder; private File dataFolder;
private Logger logger; private Logger logger;
/**
* Creates a Plex module.
*/
public PlexModule()
{
}
/**
* Returns the Plex API facade.
*
* @return Plex API facade for supported module integrations
*/
public PlexApi api() public PlexApi api()
{ {
return api; return api;
} }
/**
* Called when the module is loaded.
*/
public void load() public void load()
{ {
} }
/**
* Called when the module is enabled.
*/
public void enable() public void enable()
{ {
} }
/**
* Called when the module is disabled.
*/
public void disable() public void disable()
{ {
} }
/**
* Registers and tracks a listener owned by this module.
*
* @param listener listener to register
*/
public void registerListener(Listener listener) public void registerListener(Listener listener)
{ {
listeners.add(listener); listeners.add(listener);
@@ -61,6 +87,11 @@ public abstract class PlexModule
} }
} }
/**
* Unregisters and stops tracking a listener owned by this module.
*
* @param listener listener to unregister
*/
public void unregisterListener(Listener listener) public void unregisterListener(Listener listener)
{ {
listeners.remove(listener); listeners.remove(listener);
@@ -72,6 +103,11 @@ public abstract class PlexModule
HandlerList.unregisterAll(listener); HandlerList.unregisterAll(listener);
} }
/**
* Registers and tracks a command owned by this module.
*
* @param command command to register
*/
public void registerCommand(PlexCommand command) public void registerCommand(PlexCommand command)
{ {
commands.add(command); commands.add(command);
@@ -81,6 +117,11 @@ public abstract class PlexModule
} }
} }
/**
* Unregisters and stops tracking a command owned by this module.
*
* @param command command to unregister
*/
public void unregisterCommand(PlexCommand command) public void unregisterCommand(PlexCommand command)
{ {
commands.remove(command); commands.remove(command);
@@ -90,6 +131,12 @@ public abstract class PlexModule
} }
} }
/**
* Looks up a tracked command by name or alias.
*
* @param name command name or alias
* @return matching command, or {@code null} when no command matches
*/
@Nullable @Nullable
public PlexCommand getCommand(String name) public PlexCommand getCommand(String name)
{ {
@@ -99,6 +146,12 @@ public abstract class PlexModule
.orElse(null); .orElse(null);
} }
/**
* Adds a default message if the message key is not already configured.
*
* @param message message key
* @param initValue default value to write
*/
public void addDefaultMessage(String message, Object initValue) public void addDefaultMessage(String message, Object initValue)
{ {
if (api.configuration().messages().getString(message) == null) if (api.configuration().messages().getString(message) == null)
@@ -109,6 +162,13 @@ public abstract class PlexModule
} }
} }
/**
* Adds a default message and comments if the message key is not already configured.
*
* @param message message key
* @param initValue default value to write
* @param comments comments to write above the message key
*/
public void addDefaultMessage(String message, Object initValue, String... comments) public void addDefaultMessage(String message, Object initValue, String... comments)
{ {
if (api.configuration().messages().getString(message) == null) if (api.configuration().messages().getString(message) == null)
@@ -121,6 +181,12 @@ public abstract class PlexModule
} }
} }
/**
* Opens a resource from this module's class loader.
*
* @param filename resource path
* @return resource stream, or {@code null} when the resource cannot be opened
*/
@Nullable @Nullable
public InputStream getResource(@NotNull String filename) public InputStream getResource(@NotNull String filename)
{ {
@@ -142,46 +208,91 @@ public abstract class PlexModule
} }
} }
/**
* Returns commands currently tracked by this module.
*
* @return commands currently tracked by this module
*/
public List<PlexCommand> getCommands() public List<PlexCommand> getCommands()
{ {
return commands; return commands;
} }
/**
* Returns listeners currently tracked by this module.
*
* @return listeners currently tracked by this module
*/
public List<Listener> getListeners() public List<Listener> getListeners()
{ {
return listeners; return listeners;
} }
/**
* Returns metadata read from this module's module.yml.
*
* @return metadata read from this module's module.yml
*/
public PlexModuleFile getPlexModuleFile() public PlexModuleFile getPlexModuleFile()
{ {
return plexModuleFile; return plexModuleFile;
} }
/**
* Returns the module data folder.
*
* @return module data folder
*/
public File getDataFolder() public File getDataFolder()
{ {
return dataFolder; return dataFolder;
} }
/**
* Returns the module logger.
*
* @return module logger
*/
public Logger getLogger() public Logger getLogger()
{ {
return logger; return logger;
} }
/**
* Sets the Plex API facade for this module.
*
* @param api Plex API facade
*/
public void setApi(PlexApi api) public void setApi(PlexApi api)
{ {
this.api = api; this.api = api;
} }
/**
* Sets metadata read from this module's module.yml.
*
* @param plexModuleFile module metadata
*/
public void setPlexModuleFile(PlexModuleFile plexModuleFile) public void setPlexModuleFile(PlexModuleFile plexModuleFile)
{ {
this.plexModuleFile = plexModuleFile; this.plexModuleFile = plexModuleFile;
} }
/**
* Sets the module data folder.
*
* @param dataFolder data folder
*/
public void setDataFolder(File dataFolder) public void setDataFolder(File dataFolder)
{ {
this.dataFolder = dataFolder; this.dataFolder = dataFolder;
} }
/**
* Sets the module logger.
*
* @param logger logger
*/
public void setLogger(Logger logger) public void setLogger(Logger logger)
{ {
this.logger = logger; this.logger = logger;
@@ -15,6 +15,15 @@ public final class PlexModuleFile
private List<String> libraries = List.of(); private List<String> libraries = List.of();
private List<String> repositories = List.of(); private List<String> repositories = List.of();
/**
* Creates module metadata.
*
* @param name module name
* @param main main module class
* @param description module description
* @param version module version
* @param apiCompatibility required Plex API compatibility version
*/
public PlexModuleFile(String name, String main, String description, String version, int apiCompatibility) public PlexModuleFile(String name, String main, String description, String version, int apiCompatibility)
{ {
this.name = name; this.name = name;
@@ -24,46 +33,91 @@ public final class PlexModuleFile
this.apiCompatibility = apiCompatibility; this.apiCompatibility = apiCompatibility;
} }
/**
* Returns the module name.
*
* @return module name
*/
public String getName() public String getName()
{ {
return name; return name;
} }
/**
* Returns the main module class.
*
* @return main module class
*/
public String getMain() public String getMain()
{ {
return main; return main;
} }
/**
* Returns the module description.
*
* @return module description
*/
public String getDescription() public String getDescription()
{ {
return description; return description;
} }
/**
* Returns the module version.
*
* @return module version
*/
public String getVersion() public String getVersion()
{ {
return version; return version;
} }
/**
* Returns the required Plex API compatibility version.
*
* @return required Plex API compatibility version
*/
public int getApiCompatibility() public int getApiCompatibility()
{ {
return apiCompatibility; return apiCompatibility;
} }
/**
* Returns dependency libraries declared by the module.
*
* @return dependency libraries declared by the module
*/
public List<String> getLibraries() public List<String> getLibraries()
{ {
return libraries; return libraries;
} }
/**
* Sets dependency libraries declared by the module.
*
* @param libraries dependency libraries
*/
public void setLibraries(List<String> libraries) public void setLibraries(List<String> libraries)
{ {
this.libraries = List.copyOf(libraries); this.libraries = List.copyOf(libraries);
} }
/**
* Returns Maven repositories declared by the module.
*
* @return Maven repositories declared by the module
*/
public List<String> getRepositories() public List<String> getRepositories()
{ {
return repositories; return repositories;
} }
/**
* Sets Maven repositories declared by the module.
*
* @param repositories Maven repositories
*/
public void setRepositories(List<String> repositories) public void setRepositories(List<String> repositories)
{ {
this.repositories = List.copyOf(repositories); this.repositories = List.copyOf(repositories);
@@ -12,16 +12,32 @@ import java.time.Instant;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
/**
* Gson adapter that stores {@link ZonedDateTime} values as epoch milliseconds in UTC.
*/
public class ZonedDateTimeAdapter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> public class ZonedDateTimeAdapter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime>
{ {
private static final ZoneId UTC = ZoneId.of("Etc/UTC"); private static final ZoneId UTC = ZoneId.of("Etc/UTC");
/**
* Creates a Gson adapter for {@link ZonedDateTime}.
*/
public ZonedDateTimeAdapter()
{
}
/**
* {@inheritDoc}
*/
@Override @Override
public JsonElement serialize(ZonedDateTime src, Type typeOfSrc, JsonSerializationContext context) public JsonElement serialize(ZonedDateTime src, Type typeOfSrc, JsonSerializationContext context)
{ {
return new JsonPrimitive(src.toInstant().toEpochMilli()); return new JsonPrimitive(src.toInstant().toEpochMilli());
} }
/**
* {@inheritDoc}
*/
@Override @Override
public ZonedDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException public ZonedDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{ {