mirror of
https://github.com/SimplexDevelopment/FreedomNetworkSuite.git
synced 2025-07-12 17:38:34 +00:00
Migrates the entire package nomenclature to be more direct and straightforward. (#17)
Signed-off-by: Paul Reilly <pawereus@gmail.com>
This commit is contained in:
83
Datura/src/main/java/fns/datura/Datura.java
Normal file
83
Datura/src/main/java/fns/datura/Datura.java
Normal file
@ -0,0 +1,83 @@
|
||||
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.Patchwork;
|
||||
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 final Cager cager = new Cager();
|
||||
|
||||
// Features
|
||||
private final CommandSpy commandSpy = new CommandSpy();
|
||||
private final Fuckoff fuckoff = new Fuckoff();
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
Patchwork.getInstance()
|
||||
.getRegistrations()
|
||||
.getModuleRegistry()
|
||||
.addModule(this);
|
||||
|
||||
Patchwork.getInstance()
|
||||
.getRegistrations()
|
||||
.getServiceTaskRegistry()
|
||||
.registerService(SubscriptionProvider.syncService(this, locker));
|
||||
Patchwork.getInstance()
|
||||
.getRegistrations()
|
||||
.getServiceTaskRegistry()
|
||||
.registerService(SubscriptionProvider.syncService(this, cager));
|
||||
Patchwork.getInstance()
|
||||
.getRegistrations()
|
||||
.getServiceTaskRegistry()
|
||||
.registerService(SubscriptionProvider.syncService(this, fuckoff));
|
||||
|
||||
Bukkit.getPluginManager()
|
||||
.registerEvents(halter, this);
|
||||
Bukkit.getPluginManager()
|
||||
.registerEvents(commandSpy, 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;
|
||||
}
|
||||
}
|
64
Datura/src/main/java/fns/datura/cmd/AdminChatCommand.java
Normal file
64
Datura/src/main/java/fns/datura/cmd/AdminChatCommand.java
Normal file
@ -0,0 +1,64 @@
|
||||
package fns.datura.cmd;
|
||||
|
||||
import fns.patchwork.base.Patchwork;
|
||||
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;
|
||||
|
||||
Patchwork.getInstance()
|
||||
.getAdminChatDisplay()
|
||||
.toggleChat(player);
|
||||
|
||||
final boolean toggled = Patchwork.getInstance()
|
||||
.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)
|
||||
{
|
||||
Patchwork.getInstance()
|
||||
.getAdminChatDisplay()
|
||||
.adminChatMessage(sender, Component.text(message));
|
||||
}
|
||||
}
|
84
Datura/src/main/java/fns/datura/cmd/CageCommand.java
Normal file
84
Datura/src/main/java/fns/datura/cmd/CageCommand.java
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2023 TotalFreedom
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the “Software”), to deal in the Software
|
||||
* without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
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.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
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
|
||||
{
|
||||
public CageCommand(final @NotNull JavaPlugin plugin)
|
||||
{
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Subcommand(permission = "datura.cage", args = {Player.class, String.class})
|
||||
public void cagePlayer(final CommandSender sender, final Player player, final String string)
|
||||
{
|
||||
if (string.equalsIgnoreCase("on"))
|
||||
{
|
||||
((Datura) getPlugin()).getCager()
|
||||
.cagePlayer(player.getUniqueId());
|
||||
sender.sendPlainMessage("Caged " + player.getName() + ".");
|
||||
} else if (string.equalsIgnoreCase("off"))
|
||||
{
|
||||
((Datura) getPlugin()).getCager()
|
||||
.uncagePlayer(player.getUniqueId());
|
||||
sender.sendPlainMessage("Liberated " + player.getName() + ".");
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
{
|
||||
if (string.equalsIgnoreCase("on"))
|
||||
{
|
||||
Shortcuts.provideModule(Datura.class)
|
||||
.getCager()
|
||||
.cagePlayer(player.getUniqueId(), material);
|
||||
sender.sendPlainMessage("Caged " + player.getName() + ".");
|
||||
} else if (string.equalsIgnoreCase("off"))
|
||||
{
|
||||
Shortcuts.provideModule(Datura.class)
|
||||
.getCager()
|
||||
.uncagePlayer(player.getUniqueId());
|
||||
sender.sendPlainMessage("Liberated " + player.getName() + ".");
|
||||
}
|
||||
}
|
||||
}
|
94
Datura/src/main/java/fns/datura/cmd/ClearDropsCommand.java
Normal file
94
Datura/src/main/java/fns/datura/cmd/ClearDropsCommand.java
Normal 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;
|
||||
Patchwork.getInstance()
|
||||
.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)
|
||||
{
|
||||
Patchwork.getInstance()
|
||||
.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.");
|
||||
});
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
51
Datura/src/main/java/fns/datura/cmd/CommandSpyCommand.java
Normal file
51
Datura/src/main/java/fns/datura/cmd/CommandSpyCommand.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
64
Datura/src/main/java/fns/datura/cmd/FuckoffCommand.java
Normal file
64
Datura/src/main/java/fns/datura/cmd/FuckoffCommand.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
88
Datura/src/main/java/fns/datura/cmd/HaltCommand.java
Normal file
88
Datura/src/main/java/fns/datura/cmd/HaltCommand.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
Datura/src/main/java/fns/datura/cmd/LockerCommand.java
Normal file
41
Datura/src/main/java/fns/datura/cmd/LockerCommand.java
Normal file
@ -0,0 +1,41 @@
|
||||
package fns.datura.cmd;
|
||||
|
||||
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;
|
||||
|
||||
@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)
|
||||
{
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Subcommand(permission = "datura.locker", args = {Player.class, String.class})
|
||||
public void lockPlayer(final CommandSender sender, final Player player, final String string)
|
||||
{
|
||||
if (string.equalsIgnoreCase("on"))
|
||||
{
|
||||
((Datura) getPlugin()).getLocker()
|
||||
.lock(player);
|
||||
|
||||
sender.sendPlainMessage("Locked " + player.getName() + ".");
|
||||
} else if (string.equalsIgnoreCase("off"))
|
||||
{
|
||||
((Datura) getPlugin()).getLocker()
|
||||
.unlock(player);
|
||||
sender.sendPlainMessage("Unlocked " + player.getName() + ".");
|
||||
}
|
||||
}
|
||||
}
|
93
Datura/src/main/java/fns/datura/cmd/ManageUserCommand.java
Normal file
93
Datura/src/main/java/fns/datura/cmd/ManageUserCommand.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
51
Datura/src/main/java/fns/datura/cmd/SmiteCommand.java
Normal file
51
Datura/src/main/java/fns/datura/cmd/SmiteCommand.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package fns.datura.event;
|
||||
|
||||
import fns.patchwork.event.FEvent;
|
||||
import fns.patchwork.user.UserData;
|
||||
|
||||
public class UserDataUpdateEvent extends FEvent
|
||||
{
|
||||
private final UserData data;
|
||||
|
||||
public UserDataUpdateEvent(final UserData data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public UserData getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends FEvent> getEventClass()
|
||||
{
|
||||
return UserDataUpdateEvent.class;
|
||||
}
|
||||
}
|
54
Datura/src/main/java/fns/datura/features/CommandSpy.java
Normal file
54
Datura/src/main/java/fns/datura/features/CommandSpy.java
Normal 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))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
61
Datura/src/main/java/fns/datura/features/Fuckoff.java
Normal file
61
Datura/src/main/java/fns/datura/features/Fuckoff.java
Normal 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)));
|
||||
}
|
||||
}
|
41
Datura/src/main/java/fns/datura/perms/DefaultNodes.java
Normal file
41
Datura/src/main/java/fns/datura/perms/DefaultNodes.java
Normal file
@ -0,0 +1,41 @@
|
||||
package fns.datura.perms;
|
||||
|
||||
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)
|
||||
.type(NodeType.PERMISSION)
|
||||
.negated(false)
|
||||
.wildcard(true)
|
||||
.build();
|
||||
public static final Node NON_OP = new PermissionNodeBuilder()
|
||||
.key("freedom.default")
|
||||
.value(true)
|
||||
.type(NodeType.PERMISSION)
|
||||
.negated(false)
|
||||
.wildcard(false)
|
||||
.build();
|
||||
public static final Node ALL = new PermissionNodeBuilder()
|
||||
.key("*")
|
||||
.value(true)
|
||||
.type(NodeType.PERMISSION)
|
||||
.negated(false)
|
||||
.wildcard(true)
|
||||
.build();
|
||||
public static final Node NONE = new PermissionNodeBuilder()
|
||||
.key("freedom.none")
|
||||
.value(true)
|
||||
.type(NodeType.PERMISSION)
|
||||
.negated(false)
|
||||
.wildcard(false)
|
||||
.build();
|
||||
|
||||
private DefaultNodes()
|
||||
{
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
243
Datura/src/main/java/fns/datura/perms/FreedomGroup.java
Normal file
243
Datura/src/main/java/fns/datura/perms/FreedomGroup.java
Normal file
@ -0,0 +1,243 @@
|
||||
package fns.datura.perms;
|
||||
|
||||
import fns.patchwork.base.Patchwork;
|
||||
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;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class FreedomGroup implements Group
|
||||
{
|
||||
private final Component name;
|
||||
private final Component prefix;
|
||||
private final Component abbreviation;
|
||||
private final int weight;
|
||||
private final boolean isDefault;
|
||||
private final boolean isHidden;
|
||||
private final Set<Node> permissions;
|
||||
private final PermissionAttachment attachment;
|
||||
|
||||
public FreedomGroup(final Component name,
|
||||
final Component prefix,
|
||||
final Component abbreviation,
|
||||
final int weight,
|
||||
final boolean isDefault,
|
||||
final boolean isHidden)
|
||||
{
|
||||
this.name = name;
|
||||
this.prefix = prefix;
|
||||
this.abbreviation = abbreviation;
|
||||
this.weight = weight;
|
||||
this.isDefault = isDefault;
|
||||
this.isHidden = isHidden;
|
||||
this.permissions = new HashSet<>();
|
||||
this.attachment = new PermissionAttachment(Patchwork.getInstance(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId()
|
||||
{
|
||||
return UUID.nameUUIDFromBytes(getName().toString()
|
||||
.getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getPrefix()
|
||||
{
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getAbbreviation()
|
||||
{
|
||||
return abbreviation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWeight()
|
||||
{
|
||||
return weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault()
|
||||
{
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden()
|
||||
{
|
||||
return isHidden;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> permissions()
|
||||
{
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPermission(final Node node)
|
||||
{
|
||||
return permissions().add(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePermission(final Node node)
|
||||
{
|
||||
return permissions().remove(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NotNull final String name)
|
||||
{
|
||||
final Node node = permissions().stream()
|
||||
.filter(n -> n.key()
|
||||
.equalsIgnoreCase(name))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
return node != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NotNull final Permission perm)
|
||||
{
|
||||
final Node node = permissions()
|
||||
.stream()
|
||||
.filter(n -> n.bukkit()
|
||||
.equals(perm))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
return node != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NotNull final String name)
|
||||
{
|
||||
final Node node = permissions().stream()
|
||||
.filter(n -> n.key()
|
||||
.equalsIgnoreCase(name))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
return node != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NotNull final Permission perm)
|
||||
{
|
||||
final Node node = permissions()
|
||||
.stream()
|
||||
.filter(n -> n.bukkit()
|
||||
.equals(perm))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
return node != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a permission to the relative PermissionAttachment for this group. This method is not thread-safe and should
|
||||
* not be called asynchronously.
|
||||
* <p>
|
||||
* This method is only here for compatibility with the Bukkit API.
|
||||
*
|
||||
* @param plugin The plugin responsible for this attachment. May not be null or disabled.
|
||||
* @param name Name of the permission to attach
|
||||
* @param value Value of the permission
|
||||
* @return This group's PermissionAttachment.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name,
|
||||
final boolean value)
|
||||
{
|
||||
attachment.setPermission(name, value);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin)
|
||||
{
|
||||
return new PermissionAttachment(plugin, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name,
|
||||
final boolean value, final int ticks)
|
||||
{
|
||||
attachment.setPermission(name, value);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, final int ticks)
|
||||
{
|
||||
return new PermissionAttachment(plugin, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(@NotNull final PermissionAttachment attachment)
|
||||
{
|
||||
// This method shouldn't do anything, because we don't want to remove our attachment.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions()
|
||||
{
|
||||
// Not sure what this method should do, so I'm leaving it empty.
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<PermissionAttachmentInfo> getEffectivePermissions()
|
||||
{
|
||||
return permissions()
|
||||
.stream()
|
||||
.map(n -> new PermissionAttachmentInfo(
|
||||
this,
|
||||
n.key(),
|
||||
attachment, true))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp()
|
||||
{
|
||||
final Node node = permissions()
|
||||
.stream()
|
||||
.filter(n -> n.equals(DefaultNodes.OP))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
return node != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(final boolean value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
permissions().add(DefaultNodes.OP);
|
||||
} else
|
||||
{
|
||||
permissions().remove(DefaultNodes.OP);
|
||||
}
|
||||
}
|
||||
}
|
243
Datura/src/main/java/fns/datura/perms/FreedomUser.java
Normal file
243
Datura/src/main/java/fns/datura/perms/FreedomUser.java
Normal file
@ -0,0 +1,243 @@
|
||||
package fns.datura.perms;
|
||||
|
||||
import fns.datura.Datura;
|
||||
import fns.datura.user.SimpleUserData;
|
||||
import fns.patchwork.base.Patchwork;
|
||||
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;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* permission plugins.
|
||||
*/
|
||||
public class FreedomUser implements User
|
||||
{
|
||||
private final UUID uuid;
|
||||
private final Set<Node> permissions;
|
||||
private final Map<Node, PermissionAttachment> bukkitAttachments = new HashMap<>();
|
||||
private final Component displayName;
|
||||
private static final String NOT_ONLINE = "Player is not online";
|
||||
private final UserData userData;
|
||||
|
||||
public FreedomUser(final Player player)
|
||||
{
|
||||
this.uuid = player.getUniqueId();
|
||||
this.permissions = new HashSet<>();
|
||||
this.displayName = player.displayName();
|
||||
|
||||
final Datura datura = Patchwork.getInstance()
|
||||
.getRegistrations()
|
||||
.getModuleRegistry()
|
||||
.getProvider(Datura.class)
|
||||
.getModule();
|
||||
|
||||
UserData data = SimpleUserData.fromSQL(datura.getSQL(), uuid.toString());
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
data = new SimpleUserData(player);
|
||||
}
|
||||
|
||||
this.userData = data;
|
||||
|
||||
Patchwork.getInstance()
|
||||
.getRegistrations()
|
||||
.getUserRegistry()
|
||||
.registerUserData(this, userData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserData getUserData()
|
||||
{
|
||||
return userData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName()
|
||||
{
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline()
|
||||
{
|
||||
return Bukkit.getPlayer(uuid) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId()
|
||||
{
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Node> permissions()
|
||||
{
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPermission(final Node node)
|
||||
{
|
||||
final boolean value = !node.isTemporary() || node.isExpired();
|
||||
final PermissionAttachment attachment = addAttachment(Patchwork.getInstance(), node.key(), value);
|
||||
bukkitAttachments.put(node, attachment);
|
||||
return permissions().add(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePermission(final Node node)
|
||||
{
|
||||
removeAttachment(bukkitAttachments.get(node));
|
||||
bukkitAttachments.remove(node);
|
||||
return permissions.remove(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NotNull final String name)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
return player != null && player.isPermissionSet(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPermissionSet(@NotNull final Permission perm)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
return player != null && player.isPermissionSet(perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NotNull final String name)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
return player != null && player.hasPermission(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NotNull final Permission perm)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
return player != null && player.hasPermission(perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name,
|
||||
final boolean value)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
{
|
||||
return player.addAttachment(plugin, name, value);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(NOT_ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
{
|
||||
return player.addAttachment(plugin);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(NOT_ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name,
|
||||
final boolean value, final int ticks)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
{
|
||||
return player.addAttachment(plugin, name, value, ticks);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(NOT_ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, final int ticks)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
{
|
||||
return player.addAttachment(plugin, ticks);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(NOT_ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttachment(@NotNull final PermissionAttachment attachment)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
{
|
||||
player.removeAttachment(attachment);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(NOT_ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissions()
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
{
|
||||
player.recalculatePermissions();
|
||||
}
|
||||
|
||||
throw new IllegalStateException(NOT_ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<PermissionAttachmentInfo> getEffectivePermissions()
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
{
|
||||
return player.getEffectivePermissions();
|
||||
}
|
||||
|
||||
throw new IllegalStateException(NOT_ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOp()
|
||||
{
|
||||
return permissions().contains(DefaultNodes.OP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOp(final boolean value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
permissions().add(DefaultNodes.OP);
|
||||
} else
|
||||
{
|
||||
permissions().remove(DefaultNodes.OP);
|
||||
}
|
||||
}
|
||||
}
|
39
Datura/src/main/java/fns/datura/perms/PermissionNode.java
Normal file
39
Datura/src/main/java/fns/datura/perms/PermissionNode.java
Normal 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package fns.datura.perms;
|
||||
|
||||
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 long expiry = -1;
|
||||
private NodeType type = NodeType.PERMISSION;
|
||||
private boolean wildcard = false;
|
||||
|
||||
@Override
|
||||
public NodeBuilder key(final String key)
|
||||
{
|
||||
this.key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeBuilder expiry(final long expiry)
|
||||
{
|
||||
this.expiry = expiry;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeBuilder type(final NodeType type)
|
||||
{
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeBuilder wildcard(final boolean wildcard)
|
||||
{
|
||||
this.wildcard = wildcard;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node build()
|
||||
{
|
||||
return new PermissionNode(key, expiry, type, wildcard);
|
||||
}
|
||||
}
|
178
Datura/src/main/java/fns/datura/punishment/Cager.java
Normal file
178
Datura/src/main/java/fns/datura/punishment/Cager.java
Normal file
@ -0,0 +1,178 @@
|
||||
package fns.datura.punishment;
|
||||
|
||||
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;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class Cager extends Service
|
||||
{
|
||||
private final Set<UUID> cagedPlayers;
|
||||
private final Map<UUID, Location> cageLocations;
|
||||
|
||||
public Cager()
|
||||
{
|
||||
super("cager-service");
|
||||
this.cagedPlayers = new HashSet<>();
|
||||
this.cageLocations = new HashMap<>();
|
||||
Bukkit.getPluginManager()
|
||||
.registerEvents(new CageListener(), Patchwork.getInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will cage the player using {@link #createCage(Location, Material)}.
|
||||
* <p>This will also add the returned location to the {@link #cageLocations} map.
|
||||
*
|
||||
* @param uuid The UUID of the player to cage.
|
||||
*/
|
||||
public void cagePlayer(final UUID uuid)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player == null) return;
|
||||
|
||||
cagedPlayers.add(uuid);
|
||||
cageLocations.put(uuid, createCage(player.getLocation(), Material.GLASS));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method generates a cube centered around the passed location, made of the provided material. This method
|
||||
* returns the passed location object. We use the {@link ShapeUtils} class to generate the cube, which allows us to
|
||||
* define custom shapes using {@link DoubleUnaryOperator}s.
|
||||
*
|
||||
* @param location The location to center the cube around.
|
||||
* @param material The material to use for the cube.
|
||||
* @return The center location of the cube (the passed location).
|
||||
* @see ShapeUtils
|
||||
* @see DoubleUnaryOperator
|
||||
*/
|
||||
public Location createCage(final Location location, final Material material)
|
||||
{
|
||||
final ShapeUtils shapeUtils = new ShapeUtils(location.getWorld(), 0.0, 4.0);
|
||||
final List<Location> cubed = new LinkedList<>();
|
||||
cubed.addAll(shapeUtils.generate(5, t -> t, t -> 4.0, t -> t));
|
||||
cubed.addAll(shapeUtils.generate(5, t -> t, t -> 0.0, t -> t));
|
||||
cubed.addAll(shapeUtils.generate(5, t -> 0.0, t -> t, t -> t));
|
||||
cubed.addAll(shapeUtils.generate(5, t -> 4.0, t -> t, t -> t));
|
||||
cubed.addAll(shapeUtils.generate(5, t -> t, t -> t, t -> 0.0));
|
||||
cubed.addAll(shapeUtils.generate(5, t -> t, t -> t, t -> 4.0));
|
||||
|
||||
for (final Location l : cubed)
|
||||
{
|
||||
location.getWorld()
|
||||
.getBlockAt(l)
|
||||
.setType(material);
|
||||
}
|
||||
|
||||
return location.clone(); // Return the passed location as that is the center of the cube.
|
||||
}
|
||||
|
||||
public void cagePlayer(final UUID uuid, final Material material)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player == null) return;
|
||||
|
||||
cagedPlayers.add(uuid);
|
||||
cageLocations.put(uuid, createCage(player.getLocation(), material));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will uncage the player by removing them from the {@link #cagedPlayers} set.
|
||||
*
|
||||
* @param uuid The UUID of the player to uncage.
|
||||
*/
|
||||
public void uncagePlayer(final UUID uuid)
|
||||
{
|
||||
cagedPlayers.remove(uuid);
|
||||
final Location location = cageLocations.get(uuid);
|
||||
|
||||
createCage(location, Material.AIR); // Remove the cage (set all blocks to air).
|
||||
|
||||
cageLocations.remove(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will check to make sure each caged player remains within their cage. We use
|
||||
* <p>
|
||||
* <code>{@link Location#distanceSquared(Location)} * {@link Math#pow(double, double)}</code>
|
||||
* <p>
|
||||
* to check if the player is outside the cage.
|
||||
*/
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
for (final UUID uuid : cagedPlayers)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player == null) continue;
|
||||
|
||||
final Location cageLocation = getCageLocation(player);
|
||||
|
||||
final boolean inside;
|
||||
if (!player.getWorld()
|
||||
.equals(cageLocation.getWorld()))
|
||||
{
|
||||
inside = false;
|
||||
} else
|
||||
{
|
||||
inside = player.getLocation()
|
||||
.distanceSquared(cageLocation) > (Math.pow(2.5, 2.0));
|
||||
}
|
||||
|
||||
if (!inside)
|
||||
{
|
||||
player.teleport(cageLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns whether the player is caged.
|
||||
* <p>This method requires the player to be online to execute properly.</p>
|
||||
*
|
||||
* @param player The player to check.
|
||||
* @return Whether the player is caged.
|
||||
*/
|
||||
public Location getCageLocation(final Player player)
|
||||
{
|
||||
return cageLocations.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
private final class CageListener implements Listener
|
||||
{
|
||||
@EventHandler
|
||||
public void blockBreakEvent(final BlockBreakEvent event)
|
||||
{
|
||||
if (cagedPlayers.contains(event.getPlayer()
|
||||
.getUniqueId()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void playerLeaveEvent(final PlayerQuitEvent event)
|
||||
{
|
||||
if (cagedPlayers.contains(event.getPlayer()
|
||||
.getUniqueId()))
|
||||
{
|
||||
uncagePlayer(event.getPlayer()
|
||||
.getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
Datura/src/main/java/fns/datura/punishment/Halter.java
Normal file
43
Datura/src/main/java/fns/datura/punishment/Halter.java
Normal file
@ -0,0 +1,43 @@
|
||||
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
|
||||
{
|
||||
private final Set<UUID> haltedPlayers;
|
||||
|
||||
public Halter()
|
||||
{
|
||||
this.haltedPlayers = new HashSet<>();
|
||||
}
|
||||
|
||||
public void halt(final UUID uuid)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (haltedPlayers.contains(event.getPlayer()
|
||||
.getUniqueId()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
88
Datura/src/main/java/fns/datura/punishment/Locker.java
Normal file
88
Datura/src/main/java/fns/datura/punishment/Locker.java
Normal file
@ -0,0 +1,88 @@
|
||||
package fns.datura.punishment;
|
||||
|
||||
import fns.patchwork.base.Patchwork;
|
||||
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;
|
||||
|
||||
public class Locker extends Service
|
||||
{
|
||||
private final Set<UUID> lockedPlayers = new HashSet<>();
|
||||
|
||||
public Locker()
|
||||
{
|
||||
super("locker-service");
|
||||
}
|
||||
|
||||
public void lock(final Player player)
|
||||
{
|
||||
lockedPlayers.add(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void unlock(final Player player)
|
||||
{
|
||||
lockedPlayers.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
lockedPlayers.removeIf(uuid -> !Patchwork.getInstance()
|
||||
.getServer()
|
||||
.getOfflinePlayer(uuid)
|
||||
.isOnline());
|
||||
|
||||
for (final UUID uuid : lockedPlayers)
|
||||
{
|
||||
final Player player = Bukkit.getPlayer(uuid);
|
||||
if (player == null) continue;
|
||||
|
||||
lockingMethod(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void lockingMethod(@NotNull final Player player)
|
||||
{
|
||||
final double x = player.getLocation()
|
||||
.getX();
|
||||
final double z = player.getLocation()
|
||||
.getZ();
|
||||
|
||||
if ((x / z % 0.001) < 1)
|
||||
{
|
||||
player.setVelocity(new Vector(x % 12, 0, z % 12));
|
||||
}
|
||||
|
||||
player.setWalkSpeed(0.0f);
|
||||
player.setFlySpeed(0.0f);
|
||||
player.setAllowFlight(false);
|
||||
player.setFlying(false);
|
||||
player.setInvulnerable(true);
|
||||
player.setCollidable(false);
|
||||
player.setGliding(false);
|
||||
player.setGlowing(true);
|
||||
player.setSilent(true);
|
||||
player.setCanPickupItems(false);
|
||||
player.setInvisible(true);
|
||||
|
||||
player.openInventory(Bukkit.createInventory(null, 54));
|
||||
player.closeInventory(InventoryCloseEvent.Reason.UNKNOWN);
|
||||
player.teleport(player.getLocation()
|
||||
.clone());
|
||||
|
||||
final SplittableRandom random = new SplittableRandom();
|
||||
player.getEyeLocation()
|
||||
.add(new Vector(
|
||||
random.nextDouble(-1.0, 1.0),
|
||||
random.nextDouble(-1.0, 1.0),
|
||||
random.nextDouble(-1.0, 1.0)
|
||||
));
|
||||
}
|
||||
}
|
260
Datura/src/main/java/fns/datura/sql/MySQL.java
Normal file
260
Datura/src/main/java/fns/datura/sql/MySQL.java
Normal file
@ -0,0 +1,260 @@
|
||||
package fns.datura.sql;
|
||||
|
||||
import fns.patchwork.base.Patchwork;
|
||||
import fns.patchwork.sql.SQL;
|
||||
import fns.patchwork.utils.container.Identity;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
public class MySQL implements SQL
|
||||
{
|
||||
/**
|
||||
* Using StringBuilder for finality.
|
||||
*/
|
||||
private final StringBuilder url = new StringBuilder("jdbc:mysql://");
|
||||
|
||||
public MySQL(final String host, final int port, final String database)
|
||||
{
|
||||
url.append(host)
|
||||
.append(':')
|
||||
.append(port)
|
||||
.append('/')
|
||||
.append(database);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds credentials to the MySQL URL. If the URL already contains credentials, they will be overwritten.
|
||||
*
|
||||
* @param username The username to add
|
||||
* @param password The password to add
|
||||
*/
|
||||
public void addCredentials(final String username, final String password)
|
||||
{
|
||||
if (url.toString()
|
||||
.contains("?user="))
|
||||
{
|
||||
final String split = url.toString()
|
||||
.split("\\x3f")[0];
|
||||
url.setLength(0);
|
||||
url.append(split);
|
||||
}
|
||||
|
||||
url.append("?user=")
|
||||
.append(username)
|
||||
.append("&password=")
|
||||
.append(password);
|
||||
}
|
||||
|
||||
public CompletableFuture<ResultSet> getRow(final String table, final String column, final Identity identity)
|
||||
{
|
||||
return executeQuery("SELECT * FROM ? WHERE ? = ?", table, column, identity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<PreparedStatement> prepareStatement(final String query, final Object... args)
|
||||
{
|
||||
return getConnection()
|
||||
.thenApplyAsync(connection ->
|
||||
{
|
||||
try
|
||||
{
|
||||
final PreparedStatement statement = connection.prepareStatement(query);
|
||||
for (int i = 0; i < args.length; i++)
|
||||
{
|
||||
statement.setObject(i + 1, args[i]);
|
||||
}
|
||||
return statement;
|
||||
} catch (SQLException ex)
|
||||
{
|
||||
throw new CompletionException("Failed to prepare statement: "
|
||||
+ query + "\n", ex);
|
||||
}
|
||||
}, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync());
|
||||
}
|
||||
|
||||
private CompletableFuture<Connection> getConnection()
|
||||
{
|
||||
return CompletableFuture.supplyAsync(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
return DriverManager.getConnection(url.toString());
|
||||
} catch (SQLException ex)
|
||||
{
|
||||
throw new CompletionException("Failed to connect to the database: "
|
||||
+ url.toString() + "\n", ex);
|
||||
}
|
||||
}, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ResultSet> executeQuery(final String query, final Object... args)
|
||||
{
|
||||
return prepareStatement(query, args)
|
||||
.thenApplyAsync(statement ->
|
||||
{
|
||||
try
|
||||
{
|
||||
return statement.executeQuery();
|
||||
} catch (SQLException ex)
|
||||
{
|
||||
throw new CompletionException(
|
||||
"Failed to retrieve a result set from query: "
|
||||
+ query + "\n", ex);
|
||||
}
|
||||
}, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Integer> executeUpdate(final String query, final Object... args)
|
||||
{
|
||||
return prepareStatement(query, args)
|
||||
.thenApplyAsync(statement ->
|
||||
{
|
||||
try
|
||||
{
|
||||
return statement.executeUpdate();
|
||||
} catch (SQLException ex)
|
||||
{
|
||||
throw new CompletionException("Failed to execute update: "
|
||||
+ query + "\n", ex);
|
||||
}
|
||||
}, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> execute(final String query, final Object... args)
|
||||
{
|
||||
return prepareStatement(query, args)
|
||||
.thenApplyAsync(statement ->
|
||||
{
|
||||
try
|
||||
{
|
||||
return statement.execute();
|
||||
} catch (SQLException ex)
|
||||
{
|
||||
throw new CompletionException("Failed to execute statement: "
|
||||
+ query + "\n", ex);
|
||||
}
|
||||
}, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> createTable(final String table, final String... columns)
|
||||
{
|
||||
final StringBuilder query = new StringBuilder();
|
||||
|
||||
query.append("CREATE TABLE IF NOT EXISTS ? (");
|
||||
for (int i = 0; i < columns.length; i++)
|
||||
{
|
||||
query.append("?");
|
||||
if (i != columns.length - 1)
|
||||
{
|
||||
query.append(", ");
|
||||
}
|
||||
}
|
||||
query.append(")");
|
||||
|
||||
return execute(query.toString(), table, columns);
|
||||
}
|
||||
|
||||
public <T> CompletableFuture<T> getColumn(final String table, final String column, final String key,
|
||||
final Identity identity, final Class<T> type)
|
||||
{
|
||||
return executeQuery("SELECT ? FROM ? WHERE ? = ?", column, table, key, identity.getId())
|
||||
.thenApplyAsync(resultSet ->
|
||||
{
|
||||
try
|
||||
{
|
||||
if (resultSet.next())
|
||||
{
|
||||
return resultSet.getObject(column, type);
|
||||
}
|
||||
} catch (SQLException ex)
|
||||
{
|
||||
throw new CompletionException(
|
||||
"Failed to retrieve column: " + column + " from table: " + table + " " +
|
||||
"where primary key: " + key + " is equal to: " + identity.getId() + "\n",
|
||||
ex);
|
||||
}
|
||||
return null;
|
||||
}, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync());
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> updateColumn(final String table, final String column, final Object value,
|
||||
final String key, final Identity identity)
|
||||
{
|
||||
return executeUpdate("UPDATE ? SET ? = ? WHERE ? = ?", table, column, value, key, identity.getId())
|
||||
.thenApplyAsync(result -> result > 0, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync());
|
||||
}
|
||||
|
||||
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, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync());
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> insertRow(final String table, final Object... values)
|
||||
{
|
||||
final StringBuilder query = new StringBuilder();
|
||||
query.append("INSERT INTO ? VALUES (");
|
||||
for (int i = 0; i < values.length; i++)
|
||||
{
|
||||
query.append("?");
|
||||
if (i != values.length - 1)
|
||||
{
|
||||
query.append(", ");
|
||||
}
|
||||
}
|
||||
query.append(")");
|
||||
return execute(query.toString(), table, values);
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> insertRow(final String table, final String[] columns, final Object... values)
|
||||
{
|
||||
final StringBuilder query = new StringBuilder();
|
||||
query.append("INSERT INTO ? (");
|
||||
for (int i = 0; i < columns.length; i++)
|
||||
{
|
||||
query.append("?");
|
||||
if (i != columns.length - 1)
|
||||
{
|
||||
query.append(", ");
|
||||
}
|
||||
}
|
||||
query.append(") VALUES (");
|
||||
for (int i = 0; i < values.length; i++)
|
||||
{
|
||||
query.append("?");
|
||||
if (i != values.length - 1)
|
||||
{
|
||||
query.append(", ");
|
||||
}
|
||||
}
|
||||
query.append(")");
|
||||
return execute(query.toString(), table, columns, values);
|
||||
}
|
||||
|
||||
|
||||
}
|
14
Datura/src/main/java/fns/datura/sql/Result.java
Normal file
14
Datura/src/main/java/fns/datura/sql/Result.java
Normal file
@ -0,0 +1,14 @@
|
||||
package fns.datura.sql;
|
||||
|
||||
|
||||
import com.google.errorprone.annotations.Immutable;
|
||||
|
||||
/**
|
||||
* Represents a single result from a result set.
|
||||
*/
|
||||
@Immutable
|
||||
public record Result(String name, Object value)
|
||||
{
|
||||
}
|
||||
|
||||
|
128
Datura/src/main/java/fns/datura/user/ServerEconomyHolder.java
Normal file
128
Datura/src/main/java/fns/datura/user/ServerEconomyHolder.java
Normal file
@ -0,0 +1,128 @@
|
||||
package fns.datura.user;
|
||||
|
||||
import fns.patchwork.economy.EconomicEntity;
|
||||
import fns.patchwork.economy.EconomicEntityData;
|
||||
|
||||
/**
|
||||
* Represents the server's economy holder.
|
||||
* <br>
|
||||
* <br>
|
||||
* This is effectively a Bank object which is meant to represent the server itself, which can store a balance and
|
||||
* perform transactions with other EconomicEntity objects.
|
||||
* <br>
|
||||
* <br>
|
||||
* The server is initially given a maximum balance of {@link Long#MAX_VALUE}, though this can be changed using the
|
||||
* constructor {@link #ServerEconomyHolder(String, long)}. The value that this bank object holds is persistent, which
|
||||
* means that the total economic resources available are of limited supply.
|
||||
* <br>
|
||||
* <br>
|
||||
* Please be aware, if the server's economy falls below 0, it will have drastic consequences.
|
||||
*/
|
||||
public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData
|
||||
{
|
||||
private final String name;
|
||||
private long balance;
|
||||
|
||||
/**
|
||||
* Constructs a new ServerEconomyHolder with the specified name and a balance of {@link Long#MAX_VALUE}.
|
||||
*
|
||||
* @param name The name of this server economy holder.
|
||||
*/
|
||||
public ServerEconomyHolder(final String name)
|
||||
{
|
||||
this.name = name;
|
||||
this.balance = Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ServerEconomyHolder with the specified name and balance.
|
||||
*
|
||||
* @param name The name of this server economy holder.
|
||||
* @param balance The balance of this server economy holder.
|
||||
*/
|
||||
public ServerEconomyHolder(final String name, final long balance)
|
||||
{
|
||||
this.name = name;
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will return this object, as it is both the EconomicEntity and the EconomicEntityData. This is due to
|
||||
* the fact that the server should only ever have one singular concrete representation of it's economic entity and
|
||||
* the respective data.
|
||||
*
|
||||
* @return this object.
|
||||
*/
|
||||
@Override
|
||||
public EconomicEntityData getEconomicData()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The name of this server economy holder.
|
||||
*/
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will always return false, as the server should not ever be prevented from performing transactions.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
public boolean areTransactionsFrozen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The server's current available balance.
|
||||
*/
|
||||
@Override
|
||||
public long getBalance()
|
||||
{
|
||||
return balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's balance to the specified value.
|
||||
*
|
||||
* @param newBalance The new balance to set.
|
||||
*/
|
||||
@Override
|
||||
public void setBalance(final long newBalance)
|
||||
{
|
||||
balance = newBalance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified amount to the server's balance. This method mutates the balance and returns the new balance.
|
||||
*
|
||||
* @param amount The amount to add.
|
||||
* @return The new balance.
|
||||
*/
|
||||
@Override
|
||||
public long addToBalance(final long amount)
|
||||
{
|
||||
balance += amount;
|
||||
return balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified amount from the server's balance. This method mutates the balance and returns the new
|
||||
* balance.
|
||||
*
|
||||
* @param amount The amount to remove.
|
||||
* @return The new balance.
|
||||
*/
|
||||
@Override
|
||||
public long removeFromBalance(final long amount)
|
||||
{
|
||||
balance -= amount;
|
||||
return balance;
|
||||
}
|
||||
}
|
244
Datura/src/main/java/fns/datura/user/SimpleUserData.java
Normal file
244
Datura/src/main/java/fns/datura/user/SimpleUserData.java
Normal file
@ -0,0 +1,244 @@
|
||||
package fns.datura.user;
|
||||
|
||||
import fns.datura.event.UserDataUpdateEvent;
|
||||
import fns.datura.perms.FreedomUser;
|
||||
import fns.patchwork.base.Patchwork;
|
||||
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;
|
||||
|
||||
public class SimpleUserData implements UserData
|
||||
{
|
||||
private final UUID uuid;
|
||||
private final String username;
|
||||
private final User user;
|
||||
private final UserDataUpdateEvent event = new UserDataUpdateEvent(this);
|
||||
private Group group;
|
||||
private long playtime;
|
||||
private boolean canInteract;
|
||||
private AtomicLong balance;
|
||||
private boolean transactionsFrozen;
|
||||
private boolean hasCustomACFormat = false;
|
||||
private String customACFormat;
|
||||
|
||||
public SimpleUserData(final Player player)
|
||||
{
|
||||
this.uuid = player.getUniqueId();
|
||||
this.username = player.getName();
|
||||
this.user = new FreedomUser(player);
|
||||
|
||||
Patchwork.getInstance()
|
||||
.getEventBus()
|
||||
.addEvent(event);
|
||||
}
|
||||
|
||||
private SimpleUserData(
|
||||
final UUID uuid,
|
||||
final String username,
|
||||
final User user,
|
||||
final Group group,
|
||||
final long playtime,
|
||||
final boolean canInteract,
|
||||
final long balance,
|
||||
final boolean transactionsFrozen)
|
||||
{
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
this.user = user;
|
||||
this.group = group;
|
||||
this.playtime = playtime;
|
||||
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)
|
||||
{
|
||||
return sql.executeQuery("SELECT * FROM users WHERE UUID = ?", uuid)
|
||||
.thenApplyAsync(result ->
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result.next())
|
||||
{
|
||||
final String g = result.getString("group");
|
||||
|
||||
final UUID u = UUID.fromString(uuid);
|
||||
final String username = result.getString("username");
|
||||
|
||||
final Player player = Bukkit.getPlayer(u);
|
||||
|
||||
if (player == null)
|
||||
throw new IllegalStateException("Player should be online but they are not!");
|
||||
|
||||
final User user = new FreedomUser(player);
|
||||
final Group group = Patchwork.getInstance()
|
||||
.getRegistrations()
|
||||
.getGroupRegistry()
|
||||
.getGroup(g);
|
||||
|
||||
final long playtime = result.getLong("playtime");
|
||||
final boolean canInteract = result.getBoolean("canInteract");
|
||||
final long balance = result.getLong("balance");
|
||||
final boolean transactionsFrozen = result.getBoolean("transactionsFrozen");
|
||||
|
||||
return new SimpleUserData(u, username, user, group, playtime,
|
||||
canInteract, balance, transactionsFrozen);
|
||||
}
|
||||
} catch (SQLException ex)
|
||||
{
|
||||
final String sb = "An error occurred while trying to retrieve user data for" +
|
||||
" UUID " +
|
||||
uuid +
|
||||
" from the database." +
|
||||
"\nCaused by: " +
|
||||
ExceptionUtils.getRootCauseMessage(ex) +
|
||||
"\nStack trace: " +
|
||||
ExceptionUtils.getStackTrace(ex);
|
||||
|
||||
FreedomLogger.getLogger("Datura")
|
||||
.error(sb);
|
||||
}
|
||||
|
||||
final Player player = Bukkit.getPlayer(UUID.fromString(uuid));
|
||||
if (player == null) throw new IllegalStateException("Player should be online but they are not!");
|
||||
|
||||
return new SimpleUserData(player);
|
||||
}, Patchwork.getInstance()
|
||||
.getExecutor()
|
||||
.getAsync())
|
||||
.join();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull UUID getUniqueId()
|
||||
{
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser()
|
||||
{
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Group getGroup()
|
||||
{
|
||||
return group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroup(@Nullable final Group group)
|
||||
{
|
||||
event.ping();
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPlaytime()
|
||||
{
|
||||
return playtime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlaytime(final long playtime)
|
||||
{
|
||||
event.ping();
|
||||
this.playtime = playtime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlaytime(final long playtime)
|
||||
{
|
||||
event.ping();
|
||||
this.playtime += playtime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPlaytime()
|
||||
{
|
||||
event.ping();
|
||||
this.playtime = 0L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInteract()
|
||||
{
|
||||
return canInteract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInteractionState(final boolean canInteract)
|
||||
{
|
||||
event.ping();
|
||||
this.canInteract = canInteract;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areTransactionsFrozen()
|
||||
{
|
||||
return transactionsFrozen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBalance()
|
||||
{
|
||||
return balance.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBalance(final long newBalance)
|
||||
{
|
||||
balance.set(newBalance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long addToBalance(final long amount)
|
||||
{
|
||||
return balance.addAndGet(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long removeFromBalance(final long amount)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user