Merge pull request #19 from FlorianMichael/Implementations

Merge dev into production
This commit is contained in:
Paldiu 2023-08-11 13:17:21 -05:00 committed by GitHub
commit e3807e29d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
165 changed files with 2513 additions and 1152 deletions

View File

@ -0,0 +1,22 @@
package fns.corvo;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Registration;
import org.bukkit.plugin.java.JavaPlugin;
public class Corvo extends JavaPlugin
{
@Override
public void onDisable()
{
Registration.getModuleRegistry()
.removeModule(this);
}
@Override
public void onEnable()
{
Registration.getModuleRegistry()
.addModule(this);
}
}

View File

@ -1,4 +1,4 @@
package me.totalfreedom.corvo.listener;
package fns.corvo.listener;
import io.papermc.paper.event.block.BlockBreakBlockEvent;
import org.bukkit.event.EventHandler;

View File

@ -1,25 +0,0 @@
package me.totalfreedom.corvo;
import me.totalfreedom.base.CommonsBase;
import org.bukkit.plugin.java.JavaPlugin;
public class Corvo extends JavaPlugin
{
@Override
public void onDisable()
{
CommonsBase.getInstance()
.getRegistrations()
.getModuleRegistry()
.removeModule(this);
}
@Override
public void onEnable()
{
CommonsBase.getInstance()
.getRegistrations()
.getModuleRegistry()
.addModule(this);
}
}

View File

@ -1,5 +1,6 @@
name: Corvo
main: me.totalfreedom.corvo.Corvo
main: fns.corvo.Corvo
api-version: 1.20
version: 1.0.0
author: TotalFreedom
description: Services and Listeners for the Freedom Network Suite

View File

@ -0,0 +1,77 @@
package fns.datura;
import fns.datura.features.CommandSpy;
import fns.datura.features.Fuckoff;
import fns.datura.punishment.Cager;
import fns.datura.punishment.Halter;
import fns.datura.punishment.Locker;
import fns.datura.sql.MySQL;
import fns.patchwork.base.Registration;
import fns.patchwork.service.SubscriptionProvider;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
public class Datura extends JavaPlugin
{
private final MySQL sql = new MySQL("localhost", 3011, "master");
// Punishment
private final Halter halter = new Halter();
private final Locker locker = new Locker();
private Cager cager;
// Features
private final CommandSpy commandSpy = new CommandSpy();
private final Fuckoff fuckoff = new Fuckoff();
@Override
public void onEnable()
{
cager = new Cager(this);
Registration.getServiceTaskRegistry()
.registerService(SubscriptionProvider.syncService(this, locker));
Registration.getServiceTaskRegistry()
.registerService(SubscriptionProvider.syncService(this, cager));
Registration.getServiceTaskRegistry()
.registerService(SubscriptionProvider.syncService(this, fuckoff));
Bukkit.getPluginManager()
.registerEvents(halter, this);
Bukkit.getPluginManager()
.registerEvents(commandSpy, this);
Registration.getModuleRegistry()
.addModule(this);
}
public MySQL getSQL()
{
return sql;
}
public Halter getHalter()
{
return halter;
}
public Locker getLocker()
{
return locker;
}
public Cager getCager()
{
return cager;
}
public CommandSpy getCommandSpy()
{
return commandSpy;
}
public Fuckoff getFuckoff()
{
return fuckoff;
}
}

View File

@ -0,0 +1,65 @@
package fns.datura.cmd;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Base;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "")
@Permissive(perm = "")
public class AdminChatCommand extends Commander
{
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public AdminChatCommand(@NotNull final JavaPlugin plugin)
{
super(plugin);
}
@Base
public void onAdminChat(final CommandSender sender)
{
if (!(sender instanceof Player)) return;
final Player player = (Player) sender;
Shortcuts.provideModule(Patchwork.class)
.getAdminChatDisplay()
.toggleChat(player);
final boolean toggled = Shortcuts.provideModule(Patchwork.class)
.getAdminChatDisplay()
.isToggled(player);
String message = "Toggled adminchat ";
message += toggled ? "on" : "off";
player.sendPlainMessage(message + ".");
}
// String here will automatically have all additional args appended to it :)
@Subcommand(permission = "patchwork.adminchat", args = {String.class})
public void sendMessage(final CommandSender sender, final String message)
{
Shortcuts.provideModule(Patchwork.class)
.getAdminChatDisplay()
.adminChatMessage(sender, Component.text(message));
}
}

View File

@ -19,14 +19,15 @@
* THE SOFTWARE.
*/
package me.totalfreedom.datura.cmd;
package fns.datura.cmd;
import me.totalfreedom.command.Commander;
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 me.totalfreedom.datura.Datura;
import fns.datura.Datura;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -36,54 +37,48 @@ import org.jetbrains.annotations.NotNull;
@Info(name = "cage", description = "Cage a player.",
usage = "/cage <player> <on|off> [material]")
@Permissive(perm = "datura.cage")
@Completion(args = {"%player%"}, index = 0)
@Completion(args = {"on", "off"}, index = 1)
@Completion(args = {"[material]"}, index = 2)
public class CageCommand extends Commander
{
protected CageCommand(final @NotNull JavaPlugin plugin)
public CageCommand(final @NotNull JavaPlugin plugin)
{
super(plugin);
}
@Completion(args = {"%player%"}, index = 0)
@Completion(args = {"on", "off"}, index = 1)
@Subcommand(permission = "datura.cage", args = {Player.class, String.class})
public void cagePlayer(final CommandSender sender, final Player player, final String string)
{
switch (string.toLowerCase())
{
case "on" ->
if (string.equalsIgnoreCase("on"))
{
((Datura) getPlugin()).getCager()
.cagePlayer(player.getUniqueId());
sender.sendPlainMessage("Caged " + player.getName() + ".");
}
case "off" ->
} else if (string.equalsIgnoreCase("off"))
{
((Datura) getPlugin()).getCager()
.uncagePlayer(player.getUniqueId());
sender.sendPlainMessage("Liberated " + player.getName() + ".");
}
}
}
@Completion(args = {"[material]"}, index = 2)
@Subcommand(permission = "datura.cage.custom", args = {Player.class, String.class, Material.class})
public void cagePlayer(final CommandSender sender, final Player player, final String string,
final Material material)
{
switch (string.toLowerCase())
if (string.equalsIgnoreCase("on"))
{
case "on" ->
{
((Datura) getPlugin()).getCager()
Shortcuts.provideModule(Datura.class)
.getCager()
.cagePlayer(player.getUniqueId(), material);
sender.sendPlainMessage("Caged " + player.getName() + ".");
}
case "off" ->
} else if (string.equalsIgnoreCase("off"))
{
((Datura) getPlugin()).getCager()
Shortcuts.provideModule(Datura.class)
.getCager()
.uncagePlayer(player.getUniqueId());
sender.sendPlainMessage("Liberated " + player.getName() + ".");
}
}
}
}

View File

@ -0,0 +1,94 @@
package fns.datura.cmd;
import fns.datura.Datura;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Base;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "cleardrops", description = "Clears all item drops in the world" + ".", usage = "/<command>", aliases =
{"cd", "clearitems", "ci", "wipeitems", "wi", "removedrops", "rd"})
@Permissive(perm = "datura.cleardrops")
@Completion(index = 0, args = {"%world%"})
public class ClearDropsCommand extends Commander
{
/**
* Initializes this command object. The provided {@link JavaPlugin}
* should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and
* completions for this command. It will also
* automatically infer all required information from the provided
* {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public ClearDropsCommand(final @NotNull JavaPlugin plugin)
{
super(plugin);
}
@Base
public void clearDrops(final CommandSender sender)
{
if (!(sender instanceof Player))
{
sender.sendPlainMessage("You must define a world.");
return;
}
final Player player = (Player) sender;
Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.delayedExecutor(Shortcuts.provideModule(Datura.class), 20 * 10L)
.execute(() ->
{
int i = 0;
for (final Entity entity : player.getWorld().getEntities())
{
if (entity instanceof Item)
{
entity.remove();
i++;
}
}
player.sendPlainMessage("Successfully removed " + i + " items.");
});
}
@Subcommand(permission = "datura.cleardrops", args = {World.class})
public void clearDrops(final CommandSender sender, final World world)
{
Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.delayedExecutor(Shortcuts.provideModule(Datura.class), 20 * 10L)
.execute(() ->
{
int i = 0;
for (final Entity entity : world.getEntities())
{
if (entity instanceof Item)
{
entity.remove();
i++;
}
}
sender.sendPlainMessage("Successfully removed " + i + " items.");
});
}
}

View File

@ -0,0 +1,74 @@
package fns.datura.cmd;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Base;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import fns.patchwork.utils.Tagged;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "clearentities", description = "Clears all entities in the world.", usage = "/<command> [world]",
aliases = {"ew", "ce", "entitywipe", "entityclear", "ec"})
@Permissive(perm = "datura.clearentities")
@Completion(index = 0, args = {"%world%"})
public class ClearEntitiesCommand extends Commander
{
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public ClearEntitiesCommand(final @NotNull JavaPlugin plugin)
{
super(plugin);
}
@Base
public void clearEntities(final CommandSender sender)
{
if (!(sender instanceof Player))
{
sender.sendPlainMessage("You must specify a world to clear entities from.");
return;
}
final Player player = (Player) sender;
int i = 0;
for (final Entity entity : player.getWorld().getEntities())
{
if (!Tagged.NON_WIPEABLE.isTagged(entity.getType()))
{
entity.remove();
i++;
}
}
sender.sendPlainMessage("Cleared " + i + " entities.");
}
@Subcommand(permission = "datura.clearentities", args = {World.class})
public void clearEntities(final CommandSender sender, final World world)
{
int i = 0;
for (final Entity entity : world.getEntities())
{
if (!Tagged.NON_WIPEABLE.isTagged(entity.getType()))
{
entity.remove();
i++;
}
}
sender.sendPlainMessage("Cleared " + i + " entities.");
}
}

View File

@ -0,0 +1,51 @@
package fns.datura.cmd;
import fns.datura.Datura;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Base;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "commandspy", description = "Spy on commands executed by players.", usage = "/commandspy")
@Permissive(perm = "datura.commandspy", onlyPlayers = true)
public class CommandSpyCommand extends Commander
{
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public CommandSpyCommand(@NotNull final Datura plugin)
{
super(plugin);
}
@Base
public void commandSpy(final Player sender)
{
final var commandSpy = ((Datura) getPlugin()).
getCommandSpy();
final var uuid = sender.
getUniqueId();
if (commandSpy.isSpying(uuid))
{
commandSpy.stop(uuid);
sender.sendPlainMessage("CommandSpy disabled.");
}
else
{
commandSpy.spy(uuid);
sender.sendPlainMessage("CommandSpy enabled.");
}
}
}

View File

@ -0,0 +1,64 @@
package fns.datura.cmd;
import fns.datura.Datura;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "fuckoff", description = "You'll never even see it coming - repeatedly push players away from you until command is untoggled.", usage = "/fuckoff <on|off> [radius]")
@Permissive(perm = "datura.fuckoff", onlyPlayers = true)
@Completion(args = {"on", "off"}, index = 0)
@Completion(args = {"[radius]"}, index = 1)
public class FuckoffCommand extends Commander
{
private final Datura plugin = Shortcuts.provideModule(Datura.class);
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public FuckoffCommand(@NotNull final JavaPlugin plugin)
{
super(plugin);
}
@Subcommand(permission = "datura.fuckoff", args = {String.class})
public void fuckOff(final Player sender, final String toggle)
{
execute(sender, toggle, 15);
}
@Subcommand(permission = "datura.fuckoff", args = {String.class, Integer.class})
public void fuckOff(final Player sender, final String toggle, final Integer radius)
{
execute(sender, toggle, radius);
}
private void execute(final Player sender, final String toggle, final int radius)
{
if (toggle.equalsIgnoreCase("on"))
{
plugin.getFuckoff().
add(sender, radius);
sender.sendPlainMessage("FuckOff enabled.");
} else if (toggle.equalsIgnoreCase("off"))
{
plugin.getFuckoff().
remove(sender);
sender.sendPlainMessage("FuckOff disabled.");
}
}
}

View File

@ -0,0 +1,88 @@
package fns.datura.cmd;
import fns.datura.Datura;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "halt", description = "Halt a single player, or every player.", usage = "/<command> <player | all> <on, off>")
@Permissive(perm = "datura.halt")
@Completion(index = 0, args = {"%player%", "all"})
@Completion(index = 1, args = {"on", "off"})
public class HaltCommand extends Commander
{
private final Datura plugin = Shortcuts.provideModule(Datura.class);
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public HaltCommand(@NotNull final JavaPlugin plugin)
{
super(plugin);
}
@Subcommand(permission = "datura.halt", args = {Player.class, String.class})
public void haltPlayer(final CommandSender sender, final Player target, final String toggle)
{
if (toggle.equalsIgnoreCase("on"))
{
plugin.getHalter()
.halt(target.getUniqueId());
target.sendPlainMessage("You have been frozen!");
sender.sendPlainMessage("You have halted " + target.getName() + ".");
} else if (toggle.equalsIgnoreCase("off"))
{
plugin.getHalter()
.stop(target.getUniqueId());
target.sendPlainMessage("You have been unfrozen!");
sender.sendPlainMessage("You have unhalted " + target.getName() + ".");
}
}
@Subcommand(permission = "datura.halt.all", args = {String.class, String.class})
public void haltAll(final CommandSender sender, final String all, final String toggle)
{
if (all.equalsIgnoreCase("all"))
{
if (toggle.equalsIgnoreCase("on"))
{
Bukkit.getServer()
.getOnlinePlayers()
.forEach(player -> plugin.getHalter()
.halt(player.getUniqueId()));
final Component message = sender.name()
.append(Component.text(": Freezing all players"))
.color(NamedTextColor.AQUA);
Bukkit.broadcast(message);
sender.sendPlainMessage("All players have been halted.");
} else if (toggle.equalsIgnoreCase("off"))
{
plugin.getHalter()
.clear();
Bukkit.broadcast(Component.text("All players have been unfrozen!", NamedTextColor.AQUA));
sender.sendPlainMessage("All players have been unhalted.");
}
}
}
}

View File

@ -1,11 +1,11 @@
package me.totalfreedom.datura.cmd;
package fns.datura.cmd;
import me.totalfreedom.command.Commander;
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 me.totalfreedom.datura.Datura;
import fns.datura.Datura;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@ -13,6 +13,8 @@ import org.jetbrains.annotations.NotNull;
@Info(name = "locker", description = "Lock a player, preventing them from interacting with their game client.",
usage = "/locker <player> <on|off>", aliases = {"lock", "lockup"})
@Permissive(perm = "datura.locker")
@Completion(args = {"%player%"}, index = 0)
@Completion(args = {"on", "off"}, index = 1)
public final class LockerCommand extends Commander
{
public LockerCommand(final @NotNull Datura plugin)
@ -20,8 +22,6 @@ public final class LockerCommand extends Commander
super(plugin);
}
@Completion(args = {"%player%"}, index = 0)
@Completion(args = {"on", "off"}, index = 1)
@Subcommand(permission = "datura.locker", args = {Player.class, String.class})
public void lockPlayer(final CommandSender sender, final Player player, final String string)
{

View File

@ -0,0 +1,93 @@
package fns.datura.cmd;
import fns.datura.perms.PermissionNodeBuilder;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import fns.patchwork.security.Node;
import fns.patchwork.security.NodeType;
import fns.patchwork.security.PermissionHolder;
import fns.patchwork.user.User;
import java.time.Duration;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "manageuser", description = "Manage a user's permissions", usage = "/manageuser <username> <info | (add "
+ "| remove <permission>)>", aliases = {"mu", "userdata", "ud", "usermanager", "um"})
@Permissive(perm = "datura.manageuser")
@Completion(index = 0, args = {"%player%"})
@Completion(index = 1, args = {"info", "add", "remove"})
@Completion(index = 2, args = {"<permission>"})
public class ManageUserCommand extends Commander
{
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public ManageUserCommand(final @NotNull JavaPlugin plugin)
{
super(plugin);
}
@Subcommand(permission = "datura.manageuser", args = {Player.class, String.class, String.class, Long.class})
public void manageUser(final CommandSender sender, final Player player, final String addOrRemove,
final String permission, final long duration)
{
final PermissionHolder user = Shortcuts.getUser(player);
final Node node = new PermissionNodeBuilder().key(permission)
.type(NodeType.PERMISSION)
.expiry(Duration.ofMinutes(duration)
.getSeconds() + System.currentTimeMillis())
.build();
ifElse(addOrRemove, user, node);
}
@Subcommand(permission = "datura.manageuser", args = {Player.class, String.class, String.class})
public void manageUser(final CommandSender sender, final Player player, final String addOrRemove,
final String permission)
{
final PermissionHolder user = Shortcuts.getUser(player);
final Node node = new PermissionNodeBuilder().key(permission).type(NodeType.PERMISSION).build();
ifElse(addOrRemove, user, node);
}
@Subcommand(permission = "datura.manageuser", args = {Player.class, String.class})
public void userInfo(final CommandSender sender, final Player player, final String info)
{
final User user = Shortcuts.getUser(player);
if (info.equalsIgnoreCase("info"))
{
final StringBuilder permissions = new StringBuilder();
user.getEffectivePermissions().forEach(node -> permissions.append(node.getPermission()));
final String text = """
User: %s
Group: %s
Permissions: %s""".formatted(user.getName(), user.getUserData().getGroup(),
permissions.toString());
sender.sendPlainMessage(text);
}
}
private void ifElse(final String addOrRemove, final PermissionHolder user, final Node node)
{
if (addOrRemove.equalsIgnoreCase("add"))
{
user.addPermission(node);
}
else if (addOrRemove.equalsIgnoreCase("remove"))
{
user.removePermission(node);
}
}
}

View File

@ -0,0 +1,51 @@
package fns.datura.cmd;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "smite", description = "Smite a player.", usage = "/smite <player>", aliases = {"sm"})
@Permissive(perm = "datura.smite")
@Completion(index = 0, args = {"%player%"})
public class SmiteCommand extends Commander
{
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
public SmiteCommand(@NotNull final JavaPlugin plugin)
{
super(plugin);
}
@Subcommand(permission = "datura.smite", args = {Player.class})
public void smite(final CommandSender sender, final Player player)
{
final double size = 5D;
for (int i = 0; i < size * size * size; i++)
{
final double x = i % size;
final double y = (i / size) % size;
final double z = (i / size / size) % size;
final Location location = player.getLocation()
.clone()
.add(x - size / 2, y - size / 2, z - size / 2);
player.getWorld()
.strikeLightning(location);
}
}
}

View File

@ -1,7 +1,7 @@
package me.totalfreedom.datura.event;
package fns.datura.event;
import me.totalfreedom.event.FEvent;
import me.totalfreedom.user.UserData;
import fns.patchwork.event.FEvent;
import fns.patchwork.user.UserData;
public class UserDataUpdateEvent extends FEvent
{

View File

@ -0,0 +1,54 @@
package fns.datura.features;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class CommandSpy implements Listener
{
private final Set<UUID> commandWatchers;
public CommandSpy()
{
this.commandWatchers = new HashSet<>();
}
public void spy(final UUID uuid)
{
this.commandWatchers.add(uuid);
}
public void stop(final UUID uuid)
{
this.commandWatchers.remove(uuid);
}
public void clear()
{
this.commandWatchers.clear();
}
public boolean isSpying(final UUID uuid)
{
return this.commandWatchers.contains(uuid);
}
@EventHandler
public void commandProcess(final PlayerCommandPreprocessEvent event)
{
Bukkit.getOnlinePlayers().stream()
.filter(player -> isSpying(player.getUniqueId()))
.forEach(player -> player.sendMessage(Component.text(event.getPlayer().getName(), NamedTextColor.GRAY)
.append(Component.text(": ", NamedTextColor.GRAY))
.append(Component.text(event.getMessage(), NamedTextColor.GRAY))
)
);
}
}

View File

@ -0,0 +1,61 @@
package fns.datura.features;
import fns.patchwork.service.Service;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class Fuckoff extends Service
{
private final Map<UUID, Integer> players = new ConcurrentHashMap<>();
public Fuckoff()
{
super("fuckoff-service");
}
public void add(final Player player, final int radius)
{
players.put(player.getUniqueId(), radius);
}
public void remove(final Player player)
{
players.remove(player.getUniqueId());
}
@Override
public void tick()
{
for (final Map.Entry<UUID, Integer> entry : players.entrySet())
{
final var player = Bukkit.getPlayer(entry.getKey());
if (player == null)
{
players.remove(entry.getKey());
continue;
}
pushPlayers(player, entry.getValue());
}
}
private void pushPlayers(@NotNull final Player player, final int radius)
{
Bukkit.getOnlinePlayers()
.stream()
.filter(onlinePlayer -> onlinePlayer.getLocation()
.clone()
.distanceSquared(player.getLocation()) < Math.pow(radius, 2))
.forEach(onlinePlayer ->
onlinePlayer.setVelocity(player.getLocation()
.toVector()
.add(onlinePlayer.getLocation().toVector())
.normalize()
.multiply(radius)));
}
}

View File

@ -1,36 +1,32 @@
package me.totalfreedom.datura.perms;
package fns.datura.perms;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeType;
import fns.patchwork.security.Node;
import fns.patchwork.security.NodeType;
public class DefaultNodes
{
public static final Node OP = new PermissionNodeBuilder()
.key("freedom.master_key")
.value(true)
.expiry(-1)
.type(NodeType.PERMISSION)
.negated(false)
.wildcard(true)
.build();
public static final Node NON_OP = new PermissionNodeBuilder()
.key("freedom.default")
.value(true)
.expiry(-1)
.type(NodeType.PERMISSION)
.negated(false)
.wildcard(false)
.build();
public static final Node ALL = new PermissionNodeBuilder()
.key("*")
.value(true)
.expiry(-1)
.type(NodeType.PERMISSION)
.negated(false)
.wildcard(true)
.build();
public static final Node NONE = new PermissionNodeBuilder()
.key("freedom.none")
.value(true)
.expiry(-1)
.type(NodeType.PERMISSION)
.negated(false)
.wildcard(false)
.build();

View File

@ -1,8 +1,13 @@
package me.totalfreedom.datura.perms;
package fns.datura.perms;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.security.Group;
import me.totalfreedom.security.Node;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.security.Group;
import fns.patchwork.security.Node;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import net.kyori.adventure.text.Component;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
@ -11,11 +16,6 @@ import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class FreedomGroup implements Group
{
private final Component name;
@ -41,7 +41,7 @@ public class FreedomGroup implements Group
this.isDefault = isDefault;
this.isHidden = isHidden;
this.permissions = new HashSet<>();
this.attachment = new PermissionAttachment(CommonsBase.getInstance(), this);
this.attachment = new PermissionAttachment(Shortcuts.provideModule(Patchwork.class), this);
}
@Override
@ -114,7 +114,7 @@ public class FreedomGroup implements Group
.findFirst()
.orElse(null);
return node != null && node.value();
return node != null;
}
@Override
@ -127,7 +127,7 @@ public class FreedomGroup implements Group
.findFirst()
.orElse(null);
return node != null && node.value();
return node != null;
}
@Override
@ -139,7 +139,7 @@ public class FreedomGroup implements Group
.findFirst()
.orElse(null);
return node != null && node.value();
return node != null;
}
@Override
@ -152,7 +152,7 @@ public class FreedomGroup implements Group
.findFirst()
.orElse(null);
return node != null && node.value();
return node != null;
}
/**
@ -214,8 +214,7 @@ public class FreedomGroup implements Group
.map(n -> new PermissionAttachmentInfo(
this,
n.key(),
attachment,
n.value()))
attachment, true))
.collect(Collectors.toSet());
}
@ -228,7 +227,7 @@ public class FreedomGroup implements Group
.findFirst()
.orElse(null);
return node != null && node.value();
return node != null;
}
@Override

View File

@ -1,11 +1,18 @@
package me.totalfreedom.datura.perms;
package fns.datura.perms;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.datura.Datura;
import me.totalfreedom.datura.user.SimpleUserData;
import me.totalfreedom.security.Node;
import me.totalfreedom.user.User;
import me.totalfreedom.user.UserData;
import fns.datura.Datura;
import fns.datura.user.SimpleUserData;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Registration;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.security.Node;
import fns.patchwork.user.User;
import fns.patchwork.user.UserData;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -16,12 +23,6 @@ import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* The superinterface User extends PermissionHolder, which is an extension of
* {@link org.bukkit.permissions.Permissible}. This means that our permission data can be interchanged with other
@ -33,7 +34,7 @@ public class FreedomUser implements User
private final Set<Node> permissions;
private final Map<Node, PermissionAttachment> bukkitAttachments = new HashMap<>();
private final Component displayName;
private final String NOT_ONLINE = "Player is not online";
private static final String NOT_ONLINE = "Player is not online";
private final UserData userData;
public FreedomUser(final Player player)
@ -42,11 +43,7 @@ public class FreedomUser implements User
this.permissions = new HashSet<>();
this.displayName = player.displayName();
final Datura datura = CommonsBase.getInstance()
.getRegistrations()
.getModuleRegistry()
.getProvider(Datura.class)
.getModule();
final Datura datura = Shortcuts.provideModule(Datura.class);
UserData data = SimpleUserData.fromSQL(datura.getSQL(), uuid.toString());
@ -57,8 +54,7 @@ public class FreedomUser implements User
this.userData = data;
CommonsBase.getInstance()
.getRegistrations()
Registration
.getUserRegistry()
.registerUserData(this, userData);
}
@ -96,7 +92,8 @@ public class FreedomUser implements User
@Override
public boolean addPermission(final Node node)
{
final PermissionAttachment attachment = addAttachment(CommonsBase.getInstance(), node.key(), node.value());
final boolean value = !node.isTemporary() || node.isExpired();
final PermissionAttachment attachment = addAttachment(Shortcuts.provideModule(Patchwork.class), node.key(), value);
bukkitAttachments.put(node, attachment);
return permissions().add(node);
}

View File

@ -0,0 +1,39 @@
package fns.datura.perms;
import fns.patchwork.security.Node;
import fns.patchwork.security.NodeType;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
record PermissionNode(String key, long expiry, NodeType type, boolean wildcard) implements Node
{
@Override
public Permission bukkit()
{
return new Permission(key(), PermissionDefault.FALSE);
}
@Override
public boolean compare(final Node node)
{
return node.key().equalsIgnoreCase(key()) && node.type().equals(type()) && !node.isExpired();
}
@Override
public boolean isExpired()
{
if (!isTemporary())
{
return false;
}
return System.currentTimeMillis() > expiry();
}
@Override
public boolean isTemporary()
{
return expiry() > -1;
}
}

View File

@ -1,17 +1,15 @@
package me.totalfreedom.datura.perms;
package fns.datura.perms;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeBuilder;
import me.totalfreedom.security.NodeType;
import fns.patchwork.security.Node;
import fns.patchwork.security.NodeBuilder;
import fns.patchwork.security.NodeType;
public class PermissionNodeBuilder implements NodeBuilder
{
private String key = "freedom.default";
private boolean value = true;
private long expiry = -1;
private NodeType type = NodeType.PERMISSION;
private boolean wildcard = false;
private boolean negated = false;
@Override
public NodeBuilder key(final String key)
@ -20,13 +18,6 @@ public class PermissionNodeBuilder implements NodeBuilder
return this;
}
@Override
public NodeBuilder value(final boolean value)
{
this.value = value;
return this;
}
@Override
public NodeBuilder expiry(final long expiry)
{
@ -48,16 +39,9 @@ public class PermissionNodeBuilder implements NodeBuilder
return this;
}
@Override
public NodeBuilder negated(final boolean negated)
{
this.negated = negated;
return this;
}
@Override
public Node build()
{
return new PermissionNode(key, value, expiry, type, wildcard, negated);
return new PermissionNode(key, expiry, type, wildcard);
}
}

View File

@ -1,8 +1,17 @@
package me.totalfreedom.datura.punishment;
package fns.datura.punishment;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.service.Service;
import me.totalfreedom.utils.ShapeUtils;
import fns.datura.Datura;
import fns.patchwork.base.Patchwork;
import fns.patchwork.service.Service;
import fns.patchwork.utils.ShapeUtils;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.DoubleUnaryOperator;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@ -12,27 +21,20 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.DoubleUnaryOperator;
import javax.sound.midi.Patch;
public class Cager extends Service
{
private final Set<UUID> cagedPlayers;
private final Map<UUID, Location> cageLocations;
public Cager()
public Cager(final Datura datura)
{
super("cager-service");
this.cagedPlayers = new HashSet<>();
this.cageLocations = new HashMap<>();
Bukkit.getPluginManager()
.registerEvents(new CageListener(), CommonsBase.getInstance());
.registerEvents(new CageListener(), datura);
}
/**

View File

@ -1,12 +1,11 @@
package me.totalfreedom.datura.punishment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
package fns.datura.punishment;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
public class Halter implements Listener
{
@ -22,6 +21,16 @@ public class Halter implements Listener
this.haltedPlayers.add(uuid);
}
public void stop(final UUID uuid)
{
this.haltedPlayers.remove(uuid);
}
public void clear()
{
this.haltedPlayers.clear();
}
@EventHandler
public void playerMove(final PlayerMoveEvent event)
{

View File

@ -1,18 +1,18 @@
package me.totalfreedom.datura.punishment;
package fns.datura.punishment;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.service.Service;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.service.Service;
import java.util.HashSet;
import java.util.Set;
import java.util.SplittableRandom;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.SplittableRandom;
import java.util.UUID;
public class Locker extends Service
{
private final Set<UUID> lockedPlayers = new HashSet<>();
@ -35,7 +35,7 @@ public class Locker extends Service
@Override
public void tick()
{
lockedPlayers.removeIf(uuid -> !CommonsBase.getInstance()
lockedPlayers.removeIf(uuid -> !Shortcuts.provideModule(Patchwork.class)
.getServer()
.getOfflinePlayer(uuid)
.isOnline());

View File

@ -1,9 +1,9 @@
package me.totalfreedom.datura.sql;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.sql.SQL;
import me.totalfreedom.utils.container.Identity;
package fns.datura.sql;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.sql.SQL;
import fns.patchwork.utils.container.Identity;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@ -75,7 +75,7 @@ public class MySQL implements SQL
throw new CompletionException("Failed to prepare statement: "
+ query + "\n", ex);
}
}, CommonsBase.getInstance()
}, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync());
}
@ -92,7 +92,7 @@ public class MySQL implements SQL
throw new CompletionException("Failed to connect to the database: "
+ url.toString() + "\n", ex);
}
}, CommonsBase.getInstance()
}, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync());
}
@ -112,7 +112,7 @@ public class MySQL implements SQL
"Failed to retrieve a result set from query: "
+ query + "\n", ex);
}
}, CommonsBase.getInstance()
}, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync());
}
@ -131,7 +131,7 @@ public class MySQL implements SQL
throw new CompletionException("Failed to execute update: "
+ query + "\n", ex);
}
}, CommonsBase.getInstance()
}, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync());
}
@ -150,7 +150,7 @@ public class MySQL implements SQL
throw new CompletionException("Failed to execute statement: "
+ query + "\n", ex);
}
}, CommonsBase.getInstance()
}, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync());
}
@ -194,7 +194,7 @@ public class MySQL implements SQL
ex);
}
return null;
}, CommonsBase.getInstance()
}, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync());
}
@ -203,7 +203,7 @@ public class MySQL implements SQL
final String key, final Identity identity)
{
return executeUpdate("UPDATE ? SET ? = ? WHERE ? = ?", table, column, value, key, identity.getId())
.thenApplyAsync(result -> result > 0, CommonsBase.getInstance()
.thenApplyAsync(result -> result > 0, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync());
}
@ -211,7 +211,7 @@ public class MySQL implements SQL
public CompletableFuture<Boolean> deleteRow(final String table, final String key, final Identity identity)
{
return executeUpdate("DELETE FROM ? WHERE ? = ?", table, key, identity.getId())
.thenApplyAsync(result -> result > 0, CommonsBase.getInstance()
.thenApplyAsync(result -> result > 0, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync());
}

View File

@ -1,4 +1,4 @@
package me.totalfreedom.datura.sql;
package fns.datura.sql;
import com.google.errorprone.annotations.Immutable;

View File

@ -1,7 +1,7 @@
package me.totalfreedom.datura.user;
package fns.datura.user;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.EconomicEntityData;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.EconomicEntityData;
/**
* Represents the server's economy holder.

View File

@ -1,23 +1,25 @@
package me.totalfreedom.datura.user;
package fns.datura.user;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.datura.event.UserDataUpdateEvent;
import me.totalfreedom.datura.perms.FreedomUser;
import me.totalfreedom.security.Group;
import me.totalfreedom.sql.SQL;
import me.totalfreedom.user.User;
import me.totalfreedom.user.UserData;
import me.totalfreedom.utils.logging.FreedomLogger;
import fns.datura.event.UserDataUpdateEvent;
import fns.datura.perms.FreedomUser;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Registration;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.display.adminchat.AdminChatFormat;
import fns.patchwork.security.Group;
import fns.patchwork.sql.SQL;
import fns.patchwork.user.User;
import fns.patchwork.user.UserData;
import fns.patchwork.utils.logging.FreedomLogger;
import java.sql.SQLException;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
public class SimpleUserData implements UserData
{
private final UUID uuid;
@ -29,6 +31,8 @@ public class SimpleUserData implements UserData
private boolean canInteract;
private AtomicLong balance;
private boolean transactionsFrozen;
private boolean hasCustomACFormat = false;
private String customACFormat;
public SimpleUserData(final Player player)
{
@ -36,7 +40,7 @@ public class SimpleUserData implements UserData
this.username = player.getName();
this.user = new FreedomUser(player);
CommonsBase.getInstance()
Shortcuts.provideModule(Patchwork.class)
.getEventBus()
.addEvent(event);
}
@ -59,6 +63,7 @@ public class SimpleUserData implements UserData
this.canInteract = canInteract;
this.balance = new AtomicLong(balance);
this.transactionsFrozen = transactionsFrozen;
this.customACFormat = AdminChatFormat.DEFAULT.serialize();
}
public static SimpleUserData fromSQL(final SQL sql, final String uuid)
@ -81,8 +86,7 @@ public class SimpleUserData implements UserData
throw new IllegalStateException("Player should be online but they are not!");
final User user = new FreedomUser(player);
final Group group = CommonsBase.getInstance()
.getRegistrations()
final Group group = Registration
.getGroupRegistry()
.getGroup(g);
@ -113,7 +117,7 @@ public class SimpleUserData implements UserData
if (player == null) throw new IllegalStateException("Player should be online but they are not!");
return new SimpleUserData(player);
}, CommonsBase.getInstance()
}, Shortcuts.provideModule(Patchwork.class)
.getExecutor()
.getAsync())
.join();
@ -219,4 +223,23 @@ public class SimpleUserData implements UserData
{
return balance.addAndGet(-amount);
}
@Override
public boolean hasCustomACFormat()
{
return hasCustomACFormat;
}
@Override
public AdminChatFormat getCustomACFormat()
{
return AdminChatFormat.deserialize(customACFormat);
}
@Override
public void setCustomACFormat(final String format)
{
this.hasCustomACFormat = format.equals(AdminChatFormat.DEFAULT.serialize());
this.customACFormat = format;
}
}

View File

@ -1,60 +0,0 @@
package me.totalfreedom.datura;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.datura.punishment.Cager;
import me.totalfreedom.datura.punishment.Halter;
import me.totalfreedom.datura.punishment.Locker;
import me.totalfreedom.datura.sql.MySQL;
import me.totalfreedom.service.SubscriptionProvider;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
public class Datura extends JavaPlugin
{
private final MySQL sql = new MySQL("localhost", 3011, "master");
private final Halter halter = new Halter();
private final Locker locker = new Locker();
private final Cager cager = new Cager();
@Override
public void onEnable()
{
CommonsBase.getInstance()
.getRegistrations()
.getModuleRegistry()
.addModule(this);
CommonsBase.getInstance()
.getRegistrations()
.getServiceTaskRegistry()
.registerService(SubscriptionProvider.syncService(this, locker));
CommonsBase.getInstance()
.getRegistrations()
.getServiceTaskRegistry()
.registerService(SubscriptionProvider.syncService(this, cager));
Bukkit.getPluginManager()
.registerEvents(halter, this);
}
public MySQL getSQL()
{
return sql;
}
public Halter getHalter()
{
return halter;
}
public Locker getLocker()
{
return locker;
}
public Cager getCager()
{
return cager;
}
}

View File

@ -1,49 +0,0 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeType;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
record PermissionNode(String key,
boolean value,
long expiry,
NodeType type,
boolean wildcard) implements Node
{
@Override
public Permission bukkit()
{
return new Permission(key(),
value()
? PermissionDefault.TRUE
: PermissionDefault.FALSE);
}
@Override
public boolean compare(final Node node)
{
return node.key()
.equalsIgnoreCase(key())
&& node.value() == value()
&& node.type() == type();
}
@Override
public boolean isExpired()
{
if (!isTemporary())
{
return false;
}
return System.currentTimeMillis() > expiry();
}
@Override
public boolean isTemporary()
{
return expiry() > -1;
}
}

View File

@ -1,5 +1,6 @@
name: Datura
main: me.totalfreedom.datura.Datura
main: fns.datura.Datura
api-version: 1.20
version: 1.0.0
author: TotalFreedom
description: Data Manager for the Freedom Network Suite

View File

@ -0,0 +1,21 @@
package fns.fossil;
import fns.fossil.trail.Trailer;
import fns.patchwork.base.Registration;
import fns.patchwork.service.SubscriptionProvider;
import org.bukkit.plugin.java.JavaPlugin;
public class Fossil extends JavaPlugin
{
private final Trailer trailer = new Trailer();
@Override
public void onEnable()
{
Registration.getServiceTaskRegistry()
.registerService(
SubscriptionProvider.syncService(this, trailer));
Registration.getModuleRegistry()
.addModule(this);
}
}

View File

@ -1,12 +1,11 @@
package me.totalfreedom.fossil.bouncypads;
package fns.fossil.bouncypads;
import com.google.errorprone.annotations.Immutable;
import java.util.SplittableRandom;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.SplittableRandom;
/**
* Represents a bouncy pad. Has a velocity and a type.
*/

View File

@ -1,7 +1,12 @@
package me.totalfreedom.fossil.bouncypads;
package fns.fossil.bouncypads;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.fossil.Fossil;
import fns.fossil.Fossil;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Stream;
import fns.patchwork.base.Shortcuts;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Tag;
@ -12,11 +17,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Stream;
/**
* Holds all the active pads for each player, and also manages player pad interaction.
*/
@ -33,12 +33,7 @@ public class PadHolder implements Listener
public PadHolder()
{
Bukkit.getPluginManager()
.registerEvents(this, CommonsBase
.getInstance()
.getRegistrations()
.getModuleRegistry()
.getProvider(Fossil.class)
.getModule());
.registerEvents(this, Shortcuts.provideModule(Fossil.class));
}
/**

View File

@ -1,4 +1,4 @@
package me.totalfreedom.fossil.bouncypads;
package fns.fossil.bouncypads;
import org.bukkit.block.BlockFace;

View File

@ -19,13 +19,13 @@
* THE SOFTWARE.
*/
package me.totalfreedom.fossil.cmd;
package fns.fossil.cmd;
import me.totalfreedom.command.Commander;
import me.totalfreedom.command.annotation.Base;
import me.totalfreedom.command.annotation.Info;
import me.totalfreedom.command.annotation.Permissive;
import me.totalfreedom.utils.kyori.FreedomMiniMessage;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Base;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.utils.kyori.FreedomMiniMessage;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
@ -46,8 +46,10 @@ public class CakeCommand extends Commander
@Base
public void broadcastCake(final CommandSender sender)
{
Bukkit.broadcast(FreedomMiniMessage.deserialize(true,
"<rainbow>But there's no sense crying over every mistake. You just keep on trying till you run out of " +
Bukkit.getServer().sendMessage(FreedomMiniMessage.deserialize(true,
"<rainbow>But there's no sense crying over " +
"every mistake. You just keep on trying " +
"till you run out of " +
"cake.</rainbow>"));
final ItemStack stack = new ItemStack(Material.CAKE, 1);

View File

@ -1,9 +1,9 @@
package me.totalfreedom.fossil.economy;
package fns.fossil.economy;
import me.totalfreedom.economy.CompletedTransaction;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.Transaction;
import me.totalfreedom.economy.TransactionResult;
import fns.patchwork.economy.CompletedTransaction;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.Transaction;
import fns.patchwork.economy.TransactionResult;
public class SimpleCompletedTransaction implements CompletedTransaction
{

View File

@ -1,9 +1,9 @@
package me.totalfreedom.fossil.economy;
package fns.fossil.economy;
import me.totalfreedom.economy.CompletedTransaction;
import me.totalfreedom.economy.MutableTransaction;
import me.totalfreedom.economy.TransactionLogger;
import me.totalfreedom.economy.Transactor;
import fns.patchwork.economy.CompletedTransaction;
import fns.patchwork.economy.MutableTransaction;
import fns.patchwork.economy.TransactionLogger;
import fns.patchwork.economy.Transactor;
public class SimpleLoggedTransactor implements Transactor
{

View File

@ -1,7 +1,7 @@
package me.totalfreedom.fossil.economy;
package fns.fossil.economy;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.MutableTransaction;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.MutableTransaction;
public class SimpleMutableTransaction extends SimpleTransaction implements MutableTransaction
{

View File

@ -1,8 +1,7 @@
package me.totalfreedom.fossil.economy;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.Transaction;
package fns.fossil.economy;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.Transaction;
import java.util.concurrent.atomic.AtomicLong;
public class SimpleTransaction implements Transaction

View File

@ -1,11 +1,11 @@
package me.totalfreedom.fossil.economy;
package fns.fossil.economy;
import me.totalfreedom.audience.MutableAudienceForwarder;
import me.totalfreedom.economy.CompletedTransaction;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.TransactionLogger;
import me.totalfreedom.economy.TransactionResult;
import me.totalfreedom.utils.logging.FreedomLogger;
import fns.patchwork.audience.MutableAudienceForwarder;
import fns.patchwork.economy.CompletedTransaction;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.TransactionLogger;
import fns.patchwork.economy.TransactionResult;
import fns.patchwork.utils.logging.FreedomLogger;
import net.kyori.adventure.text.Component;
public class SimpleTransactionLogger implements TransactionLogger

View File

@ -1,6 +1,6 @@
package me.totalfreedom.fossil.economy;
package fns.fossil.economy;
import me.totalfreedom.economy.TransactionResult;
import fns.patchwork.economy.TransactionResult;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
@ -15,20 +15,20 @@ public class SimpleTransactionResult implements TransactionResult
"The source has an insufficient balance to carry out this transaction.", false);
private final String message;
private final Component component;
private final boolean successful;
private final boolean isSuccessful;
public SimpleTransactionResult(final String message, final boolean successful)
public SimpleTransactionResult(final String message, final boolean isSuccessful)
{
this(message, Component.text(message, successful
this(message, Component.text(message, isSuccessful
? NamedTextColor.GREEN
: NamedTextColor.RED), successful);
: NamedTextColor.RED), isSuccessful);
}
public SimpleTransactionResult(final String message, final Component component, final boolean successful)
public SimpleTransactionResult(final String message, final Component component, final boolean isSuccessful)
{
this.message = message;
this.component = component;
this.successful = successful;
this.isSuccessful = isSuccessful;
}
@Override
@ -40,7 +40,7 @@ public class SimpleTransactionResult implements TransactionResult
@Override
public boolean isSuccessful()
{
return successful;
return isSuccessful;
}
@Override

View File

@ -1,10 +1,10 @@
package me.totalfreedom.fossil.economy;
package fns.fossil.economy;
import me.totalfreedom.economy.CompletedTransaction;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.EconomicEntityData;
import me.totalfreedom.economy.MutableTransaction;
import me.totalfreedom.economy.Transactor;
import fns.patchwork.economy.CompletedTransaction;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.EconomicEntityData;
import fns.patchwork.economy.MutableTransaction;
import fns.patchwork.economy.Transactor;
public class SimpleTransactor implements Transactor
{

View File

@ -1,4 +1,4 @@
package me.totalfreedom.fossil.items;
package fns.fossil.items;
import org.bukkit.Location;
import org.bukkit.Material;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.fossil.items;
package fns.fossil.items;
import org.bukkit.Material;
import org.bukkit.entity.Entity;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.fossil.items;
package fns.fossil.items;
import org.bukkit.Material;
import org.bukkit.entity.Entity;

View File

@ -1,15 +1,13 @@
package me.totalfreedom.fossil.reactions;
package fns.fossil.reactions;
import me.totalfreedom.display.BossBarDisplay;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.shop.Reaction;
import me.totalfreedom.shop.ReactionType;
import fns.patchwork.display.BossBarDisplay;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.shop.Reaction;
import fns.patchwork.shop.ReactionType;
import java.util.SplittableRandom;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.bossbar.BossBar;
import java.util.SplittableRandom;
import java.util.function.Consumer;
/**
* Represents a single chat reaction that can be performed by a player.
*/
@ -29,12 +27,6 @@ public final class CopyCatReaction extends Reaction
return reward;
}
@Override
public void onReact(final Consumer<EconomicEntity> entity)
{
entity.accept(null);
}
@Override
public void display(final Audience audience)
{
@ -44,6 +36,12 @@ public final class CopyCatReaction extends Reaction
.build();
}
@Override
public void onReact(final EconomicEntity entity)
{
//
}
public String getRandomCharacterString()
{
final SplittableRandom random = new SplittableRandom();

View File

@ -0,0 +1,5 @@
package fns.fossil.shop;
public class Shoppe
{
}

View File

@ -1,6 +1,6 @@
package me.totalfreedom.fossil.shop.menus;
package fns.fossil.shop.menus;
import me.totalfreedom.display.AbstractMenu;
import fns.patchwork.display.AbstractMenu;
public final class MainMenu extends AbstractMenu
{

View File

@ -1,8 +1,7 @@
package me.totalfreedom.fossil.trail;
import me.totalfreedom.particle.Trail;
import me.totalfreedom.service.Service;
package fns.fossil.trail;
import fns.patchwork.particle.Trail;
import fns.patchwork.service.Service;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,6 +1,6 @@
package me.totalfreedom.fossil.trail.types;
package fns.fossil.trail.types;
import me.totalfreedom.particle.TrailType;
import fns.patchwork.particle.TrailType;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;

View File

@ -1,6 +1,6 @@
package me.totalfreedom.fossil.trail.types;
package fns.fossil.trail.types;
import me.totalfreedom.particle.TrailType;
import fns.patchwork.particle.TrailType;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;

View File

@ -1,6 +1,6 @@
package me.totalfreedom.fossil.trail.types;
package fns.fossil.trail.types;
import me.totalfreedom.particle.TrailType;
import fns.patchwork.particle.TrailType;
import org.bukkit.Location;
import org.bukkit.entity.Player;

View File

@ -1,14 +1,13 @@
package me.totalfreedom.fossil.trail.types;
package fns.fossil.trail.types;
import me.totalfreedom.particle.TrailType;
import me.totalfreedom.utils.InterpolationUtils;
import fns.patchwork.particle.TrailType;
import fns.patchwork.utils.InterpolationUtils;
import java.util.Iterator;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
import java.util.Iterator;
public final class RainbowTrail extends SimpleTrail
{
private Iterator<Color> currentColor;

View File

@ -1,7 +1,9 @@
package me.totalfreedom.fossil.trail.types;
package fns.fossil.trail.types;
import me.totalfreedom.particle.Trail;
import me.totalfreedom.particle.TrailType;
import fns.patchwork.particle.Trail;
import fns.patchwork.particle.TrailType;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.OfflinePlayer;
@ -9,9 +11,6 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.UUID;
public abstract class SimpleTrail implements Trail
{
private final UUID associatedPlayerUUID;

View File

@ -1,6 +1,6 @@
package me.totalfreedom.fossil.trail.types;
package fns.fossil.trail.types;
import me.totalfreedom.particle.TrailType;
import fns.patchwork.particle.TrailType;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.fossil.trail.types;
package fns.fossil.trail.types;
import org.bukkit.entity.Player;

View File

@ -1,25 +0,0 @@
package me.totalfreedom.fossil;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.base.Registration;
import me.totalfreedom.fossil.trail.Trailer;
import me.totalfreedom.service.SubscriptionProvider;
import org.bukkit.plugin.java.JavaPlugin;
public class Fossil extends JavaPlugin
{
private final Trailer trailer = new Trailer();
private final Registration registration = CommonsBase.getInstance()
.getRegistrations();
@Override
public void onEnable()
{
registration.getModuleRegistry()
.addModule(this);
registration.getServiceTaskRegistry()
.registerService(
SubscriptionProvider.syncService(this, trailer));
}
}

View File

@ -1,5 +0,0 @@
package me.totalfreedom.fossil.shop;
public class Shoppe
{
}

View File

@ -1,6 +1,7 @@
name: Fossil
version: 1.0
main: me.totalfreedom.fossil.Fossil
main: fns.fossil.Fossil
api-version: 1.20
author: TotalFreedom
description: The Fun Module for the Freedom Network.
depend:

View File

@ -1,6 +1,7 @@
package me.totalfreedom.api;
package fns.patchwork.api;
import me.totalfreedom.provider.ContextProvider;
import fns.patchwork.provider.ContextProvider;
import java.util.function.Function;
import net.kyori.adventure.text.Component;
import org.bukkit.Location;
import org.bukkit.World;
@ -12,8 +13,6 @@ import org.bukkit.event.block.Action;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
/**
* Represents an object context. This class is a simple generic type wrapper that can be used to ensure data types. This
* class is also used to provide a simple way to map data types.

View File

@ -1,4 +1,4 @@
package me.totalfreedom.api;
package fns.patchwork.api;
/**
* Interpolates a range of values and returns the results in a {@link Double} array.

View File

@ -1,4 +1,4 @@
package me.totalfreedom.api;
package fns.patchwork.api;
/**
* This interface represents a Serializable object. Objects which require custom serialization and cannot simply

View File

@ -1,5 +1,9 @@
package me.totalfreedom.audience;
package fns.patchwork.audience;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.chat.ChatType;
@ -13,13 +17,8 @@ import net.kyori.adventure.title.Title;
import net.kyori.adventure.title.TitlePart;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
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 &
* A replacement for {@link net.kyori.adventure.audience.ForwardingAudience} that allows for audiences to be removed and
* added at will. Not thread safe.
* <p>
* This is intended for use in toggleable logging systems, for example, potion spy.

View File

@ -1,61 +1,59 @@
package me.totalfreedom.base;
package fns.patchwork.base;
import me.totalfreedom.event.EventBus;
import me.totalfreedom.service.FreedomExecutor;
import me.totalfreedom.service.SubscriptionProvider;
import fns.patchwork.display.adminchat.AdminChatDisplay;
import fns.patchwork.event.EventBus;
import fns.patchwork.service.FreedomExecutor;
import fns.patchwork.service.SubscriptionProvider;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
/**
* The base class for Patchwork.
*/
public class CommonsBase extends JavaPlugin
public class Patchwork extends JavaPlugin
{
/**
* The {@link EventBus} for this plugin.
*/
private final EventBus eventBus = new EventBus(this);
/**
* The {@link Registration} object for this plugin.
*/
private final Registration registration = new Registration();
private EventBus eventBus;
/**
* The {@link FreedomExecutor} for this plugin.
*/
private final FreedomExecutor executor = new FreedomExecutor();
private FreedomExecutor executor;
/**
* Provides this plugin instance through a safe static method. This is effectively the same thing as using
* {@link JavaPlugin#getPlugin(Class)}
*
* @return the plugin instance
* The {@link AdminChatDisplay} for this plugin.
*/
public static CommonsBase getInstance()
{
return JavaPlugin.getPlugin(CommonsBase.class);
}
private AdminChatDisplay acdisplay;
@Override
public void onDisable()
{
Bukkit.getScheduler()
.runTaskLater(this, () -> getRegistrations()
.runTaskLater(this, () -> Registration
.getServiceTaskRegistry()
.stopAllServices(), 1L);
getRegistrations().getServiceTaskRegistry()
Registration.getServiceTaskRegistry()
.unregisterService(EventBus.class);
}
@Override
public void onEnable()
{
getRegistrations().getServiceTaskRegistry()
eventBus = new EventBus(this);
executor = new FreedomExecutor(this);
acdisplay = new AdminChatDisplay(this);
Registration.getServiceTaskRegistry()
.registerService(SubscriptionProvider.asyncService(this, eventBus));
getExecutor().getSync()
.execute(() -> getRegistrations()
.execute(() -> Registration
.getServiceTaskRegistry()
.startAllServices());
Registration.getModuleRegistry().addModule(this);
}
/**
@ -68,17 +66,6 @@ public class CommonsBase extends JavaPlugin
return executor;
}
/**
* Get's the Registration object for this plugin. This object contains every registry class for the various features
* provided by this plugin.
*
* @return the Registration object
*/
public Registration getRegistrations()
{
return registration;
}
/**
* Gets the {@link EventBus} for this plugin. The EventBus is used to register and listen to custom events provided
* by Freedom Network Suite.
@ -89,4 +76,15 @@ public class CommonsBase extends JavaPlugin
{
return eventBus;
}
/**
* Gets the {@link AdminChatDisplay} for this plugin. The AdminChatDisplay is used to display messages sent in
* adminchat.
*
* @return the {@link AdminChatDisplay}
*/
public AdminChatDisplay getAdminChatDisplay()
{
return acdisplay;
}
}

View File

@ -0,0 +1,95 @@
package fns.patchwork.base;
import fns.patchwork.data.ConfigRegistry;
import fns.patchwork.data.EventRegistry;
import fns.patchwork.data.GroupRegistry;
import fns.patchwork.data.ModuleRegistry;
import fns.patchwork.data.ServiceTaskRegistry;
import fns.patchwork.data.UserRegistry;
/**
* This class is a holder for each registry in the data package.
* <br>
* Registries such as {@link ModuleRegistry} and {@link ServiceTaskRegistry} can be found as final objects in this
* class.
*/
public class Registration
{
/**
* The {@link EventRegistry}
*/
private static final EventRegistry eventRegistry = new EventRegistry();
/**
* The {@link UserRegistry}
*/
private static final UserRegistry userRegistry = new UserRegistry();
/**
* The {@link ServiceTaskRegistry}
*/
private static final ServiceTaskRegistry serviceTaskRegistry = new ServiceTaskRegistry();
/**
* The {@link ModuleRegistry}
*/
private static final ModuleRegistry moduleRegistry = new ModuleRegistry();
/**
* The {@link GroupRegistry}
*/
private static final GroupRegistry groupRegistry = new GroupRegistry();
/**
* The {@link ConfigRegistry}
*/
private static final ConfigRegistry configRegistry = new ConfigRegistry();
private Registration()
{
throw new AssertionError();
}
/**
* @return The {@link ModuleRegistry}
*/
public static ModuleRegistry getModuleRegistry()
{
return moduleRegistry;
}
/**
* @return The {@link EventRegistry}
*/
public static EventRegistry getEventRegistry()
{
return eventRegistry;
}
/**
* @return The {@link UserRegistry}
*/
public static UserRegistry getUserRegistry()
{
return userRegistry;
}
/**
* @return The {@link ServiceTaskRegistry}
*/
public static ServiceTaskRegistry getServiceTaskRegistry()
{
return serviceTaskRegistry;
}
/**
* @return The {@link GroupRegistry}
*/
public static GroupRegistry getGroupRegistry()
{
return groupRegistry;
}
/**
* @return The {@link ConfigRegistry}
*/
public static ConfigRegistry getConfigRegistry()
{
return configRegistry;
}
}

View File

@ -0,0 +1,26 @@
package fns.patchwork.base;
import fns.patchwork.user.User;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public final class Shortcuts
{
private Shortcuts()
{
throw new AssertionError();
}
public static <T extends JavaPlugin> T provideModule(final Class<T> pluginClass)
{
return Registration.getModuleRegistry()
.getProvider(pluginClass)
.getModule();
}
public static User getUser(final Player player)
{
return Registration.getUserRegistry()
.getUser(player);
}
}

View File

@ -1,33 +1,31 @@
package me.totalfreedom.command;
package fns.patchwork.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.logging.FreedomLogger;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Subcommand;
import fns.patchwork.provider.ContextProvider;
import fns.patchwork.utils.logging.FreedomLogger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Location;
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;
/**
* This class is acts as a delegate between our custom command implementation and the Bukkit API.
* <br>
* This class is not meant to be used directly, and is only public to allow for the Bukkit API to access it. As a
* result, this file will remain undocumented.
* <span color=#ff0000>
* <br>
* <br>
* This class is not thread-safe.
* <br>
@ -36,7 +34,6 @@ import java.util.Set;
* This class is not meant to be instantiated.
* <br>
* This class is not meant to be used outside Patchwork.
* </span>
*/
public final class BukkitDelegate extends Command implements PluginIdentifiableCommand
{
@ -69,7 +66,7 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
@NotNull final String commandLabel,
@NotNull final String[] args)
{
if (sender instanceof ConsoleCommandSender && noConsole)
if (!(sender instanceof Player) && noConsole)
{
sender.sendMessage(Component.text("This command can only be run by players."));
return true;
@ -100,10 +97,19 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
if (command.getBaseMethod() != null)
{
try
{
if (noConsole)
{
command.getBaseMethod()
.invoke(command, (Player) sender);
}
else
{
command.getBaseMethod()
.invoke(command, sender);
} catch (Exception ex)
}
}
catch (Exception ex)
{
FreedomLogger.getLogger("Patchwork")
.error(ex);
@ -120,7 +126,7 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
final Subcommand node)
{
final Class<?>[] argTypes = node.args();
if (argTypes.length != args.length)
if (argTypes.length > args.length)
return;
final Object[] objects = new Object[argTypes.length + 1];
@ -130,18 +136,52 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
final Class<?> argType = argTypes[i];
final String arg = args[i];
if (argType == String.class)
if (argType.equals(String.class))
{
if (i == argTypes.length - 1)
{
final String[] reasonArgs = Arrays.copyOfRange(args, i, args.length - 1);
final String reason = String.join(" ", reasonArgs);
objects[i] = reason;
}
else
{
continue;
}
}
final Context<?> context = () -> provider.fromString(arg, argType);
objects[i] = context.get();
if (argType.equals(Location.class))
{
final String[] locationArgs = Arrays.copyOfRange(args, i, i + 3);
final String location = String.join(" ", locationArgs);
objects[i] = location;
}
final Object obj = provider.fromString(arg, argType);
if (obj == null)
{
FreedomLogger.getLogger("Datura")
.error("Failed to parse argument " + arg + " for type " + argType.getName());
return;
}
objects[i] = obj;
}
try
{
if (noConsole)
{
command.getSubcommands()
.get(node)
.invoke(command, (Player) sender, objects);
}
else
{
command.getSubcommands()
.get(node)
.invoke(command, sender, objects);
} catch (Exception ex)
}
}
catch (Exception ex)
{
FreedomLogger.getLogger("Patchwork")
.error(ex);
@ -183,7 +223,7 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
"7",
"8",
"9"));
case "%location%" -> results.add("world,x,y,z");
case "%location%" -> results.add("world x y z");
default -> results.add(p);
}
}

View File

@ -1,4 +1,4 @@
package me.totalfreedom.command;
package fns.patchwork.command;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandMap;

View File

@ -1,14 +1,10 @@
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;
package fns.patchwork.command;
import fns.patchwork.command.annotation.Base;
import fns.patchwork.command.annotation.Completion;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.command.annotation.Subcommand;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
@ -16,6 +12,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* This is the base command class which should be extended when creating a new command. Commands must be annotated with
@ -28,9 +27,7 @@ import java.util.stream.Stream;
* You are allowed to have as many methods as you want which are annotated with the {@link Subcommand} annotation. These
* methods will be called when the command is executed with the specified subcommand.
* <br>
* You are also allowed to use multiple {@link Completion} annotations per method to define multiple tab completions for
* a single subcommand. This would be useful in the case where you would like to include specific completion cases, but
* also support basic String completion cases.
* You are also allowed to use multiple {@link Completion} annotations per class to define the tab completions for each method.
* <br>
* When creating {@link Completion} annotations, you only need to register arguments a single time per class. For more
* information, see {@link Subcommand}.

View File

@ -1,4 +1,4 @@
package me.totalfreedom.command.annotation;
package fns.patchwork.command.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.command.annotation;
package fns.patchwork.command.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
@ -12,7 +12,7 @@ import java.lang.annotation.Target;
* This will register at class level, and does not retain method information. As a result, you only need to register the
* arguments a single time, and it will always be used in tab completions.
*/
@Target(ElementType.METHOD)
@Target(ElementType.TYPE)
@Repeatable(Completions.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface Completion

View File

@ -1,4 +1,4 @@
package me.totalfreedom.command.annotation;
package fns.patchwork.command.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -8,10 +8,10 @@ import java.lang.annotation.Target;
/**
* A marker interface which represents a holder for multiple {@link Completion} annotations.
* <br>
* <u>This interface is <span color=#ff0000><b>NOT</b></span> intended for implementation and should
* <span color=#ff0000><b>NOT</b></span> be used.</u>
* <u>This interface is <b>NOT</b> intended for implementation and should
* <b>NOT</b> be used.</u>
*/
@Target(ElementType.METHOD)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Completions
{

View File

@ -1,4 +1,4 @@
package me.totalfreedom.command.annotation;
package fns.patchwork.command.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.command.annotation;
package fns.patchwork.command.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

View File

@ -1,8 +1,7 @@
package me.totalfreedom.command.annotation;
import me.totalfreedom.command.CommandHandler;
import me.totalfreedom.provider.ContextProvider;
package fns.patchwork.command.annotation;
import fns.patchwork.command.CommandHandler;
import fns.patchwork.provider.ContextProvider;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@ -10,19 +9,26 @@ import java.lang.annotation.Target;
/**
* This annotation should be used to mark methods as subcommand methods. Subcommand methods can have custom arguments
* (current supported arguments can be found in the {@link ContextProvider}), and can also have a custom permission.
* These subcommands can also be annotated with {@link Completions} to provide tab completions for the subcommand. The
* subcommand method must be public, and must be in a class that is registered with the {@link CommandHandler}.
* <br>
* <i>(current supported arguments can be found in the {@link ContextProvider})</i>, and can also have a custom
* permission. These subcommands can also be annotated with {@link Completions} to provide tab completions for the
* subcommand. The subcommand method must be public, and must be in a class that is registered with the
* {@link CommandHandler}.
* <p>
* Tab completions with the {@link Completions} annotation are only supported for subcommands. When registering
* completions, you only need to define the completion arguments a single time. If there are other methods which
* function as optional additional arguments for the subcommand, the previously registered arguments will still be
* present when the user does their tab completion.
* <br>
* <p>
* For example, if you have a subcommand method with the arguments {@code (Player, String)}, and another method which
* has the arguments {@code (Player, String, String)}, the tab completions for the second method will still have the
* {@code Player} and {@code String} arguments registered from the first method. You will only need to provide a
* {@link Completion} for the additional 3rd argument.
* <p>
* Additionally, if the final argument is a String object, the BukkitDelegate will automatically append any additional
* arguments to the end of the String. For example, if you have a subcommand method with the arguments
* {@code (Player, String)}, and the user executes the command with the arguments {@code /command playerName arg2 arg3},
* the {@code String} argument will be {@code "arg2 arg3"}. This allows for us to use a String at the end of our
* subcommand arguments to allow for the user to input a reason.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)

View File

@ -1,8 +1,7 @@
package me.totalfreedom.config;
import me.totalfreedom.api.Context;
import me.totalfreedom.provider.ContextProvider;
package fns.patchwork.config;
import fns.patchwork.api.Context;
import fns.patchwork.provider.ContextProvider;
import java.io.File;
import java.io.IOException;
import java.util.List;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.config;
package fns.patchwork.config;
public final class YamlWrapper
{

View File

@ -1,7 +1,6 @@
package me.totalfreedom.data;
import me.totalfreedom.config.Configuration;
package fns.patchwork.data;
import fns.patchwork.config.Configuration;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,8 +1,7 @@
package me.totalfreedom.data;
import me.totalfreedom.event.FEvent;
import me.totalfreedom.provider.EventProvider;
package fns.patchwork.data;
import fns.patchwork.event.FEvent;
import fns.patchwork.provider.EventProvider;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,10 +1,9 @@
package me.totalfreedom.data;
import me.totalfreedom.security.Group;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
package fns.patchwork.data;
import fns.patchwork.security.Group;
import java.util.ArrayList;
import java.util.List;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
/**
* A registry for {@link Group}s.

View File

@ -1,10 +1,9 @@
package me.totalfreedom.data;
import me.totalfreedom.provider.ModuleProvider;
import org.bukkit.plugin.java.JavaPlugin;
package fns.patchwork.data;
import fns.patchwork.provider.ModuleProvider;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.plugin.java.JavaPlugin;
/**
* A registry for modules.

View File

@ -1,14 +1,13 @@
package me.totalfreedom.data;
import me.totalfreedom.service.Service;
import me.totalfreedom.service.ServiceSubscription;
import me.totalfreedom.service.SubscriptionProvider;
import me.totalfreedom.service.Task;
import me.totalfreedom.service.TaskSubscription;
import org.jetbrains.annotations.Nullable;
package fns.patchwork.data;
import fns.patchwork.service.Service;
import fns.patchwork.service.ServiceSubscription;
import fns.patchwork.service.SubscriptionProvider;
import fns.patchwork.service.Task;
import fns.patchwork.service.TaskSubscription;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.Nullable;
/**
* A registry for all services and tasks registered with Patchwork.
@ -284,7 +283,7 @@ public class ServiceTaskRegistry
* <br>
* <i>The service should have been registered previously as a <b>ServiceSubscription</b></i>.
*
* @param service The service you are trying to unregister.
* @param clazz The service you are trying to unregister.
* @see #registerService(ServiceSubscription)
* @see ServiceSubscription
*/

View File

@ -1,11 +1,10 @@
package me.totalfreedom.data;
import me.totalfreedom.user.User;
import me.totalfreedom.user.UserData;
import org.bukkit.entity.Player;
package fns.patchwork.data;
import fns.patchwork.user.User;
import fns.patchwork.user.UserData;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.entity.Player;
/**
* A registry for {@link UserData} objects.

View File

@ -1,5 +1,10 @@
package me.totalfreedom.display;
package fns.patchwork.display;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -9,12 +14,6 @@ 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;
/**
* Represents a menu that can be opened by a player.
*/

View File

@ -1,5 +1,8 @@
package me.totalfreedom.display;
package fns.patchwork.display;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import net.kyori.adventure.bossbar.BossBar;
@ -7,10 +10,6 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import org.jetbrains.annotations.Range;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* This class is a wrapper for {@link BossBar} objects. It provides some handy methods for changing the boss bar's
* properties, displaying the bar to {@link Audience}s, and a {@link BossBarBuilder} to easily create new boss bars.

View File

@ -1,9 +1,8 @@
package me.totalfreedom.display;
import me.totalfreedom.service.Task;
import org.bukkit.Bukkit;
package fns.patchwork.display;
import fns.patchwork.service.Task;
import java.time.Duration;
import org.bukkit.Bukkit;
public class BossBarTimer extends Task
{

View File

@ -1,4 +1,4 @@
package me.totalfreedom.display;
package fns.patchwork.display;
import org.bukkit.entity.Player;

View File

@ -1,5 +1,9 @@
package me.totalfreedom.display;
package fns.patchwork.display;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
@ -10,11 +14,6 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
/**
* A class that represents an inventory that can be displayed to players. This class also represents the inventory
* holder which contains the inventory.

View File

@ -1,6 +1,6 @@
package me.totalfreedom.display;
package fns.patchwork.display;
import me.totalfreedom.utils.kyori.FreedomAdventure;
import fns.patchwork.utils.kyori.FreedomAdventure;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
@ -78,6 +78,7 @@ public class DisplayableView extends InventoryView
}
@Override
@Deprecated(forRemoval = true, since = "1.16")
public @NotNull String getTitle()
{
return title;

View File

@ -1,13 +1,12 @@
package me.totalfreedom.display;
package fns.patchwork.display;
import java.time.Duration;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.title.Title;
import java.time.Duration;
/**
* A wrapper class for {@link Title}s that allows for easy display to an {@link Audience}.
*/

View File

@ -0,0 +1,119 @@
package fns.patchwork.display.adminchat;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
public class ACFormatBuilder
{
private char openTag = '[';
private char closeTag = ']';
private TextColor prefixColor = NamedTextColor.DARK_RED;
private TextColor bracketColor = NamedTextColor.WHITE;
private TextColor nameColor = NamedTextColor.AQUA;
private TextColor rankColor = NamedTextColor.GOLD;
private String prefix = "Admin";
private String chatSplitter = ">>";
private ACFormatBuilder()
{
}
public static ACFormatBuilder format()
{
return new ACFormatBuilder();
}
public ACFormatBuilder openBracket(final char openTag)
{
this.openTag = openTag;
return this;
}
public ACFormatBuilder closeBracket(final char closeTag)
{
this.closeTag = closeTag;
return this;
}
public ACFormatBuilder prefixColor(final TextColor prefixColor)
{
this.prefixColor = prefixColor;
return this;
}
public ACFormatBuilder bracketColor(final TextColor bracketColor)
{
this.bracketColor = bracketColor;
return this;
}
public ACFormatBuilder prefix(final String prefix)
{
this.prefix = prefix;
return this;
}
public ACFormatBuilder chatSplitter(final String chatSplitter)
{
this.chatSplitter = chatSplitter;
return this;
}
public ACFormatBuilder nameColor(final TextColor nameColor)
{
this.nameColor = nameColor;
return this;
}
public ACFormatBuilder rankColor(final TextColor rankColor)
{
this.rankColor = rankColor;
return this;
}
String openBracket()
{
return String.valueOf(openTag);
}
String closeBracket()
{
return String.valueOf(closeTag);
}
TextColor prefixColor()
{
return prefixColor;
}
TextColor bracketColor()
{
return bracketColor;
}
TextColor nameColor()
{
return nameColor;
}
TextColor rankColor()
{
return rankColor;
}
String prefix()
{
return prefix;
}
String chatSplitter()
{
return chatSplitter;
}
public AdminChatFormat build()
{
return new AdminChatFormat(this);
}
}

View File

@ -0,0 +1,140 @@
package fns.patchwork.display.adminchat;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Registration;
import fns.patchwork.base.Shortcuts;
import fns.patchwork.security.Groups;
import fns.patchwork.user.UserData;
import io.papermc.paper.event.player.AsyncChatEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
public class AdminChatDisplay
{
protected static final String ACPERM = "patchwork.adminchat";
private final Map<UUID, AdminChatFormat> adminChatFormat = new HashMap<>();
private final Set<UUID> toggledChat = new HashSet<>();
public AdminChatDisplay(final Patchwork patchwork)
{
new ACListener(this, patchwork);
}
public void addPlayer(final Player player, final AdminChatFormat format)
{
adminChatFormat.put(player.getUniqueId(), format);
}
public void removePlayer(final Player player)
{
adminChatFormat.remove(player.getUniqueId());
}
public boolean hasPlayer(final Player player)
{
return adminChatFormat.containsKey(player.getUniqueId());
}
public void updateFormat(final Player player, final AdminChatFormat newFormat)
{
adminChatFormat.put(player.getUniqueId(), newFormat);
}
public AdminChatFormat getFormat(final Player player)
{
return adminChatFormat.get(player.getUniqueId());
}
public Set<UUID> getPlayers()
{
return adminChatFormat.keySet();
}
public Map<UUID, AdminChatFormat> getAdminChatFormat()
{
return adminChatFormat;
}
public boolean isToggled(final Player player)
{
return toggledChat.contains(player.getUniqueId());
}
public void toggleChat(final Player player)
{
if (toggledChat.contains(player.getUniqueId()))
{
toggledChat.remove(player.getUniqueId());
} else
{
toggledChat.add(player.getUniqueId());
}
}
public void adminChatMessage(final CommandSender sender, final Component message)
{
Bukkit.getOnlinePlayers()
.forEach(player ->
{
if (player.hasPermission(ACPERM))
{
final Component formatted = Component.empty();
formatted.append(getFormat(player).format(sender.getName(), Groups.fromSender(sender)))
.append(Component.space())
.append(message);
player.sendMessage(formatted);
}
});
}
public static final class ACListener implements Listener
{
private final AdminChatDisplay display;
public ACListener(final AdminChatDisplay display, final Patchwork patchwork)
{
this.display = display;
Bukkit.getPluginManager()
.registerEvents(this, patchwork);
}
@EventHandler
public void playerChat(final AsyncChatEvent event)
{
if (display.isToggled(event.getPlayer()))
{
event.setCancelled(true);
display.adminChatMessage(event.getPlayer(), event.message());
}
}
@EventHandler
public void playerJoin(final PlayerJoinEvent event)
{
final Player player = event.getPlayer();
if (player.hasPermission(ACPERM))
{
final UserData data = Registration.getUserRegistry()
.fromPlayer(player);
if (data.hasCustomACFormat())
{
display.addPlayer(player, data.getCustomACFormat());
} else
{
display.addPlayer(player, AdminChatFormat.DEFAULT);
}
}
}
}
}

View File

@ -0,0 +1,107 @@
package fns.patchwork.display.adminchat;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public final class AdminChatFormat
{
public static final AdminChatFormat DEFAULT = ACFormatBuilder.format()
.build();
private final Component prefix;
private final Component userName;
private final Component rank;
private final Component chatSplitter;
private final Component fullFormat;
AdminChatFormat(final ACFormatBuilder builder)
{
this.prefix = Component.text(builder.openBracket(), builder.bracketColor())
.append(Component.text(builder.prefix(), builder.prefixColor()))
.append(Component.text(builder.closeBracket(), builder.bracketColor()));
this.userName = Component.text("%name%", builder.nameColor());
this.rank = Component.text(builder.openBracket(), builder.bracketColor())
.append(Component.text("%rank%", builder.rankColor()))
.append(Component.text(builder.closeBracket(), builder.bracketColor()));
// Nice formatting :(
if (builder.chatSplitter()
.equals(":"))
{
this.chatSplitter = Component.text(":", NamedTextColor.WHITE);
} else
{
this.chatSplitter = Component.space()
.append(Component.text(builder.chatSplitter(), NamedTextColor.WHITE));
}
// Formatting because []: is cleaner than [] :, but anything else such as [] >> or [] -> looks better with the space between.
this.fullFormat = prefix.appendSpace()
.append(userName)
.appendSpace()
.append(rank)
.append(chatSplitter)
.appendSpace();
}
public static AdminChatFormat deserialize(final String serialized)
{
final Component dez = LegacyComponentSerializer.legacyAmpersand()
.deserialize(serialized);
final Component prefix = dez.children()
.get(0);
final Component userName = dez.children()
.get(1);
final Component rank = dez.children()
.get(2);
final Component chatSplitter = dez.children()
.get(3);
return ACFormatBuilder.format()
.prefix(((TextComponent) prefix).content())
.prefixColor(prefix.color())
.nameColor(userName.color())
.rankColor(rank.color())
.chatSplitter(((TextComponent) chatSplitter).content())
.build();
}
public Component getPrefix()
{
return prefix;
}
public Component getUserName()
{
return userName;
}
public Component getRank()
{
return rank;
}
public Component getFullFormat()
{
return fullFormat;
}
public Component format(final String name, final String rank)
{
return fullFormat.replaceText(b ->
{
b.matchLiteral("%name%")
.replacement(name);
b.matchLiteral("%rank%")
.replacement(rank);
});
}
public String serialize()
{
return LegacyComponentSerializer.legacyAmpersand()
.serialize(fullFormat);
}
}

View File

@ -1,4 +1,4 @@
package me.totalfreedom.economy;
package fns.patchwork.economy;
/**
* Represents an immutable transaction that has been fully handled by a {@link Transactor} instance

View File

@ -1,4 +1,4 @@
package me.totalfreedom.economy;
package fns.patchwork.economy;
/**
* An entity that is able to transfer sums of currency between other {@link EconomicEntity}

View File

@ -1,4 +1,4 @@
package me.totalfreedom.economy;
package fns.patchwork.economy;
/**
* Metadata associated with a {@link EconomicEntity}

View File

@ -1,4 +1,4 @@
package me.totalfreedom.economy;
package fns.patchwork.economy;
/**
* A transaction that can be changed.

Some files were not shown because too many files have changed in this diff Show More