Merge pull request #1 from AtlasMediaGroup/banning-update

Banning update
This commit is contained in:
Video 2023-05-24 20:10:54 -06:00 committed by GitHub
commit 595edc6e24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 1073 additions and 496 deletions

View File

@ -11,8 +11,6 @@ repositories {
dependencies {
compileOnly project(":Patchwork")
compileOnly "com.discord4j:discord4j-core:3.2.3"
compileOnly "com.discord4j:discord4j-commons:3.2.3"
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'

View File

@ -0,0 +1,66 @@
package me.totalfreedom.datura.banning;
import me.totalfreedom.security.ban.BanID;
import java.time.Instant;
import java.time.temporal.ChronoField;
public final class BanUID implements BanID
{
private final char prefix;
private final int numericalTag;
private BanUID(final boolean permanent)
{
if (permanent)
{
prefix = 'P';
} else
{
prefix = 'T';
}
final Instant instant = Instant.now();
final String stringBuilder = String.valueOf(instant.get(ChronoField.DAY_OF_YEAR)) + // The first three numbers between 001 -> 365
instant.get(ChronoField.HOUR_OF_DAY) + // next two numbers between 00 -> 23
instant.get(ChronoField.MINUTE_OF_HOUR) + // next two numbers between 00 -> 59
instant.get(ChronoField.MILLI_OF_SECOND); // last three numbers between 000 -> 999
numericalTag = Integer.parseInt(stringBuilder);
}
public static BanUID createTempID()
{
return new BanUID(false);
}
public static BanUID createPermID()
{
return new BanUID(true);
}
@Override
public String getID()
{
return getIDPrefix() + "-" + getNumericalTag();
}
@Override
public char getIDPrefix()
{
return prefix;
}
@Override
public int getNumericalTag()
{
return numericalTag;
}
@Override
public boolean isPermanent()
{
return getIDPrefix() == 'P';
}
}

View File

@ -0,0 +1,82 @@
package me.totalfreedom.datura.banning;
import me.totalfreedom.security.ban.Ban;
import me.totalfreedom.security.ban.BanID;
import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.UUID;
public final class SimpleBan implements Ban
{
private final BanID id;
private final UUID offenderID;
private final String reason;
private final String issuer;
private final Instant creationTime;
private final Instant expiry;
public SimpleBan(
final UUID offenderID,
final String reason,
final String issuer,
final Instant creationTime,
final Instant expiry)
{
if (expiry == null)
{
this.id = BanUID.createPermID();
} else
{
this.id = BanUID.createTempID();
}
this.offenderID = offenderID;
this.reason = reason;
this.issuer = issuer;
this.creationTime = creationTime;
this.expiry = expiry;
}
@Override
public BanID getBanID()
{
return id;
}
@Override
public UUID getOffenderID()
{
return offenderID;
}
@Override
public String getReason()
{
return reason;
}
@Override
public String getBanIssuer()
{
return issuer;
}
@Override
public Instant getCreationTime()
{
return creationTime;
}
@Override
public @Nullable Instant getExpiry()
{
return expiry;
}
@Override
public boolean isExpired()
{
return Instant.now().compareTo(expiry) >= 0;
}
}

View File

@ -0,0 +1,26 @@
package me.totalfreedom.datura.cmd;
import me.totalfreedom.command.CommandBase;
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 org.bukkit.entity.Player;
@Completion(args = {"%player%"}, index = 0)
@Info(name = "kick", description = "Kick a player from the server.", usage = "/kick <player>")
@Permissive(perm = "datura.kick")
public class KickCommand extends CommandBase
{
protected KickCommand(final Datura plugin)
{
super(plugin);
}
@Subcommand(permission = "datura.kick", args = {Player.class})
public void kick(final Player player)
{
player.kickPlayer("You have been kicked from the server.");
}
}

View File

@ -0,0 +1,25 @@
package me.totalfreedom.datura.event;
import me.totalfreedom.event.FEvent;
import me.totalfreedom.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;
}
}

View File

@ -1,7 +1,7 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeType;
import me.totalfreedom.security.perm.Node;
import me.totalfreedom.security.perm.NodeType;
public class DefaultNodes
{

View File

@ -1,8 +1,8 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.security.Group;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.perm.Group;
import me.totalfreedom.security.perm.Node;
import net.kyori.adventure.text.Component;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
@ -27,12 +27,12 @@ public class FreedomGroup implements Group
private final Set<Node> permissions;
private final PermissionAttachment attachment;
public FreedomGroup(Component name,
Component prefix,
Component abbreviation,
int weight,
boolean isDefault,
boolean isHidden)
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;
@ -94,21 +94,21 @@ public class FreedomGroup implements Group
}
@Override
public boolean addPermission(Node node)
public boolean addPermission(final Node node)
{
return permissions().add(node);
}
@Override
public boolean removePermission(Node node)
public boolean removePermission(final Node node)
{
return permissions().remove(node);
}
@Override
public boolean isPermissionSet(@NotNull String name)
public boolean isPermissionSet(@NotNull final String name)
{
Node node = permissions().stream()
final Node node = permissions().stream()
.filter(n -> n.key().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
@ -117,9 +117,9 @@ public class FreedomGroup implements Group
}
@Override
public boolean isPermissionSet(@NotNull Permission perm)
public boolean isPermissionSet(@NotNull final Permission perm)
{
Node node = permissions()
final Node node = permissions()
.stream()
.filter(n -> n.bukkit().equals(perm))
.findFirst()
@ -129,9 +129,9 @@ public class FreedomGroup implements Group
}
@Override
public boolean hasPermission(@NotNull String name)
public boolean hasPermission(@NotNull final String name)
{
Node node = permissions().stream()
final Node node = permissions().stream()
.filter(n -> n.key().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
@ -140,9 +140,9 @@ public class FreedomGroup implements Group
}
@Override
public boolean hasPermission(@NotNull Permission perm)
public boolean hasPermission(@NotNull final Permission perm)
{
Node node = permissions()
final Node node = permissions()
.stream()
.filter(n -> n.bukkit().equals(perm))
.findFirst()
@ -164,33 +164,33 @@ public class FreedomGroup implements Group
* @return This group's PermissionAttachment.
*/
@Override
public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value)
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 Plugin plugin)
public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin)
{
return new PermissionAttachment(plugin, this);
}
@Override
public @Nullable PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks)
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 Plugin plugin, int ticks)
public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, final int ticks)
{
return new PermissionAttachment(plugin, this);
}
@Override
public void removeAttachment(@NotNull PermissionAttachment attachment)
public void removeAttachment(@NotNull final PermissionAttachment attachment)
{
// This method shouldn't do anything, because we don't want to remove our attachment.
}
@ -217,7 +217,7 @@ public class FreedomGroup implements Group
@Override
public boolean isOp()
{
Node node = permissions()
final Node node = permissions()
.stream()
.filter(n -> n.equals(DefaultNodes.OP))
.findFirst()
@ -227,7 +227,7 @@ public class FreedomGroup implements Group
}
@Override
public void setOp(boolean value)
public void setOp(final boolean value)
{
if (value)
{

View File

@ -3,7 +3,7 @@ package me.totalfreedom.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.security.perm.Node;
import me.totalfreedom.user.User;
import me.totalfreedom.user.UserData;
import net.kyori.adventure.text.Component;
@ -16,7 +16,11 @@ import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
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,
@ -32,13 +36,13 @@ public class FreedomUser implements User
private final String NOT_ONLINE = "Player is not online";
private final UserData userData;
public FreedomUser(Player player)
public FreedomUser(final Player player)
{
this.uuid = player.getUniqueId();
this.permissions = new HashSet<>();
this.displayName = player.displayName();
Datura datura = CommonsBase.getInstance()
final Datura datura = CommonsBase.getInstance()
.getRegistrations()
.getModuleRegistry()
.getModule(Datura.class)
@ -77,15 +81,15 @@ public class FreedomUser implements User
}
@Override
public boolean addPermission(Node node)
public boolean addPermission(final Node node)
{
PermissionAttachment attachment = addAttachment(CommonsBase.getInstance(), node.key(), node.value());
final PermissionAttachment attachment = addAttachment(CommonsBase.getInstance(), node.key(), node.value());
bukkitAttachments.put(node, attachment);
return permissions().add(node);
}
@Override
public boolean removePermission(Node node)
public boolean removePermission(final Node node)
{
removeAttachment(bukkitAttachments.get(node));
bukkitAttachments.remove(node);
@ -105,37 +109,37 @@ public class FreedomUser implements User
}
@Override
public boolean isPermissionSet(@NotNull String name)
public boolean isPermissionSet(@NotNull final String name)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
return player != null && player.isPermissionSet(name);
}
@Override
public boolean isPermissionSet(@NotNull Permission perm)
public boolean isPermissionSet(@NotNull final Permission perm)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
return player != null && player.isPermissionSet(perm);
}
@Override
public boolean hasPermission(@NotNull String name)
public boolean hasPermission(@NotNull final String name)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
return player != null && player.hasPermission(name);
}
@Override
public boolean hasPermission(@NotNull Permission perm)
public boolean hasPermission(@NotNull final Permission perm)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
return player != null && player.hasPermission(perm);
}
@Override
public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value)
public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, final boolean value)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player != null)
{
return player.addAttachment(plugin, name, value);
@ -145,9 +149,9 @@ public class FreedomUser implements User
}
@Override
public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin)
public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player != null)
{
return player.addAttachment(plugin);
@ -157,9 +161,9 @@ public class FreedomUser implements User
}
@Override
public @Nullable PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks)
public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, final boolean value, final int ticks)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player != null)
{
return player.addAttachment(plugin, name, value, ticks);
@ -169,9 +173,9 @@ public class FreedomUser implements User
}
@Override
public @Nullable PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks)
public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, final int ticks)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player != null)
{
return player.addAttachment(plugin, ticks);
@ -181,9 +185,9 @@ public class FreedomUser implements User
}
@Override
public void removeAttachment(@NotNull PermissionAttachment attachment)
public void removeAttachment(@NotNull final PermissionAttachment attachment)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player != null)
{
player.removeAttachment(attachment);
@ -195,7 +199,7 @@ public class FreedomUser implements User
@Override
public void recalculatePermissions()
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player != null)
{
player.recalculatePermissions();
@ -207,7 +211,7 @@ public class FreedomUser implements User
@Override
public @NotNull Set<PermissionAttachmentInfo> getEffectivePermissions()
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player != null)
{
return player.getEffectivePermissions();
@ -223,7 +227,7 @@ public class FreedomUser implements User
}
@Override
public void setOp(boolean value)
public void setOp(final boolean value)
{
if (value)
{

View File

@ -1,7 +1,7 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeType;
import me.totalfreedom.security.perm.Node;
import me.totalfreedom.security.perm.NodeType;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
@ -21,7 +21,7 @@ record PermissionNode(String key,
}
@Override
public boolean compare(Node node)
public boolean compare(final Node node)
{
return node.key().equalsIgnoreCase(key())
&& node.value() == value()

View File

@ -1,8 +1,8 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeBuilder;
import me.totalfreedom.security.NodeType;
import me.totalfreedom.security.perm.Node;
import me.totalfreedom.security.perm.NodeBuilder;
import me.totalfreedom.security.perm.NodeType;
public class PermissionNodeBuilder implements NodeBuilder
{
@ -14,42 +14,42 @@ public class PermissionNodeBuilder implements NodeBuilder
private boolean negated = false;
@Override
public NodeBuilder key(String key)
public NodeBuilder key(final String key)
{
this.key = key;
return this;
}
@Override
public NodeBuilder value(boolean value)
public NodeBuilder value(final boolean value)
{
this.value = value;
return this;
}
@Override
public NodeBuilder expiry(long expiry)
public NodeBuilder expiry(final long expiry)
{
this.expiry = expiry;
return this;
}
@Override
public NodeBuilder type(NodeType type)
public NodeBuilder type(final NodeType type)
{
this.type = type;
return this;
}
@Override
public NodeBuilder wildcard(boolean wildcard)
public NodeBuilder wildcard(final boolean wildcard)
{
this.wildcard = wildcard;
return this;
}
@Override
public NodeBuilder negated(boolean negated)
public NodeBuilder negated(final boolean negated)
{
this.negated = negated;
return this;

View File

@ -12,7 +12,13 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.DoubleUnaryOperator;
public class Cager extends Service
@ -34,18 +40,18 @@ public class Cager extends Service
*
* @param uuid The UUID of the player to cage.
*/
public void cagePlayer(UUID uuid)
public void cagePlayer(final UUID uuid)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player == null) return;
cagedPlayers.add(uuid);
cageLocations.put(uuid, createCage(player.getLocation(), Material.GLASS));
}
public void cagePlayer(UUID uuid, Material material)
public void cagePlayer(final UUID uuid, final Material material)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player == null) return;
cagedPlayers.add(uuid);
@ -57,10 +63,10 @@ public class Cager extends Service
*
* @param uuid The UUID of the player to uncage.
*/
public void uncagePlayer(UUID uuid)
public void uncagePlayer(final UUID uuid)
{
cagedPlayers.remove(uuid);
Location location = cageLocations.get(uuid);
final Location location = cageLocations.get(uuid);
createCage(location, Material.AIR); // Remove the cage (set all blocks to air).
@ -78,12 +84,12 @@ public class Cager extends Service
@Override
public void tick()
{
for (UUID uuid : cagedPlayers)
for (final UUID uuid : cagedPlayers)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player == null) continue;
Location cageLocation = getCageLocation(player);
final Location cageLocation = getCageLocation(player);
final boolean inside;
if (!player.getWorld().equals(cageLocation.getWorld()))
@ -108,7 +114,7 @@ public class Cager extends Service
* @param player The player to check.
* @return Whether the player is caged.
*/
public Location getCageLocation(Player player)
public Location getCageLocation(final Player player)
{
return cageLocations.get(player.getUniqueId());
}
@ -119,16 +125,16 @@ public class Cager extends Service
* We use the {@link Shaper} 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 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 Shaper
* @see DoubleUnaryOperator
*/
public Location createCage(Location location, Material material)
public Location createCage(final Location location, final Material material)
{
Shaper shaper = new Shaper(location.getWorld(), 0.0, 4.0);
List<Location> cubed = new LinkedList<>();
final Shaper shaper = new Shaper(location.getWorld(), 0.0, 4.0);
final List<Location> cubed = new LinkedList<>();
cubed.addAll(shaper.generate(5, t -> t, t -> 4.0, t -> t));
cubed.addAll(shaper.generate(5, t -> t, t -> 0.0, t -> t));
cubed.addAll(shaper.generate(5, t -> 0.0, t -> t, t -> t));
@ -136,7 +142,7 @@ public class Cager extends Service
cubed.addAll(shaper.generate(5, t -> t, t -> t, t -> 0.0));
cubed.addAll(shaper.generate(5, t -> t, t -> t, t -> 4.0));
for (Location l : cubed)
for (final Location l : cubed)
{
location.getWorld().getBlockAt(l).setType(material);
}
@ -147,7 +153,7 @@ public class Cager extends Service
private final class CageListener implements Listener
{
@EventHandler
public void blockBreakEvent(BlockBreakEvent event)
public void blockBreakEvent(final BlockBreakEvent event)
{
if (cagedPlayers.contains(event.getPlayer().getUniqueId()))
{
@ -156,7 +162,8 @@ public class Cager extends Service
}
@EventHandler
public void playerLeaveEvent(PlayerQuitEvent event) {
public void playerLeaveEvent(final PlayerQuitEvent event)
{
if (cagedPlayers.contains(event.getPlayer().getUniqueId()))
{
uncagePlayer(event.getPlayer().getUniqueId());

View File

@ -23,7 +23,7 @@ public class Halter implements Listener
}
@EventHandler
public void playerMove(PlayerMoveEvent event)
public void playerMove(final PlayerMoveEvent event)
{
if (haltedPlayers.contains(event.getPlayer().getUniqueId()))
{

View File

@ -22,7 +22,7 @@ public class Locker extends Service
super("locker-service");
}
public void lock(UUID uuid)
public void lock(final UUID uuid)
{
lockedPlayers.add(uuid);
}
@ -32,19 +32,19 @@ public class Locker extends Service
{
lockedPlayers.removeIf(uuid -> !CommonsBase.getInstance().getServer().getOfflinePlayer(uuid).isOnline());
for (UUID uuid : lockedPlayers)
for (final UUID uuid : lockedPlayers)
{
Player player = Bukkit.getPlayer(uuid);
final Player player = Bukkit.getPlayer(uuid);
if (player == null) continue;
lockingMethod(player);
}
}
private void lockingMethod(@NotNull Player player)
private void lockingMethod(@NotNull final Player player)
{
double x = player.getLocation().getX();
double z = player.getLocation().getZ();
final double x = player.getLocation().getX();
final double z = player.getLocation().getZ();
if ((x / z % 0.001) < 1)
{

View File

@ -0,0 +1,89 @@
package me.totalfreedom.datura.sql;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.datura.banning.SimpleBan;
import me.totalfreedom.security.ban.Ban;
import me.totalfreedom.security.ban.BanID;
import me.totalfreedom.sql.SQL;
import me.totalfreedom.utils.FreedomLogger;
import java.sql.SQLException;
import java.time.Instant;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class DBBan
{
private final SQL sql;
public DBBan(final SQL sql)
{
this.sql = sql;
}
public CompletableFuture<Ban> fromSQL(final BanID id)
{
return sql.executeQuery("SELECT * FROM bans WHERE id = ?", id.getID())
.thenApplyAsync(result ->
{
try
{
if (result.next())
{
final UUID uuid = UUID.fromString(result.getString("uuid"));
final Instant timestamp = Instant.parse(result.getString("timestamp"));
final Instant expiry;
final String ex = result.getString("expiry");
if (ex.equals("-1"))
{
expiry = null;
} else
{
expiry = Instant.parse(ex);
}
return new SimpleBan(uuid,
result.getString("reason"),
result.getString("issuer"),
timestamp,
expiry);
}
} catch (SQLException e)
{
FreedomLogger.getLogger("Datura")
.error(e.getMessage());
}
return null;
}, CommonsBase.getInstance().getExecutor().getAsync());
}
public void addBan(final Ban ban)
{
sql.executeUpdate("INSERT INTO bans (id, uuid, reason, issuer, timestamp, expiry) VALUES (?, ?, ?, ?, ?, ?)",
ban.getBanID().getID(),
ban.getOffenderID().toString(),
ban.getReason(),
ban.getBanIssuer(),
ban.getCreationTime().toString(),
(ban.getExpiry() != null ? ban.getExpiry().toString() : "-1")
);
}
public boolean hasEntry(final UUID uuid) {
return sql.executeQuery("SELECT * FROM bans WHERE uuid = ?", uuid.toString())
.thenApplyAsync(result ->
{
try
{
return result.next();
} catch (SQLException e)
{
FreedomLogger.getLogger("Datura")
.error(e.getMessage());
}
return false;
}, CommonsBase.getInstance().getExecutor().getAsync())
.join();
}
}

View File

@ -1,8 +1,13 @@
package me.totalfreedom.datura.sql;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.sql.SQL;
import java.sql.*;
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;
@ -10,7 +15,7 @@ public class MySQL implements SQL
{
private String url = "jdbc:mysql://";
public MySQL(String host, int port, String database) {
public MySQL(final String host, final int port, final String database) {
url += host + ":" + port + "/" + database;
}
@ -21,7 +26,7 @@ public class MySQL implements SQL
* @param username The username to add
* @param password The password to add
*/
public void addCredentials(String username, String password) {
public void addCredentials(final String username, final String password) {
if (url.contains("?user=")) {
url = url.split("\\x3f")[0];
}
@ -30,7 +35,7 @@ public class MySQL implements SQL
}
@Override
public CompletableFuture<Connection> getConnection(String url)
public CompletableFuture<Connection> getConnection(final String url)
{
return CompletableFuture.supplyAsync(() -> {
try {
@ -39,16 +44,16 @@ public class MySQL implements SQL
throw new CompletionException("Failed to connect to the database: "
+ url + "\n", ex);
}
});
}, CommonsBase.getInstance().getExecutor().getAsync());
}
@Override
public CompletableFuture<PreparedStatement> prepareStatement(String query, Object... args)
public CompletableFuture<PreparedStatement> prepareStatement(final String query, final Object... args)
{
return getConnection(url)
.thenApplyAsync(connection -> {
try {
PreparedStatement statement = connection.prepareStatement(query);
final PreparedStatement statement = connection.prepareStatement(query);
for (int i = 0; i < args.length; i++) {
statement.setObject(i + 1, args[i]);
}
@ -57,11 +62,11 @@ public class MySQL implements SQL
throw new CompletionException("Failed to prepare statement: "
+ query + "\n", ex);
}
});
}, CommonsBase.getInstance().getExecutor().getAsync());
}
@Override
public CompletableFuture<ResultSet> executeQuery(String query, Object... args)
public CompletableFuture<ResultSet> executeQuery(final String query, final Object... args)
{
return prepareStatement(query, args)
.thenApplyAsync(statement -> {
@ -71,11 +76,11 @@ public class MySQL implements SQL
throw new CompletionException("Failed to retrieve a result set from query: "
+ query + "\n", ex);
}
});
}, CommonsBase.getInstance().getExecutor().getAsync());
}
@Override
public CompletableFuture<Integer> executeUpdate(String query, Object... args)
public CompletableFuture<Integer> executeUpdate(final String query, final Object... args)
{
return prepareStatement(query, args)
.thenApplyAsync(statement -> {
@ -85,11 +90,11 @@ public class MySQL implements SQL
throw new CompletionException("Failed to execute update: "
+ query + "\n", ex);
}
});
}, CommonsBase.getInstance().getExecutor().getAsync());
}
@Override
public CompletableFuture<Boolean> execute(String query, Object... args)
public CompletableFuture<Boolean> execute(final String query, final Object... args)
{
return prepareStatement(query, args)
.thenApplyAsync(statement -> {
@ -99,13 +104,13 @@ public class MySQL implements SQL
throw new CompletionException("Failed to execute statement: "
+ query + "\n", ex);
}
});
}, CommonsBase.getInstance().getExecutor().getAsync());
}
@Override
public CompletableFuture<Boolean> createTable(String table, String... columns)
public CompletableFuture<Boolean> createTable(final String table, final String... columns)
{
StringBuilder query = new StringBuilder();
final StringBuilder query = new StringBuilder();
query.append("CREATE TABLE IF NOT EXISTS ? (");
for (int i = 0; i < columns.length; i++) {

View File

@ -1,8 +1,9 @@
package me.totalfreedom.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.security.perm.Group;
import me.totalfreedom.sql.SQL;
import me.totalfreedom.user.User;
import me.totalfreedom.user.UserData;
@ -22,6 +23,7 @@ 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 frozen;
@ -35,6 +37,8 @@ public class SimpleUserData implements UserData
this.uuid = player.getUniqueId();
this.username = player.getName();
this.user = new FreedomUser(player);
CommonsBase.getInstance().getEventBus().addEvent(event);
}
private SimpleUserData(
@ -61,7 +65,7 @@ public class SimpleUserData implements UserData
this.transactionsFrozen = transactionsFrozen;
}
public static SimpleUserData fromSQL(SQL sql, String uuid)
public static SimpleUserData fromSQL(final SQL sql, final String uuid)
{
return sql.executeQuery("SELECT * FROM users WHERE UUID = ?", uuid)
.thenApplyAsync(result ->
@ -70,45 +74,45 @@ public class SimpleUserData implements UserData
{
if (result.next())
{
String g = result.getString("group");
final String g = result.getString("group");
UUID u = UUID.fromString(uuid);
String username = result.getString("username");
final UUID u = UUID.fromString(uuid);
final String username = result.getString("username");
Player player = Bukkit.getPlayer(u);
final Player player = Bukkit.getPlayer(u);
if (player == null)
throw new IllegalStateException("Player should be online but they are not!");
User user = new FreedomUser(player);
Group group = CommonsBase.getInstance()
final User user = new FreedomUser(player);
final Group group = CommonsBase.getInstance()
.getRegistrations()
.getGroupRegistry()
.getGroup(g);
long playtime = result.getLong("playtime");
boolean frozen = result.getBoolean("frozen");
boolean canInteract = result.getBoolean("canInteract");
boolean caged = result.getBoolean("caged");
long balance = result.getLong("balance");
boolean transactionsFrozen = result.getBoolean("transactionsFrozen");
final long playtime = result.getLong("playtime");
final boolean frozen = result.getBoolean("frozen");
final boolean canInteract = result.getBoolean("canInteract");
final boolean caged = result.getBoolean("caged");
final long balance = result.getLong("balance");
final boolean transactionsFrozen = result.getBoolean("transactionsFrozen");
return new SimpleUserData(u, username, user, group, playtime, frozen, canInteract, caged, balance, transactionsFrozen);
}
} catch (SQLException ex)
{
StringBuilder sb = new StringBuilder();
sb.append("An error occurred while trying to retrieve user data for UUID ")
.append(uuid)
.append(" from the database.")
.append("\nCaused by: ")
.append(ExceptionUtils.getRootCauseMessage(ex))
.append("\nStack trace: ")
.append(ExceptionUtils.getStackTrace(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.toString());
.error(sb);
}
Player player = Bukkit.getPlayer(UUID.fromString(uuid));
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);
}, CommonsBase.getInstance()
@ -142,8 +146,9 @@ public class SimpleUserData implements UserData
}
@Override
public void setGroup(@Nullable Group group)
public void setGroup(@Nullable final Group group)
{
event.ping();
this.group = group;
}
@ -154,20 +159,23 @@ public class SimpleUserData implements UserData
}
@Override
public void setPlaytime(long playtime)
public void setPlaytime(final long playtime)
{
event.ping();
this.playtime = playtime;
}
@Override
public void addPlaytime(long playtime)
public void addPlaytime(final long playtime)
{
event.ping();
this.playtime += playtime;
}
@Override
public void resetPlaytime()
{
event.ping();
this.playtime = 0L;
}
@ -178,8 +186,9 @@ public class SimpleUserData implements UserData
}
@Override
public void setFrozen(boolean frozen)
public void setFrozen(final boolean frozen)
{
event.ping();
this.frozen = true;
}
@ -190,8 +199,9 @@ public class SimpleUserData implements UserData
}
@Override
public void setInteractionState(boolean canInteract)
public void setInteractionState(final boolean canInteract)
{
event.ping();
this.canInteract = canInteract;
}
@ -202,8 +212,9 @@ public class SimpleUserData implements UserData
}
@Override
public void setCaged(boolean caged)
public void setCaged(final boolean caged)
{
event.ping();
this.caged = caged;
}
@ -220,19 +231,19 @@ public class SimpleUserData implements UserData
}
@Override
public long addToBalance(long amount)
public long addToBalance(final long amount)
{
return balance.addAndGet(amount);
}
@Override
public long removeFromBalance(long amount)
public long removeFromBalance(final long amount)
{
return balance.addAndGet(-amount);
}
@Override
public void setBalance(long newBalance)
public void setBalance(final long newBalance)
{
balance.set(newBalance);
}

View File

@ -1,36 +0,0 @@
package me.totalfreedom.fossil.command;
import me.totalfreedom.command.*;
import me.totalfreedom.command.annotation.Base;
import me.totalfreedom.command.annotation.Info;
import me.totalfreedom.command.annotation.Permissive;
import me.totalfreedom.command.annotation.Subcommand;
import me.totalfreedom.fossil.Fossil;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@Info(name = "kick", description = "Kick a player", usage = "/<command> <player>")
@Permissive(perm = "fossil.kick")
public class KickCommand extends CommandBase
{
public KickCommand(Fossil plugin) {
super(plugin);
}
@Base
public void run(CommandSender sender) {
sender.sendMessage(Component.text("You must specify a player to kick."));
}
@Subcommand(permission = "fossil.kick", args = {Player.class, String.class})
public void kickPlayer(Player player, String string) {
player.kick(Component.text(string));
}
// TODO: Write the code to make this work properly.
@Subcommand(name = "info", permission = "fossil.kick.info", args = {Player.class})
public void playerinfo(Player player) {
}
}

View File

@ -12,7 +12,7 @@ public class SimpleCompletedTransaction implements CompletedTransaction
private final EconomicEntity destination;
private final long balance;
public SimpleCompletedTransaction(Transaction transaction, TransactionResult transactionResult)
public SimpleCompletedTransaction(final Transaction transaction, final TransactionResult transactionResult)
{
this.source = transaction.getSource();

View File

@ -15,16 +15,16 @@ public class SimpleLoggedTransactor implements Transactor
this(new SimpleTransactor(), new SimpleTransactionLogger());
}
public SimpleLoggedTransactor(Transactor transactor, TransactionLogger transactionLogger)
public SimpleLoggedTransactor(final Transactor transactor, final TransactionLogger transactionLogger)
{
this.transactor = transactor;
this.transactionLogger = transactionLogger;
}
@Override
public CompletedTransaction handleTransaction(MutableTransaction transaction)
public CompletedTransaction handleTransaction(final MutableTransaction transaction)
{
CompletedTransaction completedTransaction = transactor.handleTransaction(transaction);
final CompletedTransaction completedTransaction = transactor.handleTransaction(transaction);
transactionLogger.logTransaction(completedTransaction);
return completedTransaction;

View File

@ -5,25 +5,25 @@ import me.totalfreedom.economy.MutableTransaction;
public class SimpleMutableTransaction extends SimpleTransaction implements MutableTransaction
{
public SimpleMutableTransaction(EconomicEntity source, EconomicEntity destination, long balance)
public SimpleMutableTransaction(final EconomicEntity source, final EconomicEntity destination, final long balance)
{
super(source, destination, balance);
}
@Override
public long addToBalance(long amount)
public long addToBalance(final long amount)
{
return balance.addAndGet(amount);
}
@Override
public long removeFromBalance(long amount)
public long removeFromBalance(final long amount)
{
return this.addToBalance(-amount);
}
@Override
public void setBalance(long newBalance)
public void setBalance(final long newBalance)
{
balance.set(newBalance);
}

View File

@ -11,7 +11,7 @@ public class SimpleTransaction implements Transaction
private final EconomicEntity destination;
protected final AtomicLong balance;
public SimpleTransaction(EconomicEntity source, EconomicEntity destination, long balance)
public SimpleTransaction(final EconomicEntity source, final EconomicEntity destination, final long balance)
{
this.source = source;
this.destination = destination;

View File

@ -1,7 +1,10 @@
package me.totalfreedom.fossil.economy;
import me.totalfreedom.audience.MutableAudienceForwarder;
import me.totalfreedom.economy.*;
import me.totalfreedom.economy.TransactionResult;
import me.totalfreedom.economy.CompletedTransaction;
import me.totalfreedom.economy.TransactionLogger;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.utils.FreedomLogger;
import net.kyori.adventure.text.Component;
@ -10,16 +13,16 @@ public class SimpleTransactionLogger implements TransactionLogger
private final MutableAudienceForwarder audience = MutableAudienceForwarder.from(FreedomLogger.getLogger("Fossil"));
@Override
public void logTransaction(CompletedTransaction completedTransaction)
public void logTransaction(final CompletedTransaction completedTransaction)
{
StringBuilder transactionLoggingStatementBuilder = new StringBuilder();
TransactionResult result = completedTransaction.getResult();
boolean resultSuccess = result.isSuccessful();
String resultMessage = result.getMessage();
final StringBuilder transactionLoggingStatementBuilder = new StringBuilder();
final TransactionResult result = completedTransaction.getResult();
final boolean resultSuccess = result.isSuccessful();
final String resultMessage = result.getMessage();
EconomicEntity source = completedTransaction.getSource();
EconomicEntity destination = completedTransaction.getDestination();
long transactionAmount = completedTransaction.getBalance();
final EconomicEntity source = completedTransaction.getSource();
final EconomicEntity destination = completedTransaction.getDestination();
final long transactionAmount = completedTransaction.getBalance();
transactionLoggingStatementBuilder.append(resultSuccess ? "Successful" : "Unsuccessful")
.append(" (")
@ -33,7 +36,7 @@ public class SimpleTransactionLogger implements TransactionLogger
.append(transactionAmount)
.append(".");
Component message = Component.text(transactionLoggingStatementBuilder.toString());
final Component message = Component.text(transactionLoggingStatementBuilder.toString());
audience.sendMessage(message);
}

View File

@ -14,12 +14,12 @@ public class SimpleTransactionResult implements TransactionResult
private final Component component;
private final boolean successful;
public SimpleTransactionResult(String message, boolean successful)
public SimpleTransactionResult(final String message, final boolean successful)
{
this(message, Component.text(message, successful ? NamedTextColor.GREEN : NamedTextColor.RED), successful);
}
public SimpleTransactionResult(String message, Component component, boolean successful)
public SimpleTransactionResult(final String message, final Component component, final boolean successful)
{
this.message = message;
this.component = component;

View File

@ -1,37 +1,41 @@
package me.totalfreedom.fossil.economy;
import me.totalfreedom.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;
public class SimpleTransactor implements Transactor
{
@Override
public CompletedTransaction handleTransaction(MutableTransaction transaction)
public CompletedTransaction handleTransaction(final MutableTransaction transaction)
{
EconomicEntity source = transaction.getSource();
EconomicEntityData sourceData = source.getEconomicData();
final EconomicEntity source = transaction.getSource();
final EconomicEntityData sourceData = source.getEconomicData();
if (sourceData.areTransactionsFrozen())
{
return new SimpleCompletedTransaction(transaction, SimpleTransactionResult.UNAUTHORIZED);
}
long transactionAmount = transaction.getBalance();
final long transactionAmount = transaction.getBalance();
if (transactionAmount >= 0)
{
return new SimpleCompletedTransaction(transaction, SimpleTransactionResult.AMOUNT_TOO_SMALL);
}
long sourceBalance = sourceData.getBalance();
long diff = sourceBalance - transactionAmount;
final long sourceBalance = sourceData.getBalance();
final long diff = sourceBalance - transactionAmount;
if (diff > 0)
{
return new SimpleCompletedTransaction(transaction, SimpleTransactionResult.INSUFFICIENT_FUNDS);
}
EconomicEntity destination = transaction.getDestination();
EconomicEntityData destinationData = destination.getEconomicData();
final EconomicEntity destination = transaction.getDestination();
final EconomicEntityData destinationData = destination.getEconomicData();
if (destinationData.areTransactionsFrozen())
{

View File

@ -0,0 +1,8 @@
name: Fossil
version: 1.0
main: me.totalfreedom.fossil.Fossil
author: TotalFreedom
description: The Fun Module for the Freedom Network.
depend:
- Datura
- Patchwork

View File

@ -11,11 +11,18 @@ import org.bukkit.event.block.Action;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
@FunctionalInterface
public interface Context<T>
{
T get();
default <S> Context<S> map(@NotNull final Function<T, S> mapper)
{
return () -> mapper.apply(get());
}
default @Nullable String asString()
{
if (get() instanceof String string)

View File

@ -28,11 +28,11 @@ public class MutableAudienceForwarder implements Audience
{
private final Set<Audience> audiences = new HashSet<>();
public static MutableAudienceForwarder from(Audience... audiences)
public static MutableAudienceForwarder from(final Audience... audiences)
{
MutableAudienceForwarder audienceForwarder = new MutableAudienceForwarder();
final MutableAudienceForwarder audienceForwarder = new MutableAudienceForwarder();
for (Audience audience : audiences)
for (final Audience audience : audiences)
{
audienceForwarder.addAudience(audience);
}
@ -40,7 +40,7 @@ public class MutableAudienceForwarder implements Audience
return audienceForwarder;
}
public void addAudience(Audience audience)
public void addAudience(final Audience audience)
{
if (audiences.contains(audience) || audience == this /* Protect against honest self-referential calls */)
{
@ -50,14 +50,14 @@ public class MutableAudienceForwarder implements Audience
audiences.add(audience);
}
public boolean removeAudience(Audience audience)
public boolean removeAudience(final Audience audience)
{
return audiences.remove(audience);
}
@Override
public @NotNull Audience filterAudience(@NotNull Predicate<? super Audience> filter)
public @NotNull Audience filterAudience(@NotNull final Predicate<? super Audience> filter)
{
return audiences.stream()
.filter(filter)
@ -66,49 +66,49 @@ public class MutableAudienceForwarder implements Audience
}
@Override
public void forEachAudience(@NotNull Consumer<? super Audience> action)
public void forEachAudience(@NotNull final Consumer<? super Audience> action)
{
audiences.forEach(action);
}
@Override
public void sendMessage(@NotNull ComponentLike message)
public void sendMessage(@NotNull final ComponentLike message)
{
audiences.forEach(a -> a.sendMessage(message));
}
@Override
public void sendMessage(@NotNull Component message)
public void sendMessage(@NotNull final Component message)
{
audiences.forEach(a -> a.sendMessage(message));
}
@Override
public void sendMessage(@NotNull Component message, ChatType.@NotNull Bound boundChatType)
public void sendMessage(@NotNull final Component message, final ChatType.@NotNull Bound boundChatType)
{
audiences.forEach(a -> a.sendMessage(message, boundChatType));
}
@Override
public void sendMessage(@NotNull ComponentLike message, ChatType.@NotNull Bound boundChatType)
public void sendMessage(@NotNull final ComponentLike message, final ChatType.@NotNull Bound boundChatType)
{
audiences.forEach(a -> a.sendMessage(message, boundChatType));
}
@Override
public void sendMessage(@NotNull SignedMessage signedMessage, ChatType.@NotNull Bound boundChatType)
public void sendMessage(@NotNull final SignedMessage signedMessage, final ChatType.@NotNull Bound boundChatType)
{
audiences.forEach(a -> a.sendMessage(signedMessage, boundChatType));
}
@Override
public void deleteMessage(@NotNull SignedMessage signedMessage)
public void deleteMessage(@NotNull final SignedMessage signedMessage)
{
audiences.forEach(a -> a.deleteMessage(signedMessage));
}
@Override
public void deleteMessage(SignedMessage.@NotNull Signature signature)
public void deleteMessage(final SignedMessage.@NotNull Signature signature)
{
audiences.forEach(a -> a.deleteMessage(signature));
}
@ -116,61 +116,61 @@ public class MutableAudienceForwarder implements Audience
// The methods below here will (probably) never be used, however it's good to keep them for completeness' sake.
@Override
public void sendActionBar(@NotNull ComponentLike message)
public void sendActionBar(@NotNull final ComponentLike message)
{
audiences.forEach(a -> a.sendActionBar(message));
}
@Override
public void sendActionBar(@NotNull Component message)
public void sendActionBar(@NotNull final Component message)
{
audiences.forEach(a -> a.sendActionBar(message));
}
@Override
public void sendPlayerListHeader(@NotNull ComponentLike header)
public void sendPlayerListHeader(@NotNull final ComponentLike header)
{
audiences.forEach(a -> a.sendPlayerListHeader(header));
}
@Override
public void sendPlayerListHeader(@NotNull Component header)
public void sendPlayerListHeader(@NotNull final Component header)
{
audiences.forEach(a -> a.sendPlayerListHeader(header));
}
@Override
public void sendPlayerListFooter(@NotNull ComponentLike footer)
public void sendPlayerListFooter(@NotNull final ComponentLike footer)
{
audiences.forEach(a -> a.sendPlayerListFooter(footer));
}
@Override
public void sendPlayerListFooter(@NotNull Component footer)
public void sendPlayerListFooter(@NotNull final Component footer)
{
audiences.forEach(a -> a.sendPlayerListFooter(footer));
}
@Override
public void sendPlayerListHeaderAndFooter(@NotNull ComponentLike header, @NotNull ComponentLike footer)
public void sendPlayerListHeaderAndFooter(@NotNull final ComponentLike header, @NotNull final ComponentLike footer)
{
audiences.forEach(a -> a.sendPlayerListHeaderAndFooter(header, footer));
}
@Override
public void sendPlayerListHeaderAndFooter(@NotNull Component header, @NotNull Component footer)
public void sendPlayerListHeaderAndFooter(@NotNull final Component header, @NotNull final Component footer)
{
audiences.forEach(a -> a.sendPlayerListHeaderAndFooter(header, footer));
}
@Override
public void showTitle(@NotNull Title title)
public void showTitle(@NotNull final Title title)
{
audiences.forEach(a -> a.showTitle(title));
}
@Override
public <T> void sendTitlePart(@NotNull TitlePart<T> part, @NotNull T value)
public <T> void sendTitlePart(@NotNull final TitlePart<T> part, @NotNull final T value)
{
audiences.forEach(a -> a.sendTitlePart(part, value));
}
@ -188,56 +188,56 @@ public class MutableAudienceForwarder implements Audience
}
@Override
public void showBossBar(@NotNull BossBar bar)
public void showBossBar(@NotNull final BossBar bar)
{
audiences.forEach(a -> a.showBossBar(bar));
}
@Override
public void hideBossBar(@NotNull BossBar bar)
public void hideBossBar(@NotNull final BossBar bar)
{
audiences.forEach(a -> a.hideBossBar(bar));
}
@Override
public void playSound(@NotNull Sound sound)
public void playSound(@NotNull final Sound sound)
{
audiences.forEach(a -> a.playSound(sound));
}
@Override
public void playSound(@NotNull Sound sound, double x, double y, double z)
public void playSound(@NotNull final Sound sound, final double x, final double y, final double z)
{
audiences.forEach(a -> a.playSound(sound, x, y, z));
}
@Override
public void playSound(@NotNull Sound sound, Sound.@NotNull Emitter emitter)
public void playSound(@NotNull final Sound sound, final Sound.@NotNull Emitter emitter)
{
audiences.forEach(a -> a.playSound(sound, emitter));
}
@Override
public void stopSound(@NotNull Sound sound)
public void stopSound(@NotNull final Sound sound)
{
audiences.forEach(a -> a.stopSound(sound));
}
@Override
public void stopSound(@NotNull SoundStop stop)
public void stopSound(@NotNull final SoundStop stop)
{
audiences.forEach(a -> a.stopSound(stop));
}
@Override
public void openBook(Book.@NotNull Builder book)
public void openBook(final Book.@NotNull Builder book)
{
audiences.forEach(a -> a.openBook(book));
}
@Override
public void openBook(@NotNull Book book)
public void openBook(@NotNull final Book book)
{
audiences.forEach(a -> a.openBook(book));
}

View File

@ -41,4 +41,9 @@ public class CommonsBase extends JavaPlugin
{
return executor;
}
public EventBus getEventBus()
{
return eventBus;
}
}

View File

@ -1,24 +1,32 @@
package me.totalfreedom.base;
import me.totalfreedom.data.*;
import me.totalfreedom.data.GroupRegistry;
import me.totalfreedom.data.BanRegistry;
import me.totalfreedom.data.ConfigRegistry;
import me.totalfreedom.data.ModuleRegistry;
import me.totalfreedom.data.ServiceRegistry;
import me.totalfreedom.data.UserRegistry;
import me.totalfreedom.data.EventRegistry;
public class Registration
{
private final CommandRegistry commandRegistry;
private final EventRegistry eventRegistry;
private final UserRegistry userRegistry;
private final ServiceRegistry serviceRegistry;
private final ModuleRegistry moduleRegistry;
private final GroupRegistry groupRegistry;
private final BanRegistry banRegistry;
private final ConfigRegistry configRegistry;
public Registration()
{
this.commandRegistry = new CommandRegistry();
this.eventRegistry = new EventRegistry();
this.userRegistry = new UserRegistry();
this.serviceRegistry = new ServiceRegistry();
this.moduleRegistry = new ModuleRegistry();
this.groupRegistry = new GroupRegistry();
this.banRegistry = new BanRegistry();
this.configRegistry = new ConfigRegistry();
}
public ModuleRegistry getModuleRegistry()
@ -26,11 +34,6 @@ public class Registration
return moduleRegistry;
}
public CommandRegistry getCommandRegistry()
{
return commandRegistry;
}
public EventRegistry getEventRegistry()
{
return eventRegistry;
@ -50,4 +53,14 @@ public class Registration
{
return groupRegistry;
}
public BanRegistry getBanRegistry()
{
return banRegistry;
}
public ConfigRegistry getConfigRegistry()
{
return configRegistry;
}
}

View File

@ -1,24 +1,25 @@
package me.totalfreedom.command;
import jdk.jshell.MethodSnippet;
import me.totalfreedom.api.Context;
import me.totalfreedom.command.annotation.Completion;
import me.totalfreedom.command.annotation.Subcommand;
import me.totalfreedom.provider.ContextProvider;
import me.totalfreedom.utils.FreedomLogger;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Set;
public class BukkitDelegator extends Command implements PluginIdentifiableCommand
@ -30,8 +31,8 @@ public class BukkitDelegator extends Command implements PluginIdentifiableComman
BukkitDelegator(final JavaPlugin plugin, final CommandBase command)
{
super(command.getInfo().name());
this.plugin = plugin;
this.command = command;
this.plugin = command.getPlugin();
this.setDescription(command.getInfo().description());
this.setUsage(command.getInfo().usage());
this.setPermission(command.getPerms().perm());
@ -41,7 +42,9 @@ public class BukkitDelegator extends Command implements PluginIdentifiableComman
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args)
public boolean execute(@NotNull final CommandSender sender,
@NotNull final String commandLabel,
@NotNull final String[] args)
{
if (commandLabel.isEmpty() || !commandLabel.equalsIgnoreCase(getName()))
return false;
@ -63,24 +66,27 @@ public class BukkitDelegator extends Command implements PluginIdentifiableComman
if (args.length > 0)
{
ContextProvider provider = new ContextProvider();
Set<Subcommand> nodes = command.getSubcommands().keySet();
for (Subcommand node : nodes) {
Class<?>[] argTypes = node.args();
final ContextProvider provider = new ContextProvider();
final Set<Subcommand> nodes = command.getSubcommands().keySet();
for (final Subcommand node : nodes)
{
final Class<?>[] argTypes = node.args();
if (argTypes.length != args.length)
continue;
Object[] objects = new Object[0];
for (int i = 0; i < argTypes.length; i++) {
Class<?> argType = argTypes[i];
String arg = args[i];
for (int i = 0; i < argTypes.length; i++)
{
final Class<?> argType = argTypes[i];
final String arg = args[i];
if (argType == String.class)
continue;
Context<?> context = () -> provider.fromString(arg);
if (!argType.isInstance(context.get())) {
throw new IllegalStateException();
final Context<?> context = () -> provider.fromString(arg);
if (!argType.isInstance(context.get()))
{
throw new IllegalStateException(); // TODO: Change this.
}
objects = Arrays.copyOf(objects, objects.length + 1);
objects[objects.length - 1] = context.get();
@ -98,10 +104,11 @@ public class BukkitDelegator extends Command implements PluginIdentifiableComman
return false;
}
if (command.getBaseMethodPair() != null) {
if (command.getBaseMethodPair() != null)
{
try
{
command.getBaseMethodPair().getValue().invoke(command, sender);
command.getBaseMethodPair().value().invoke(command, sender);
} catch (Exception ex)
{
FreedomLogger.getLogger("Patchwork")
@ -112,6 +119,50 @@ public class BukkitDelegator extends Command implements PluginIdentifiableComman
return true;
}
@Override
public List<String> tabComplete(final CommandSender sender, final String alias, final String[] args)
{
final Set<Completion> completions = command.getCompletions();
final List<String> results = new ArrayList<>();
for (final Completion completion : completions)
{
if (completion.index() != args.length)
{
continue;
}
for (final String p : completion.args())
{
switch (p)
{
case "%player%" -> results.addAll(Bukkit.getOnlinePlayers()
.stream()
.map(Player::getName)
.toList());
case "%world%" -> results.addAll(Bukkit.getWorlds()
.stream()
.map(World::getName)
.toList());
case "%number%" -> results.addAll(List.of(
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9"));
case "%location%" -> results.add("world,x,y,z");
default -> results.add(p);
}
}
}
return results.stream().filter(s -> s.startsWith(args[args.length - 1])).toList();
}
@Override
public @NotNull Plugin getPlugin()
{

View File

@ -1,15 +1,14 @@
package me.totalfreedom.command;
import me.totalfreedom.command.annotation.Base;
import me.totalfreedom.command.annotation.Info;
import me.totalfreedom.command.annotation.Permissive;
import me.totalfreedom.command.annotation.Subcommand;
import me.totalfreedom.command.annotation.*;
import me.totalfreedom.utils.Pair;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.stream.Stream;
public abstract class CommandBase
@ -18,6 +17,7 @@ public abstract class CommandBase
private final Info info;
private final Permissive perms;
private final Map<Subcommand, Method> subcommands;
private final Set<Completion> completions;
private final Pair<Base, Method> baseMethodPair;
protected CommandBase(final JavaPlugin plugin)
@ -26,10 +26,11 @@ public abstract class CommandBase
this.perms = this.getClass().getDeclaredAnnotation(Permissive.class);
this.plugin = plugin;
this.subcommands = new HashMap<>();
this.completions = new HashSet<>();
if (this.getClass().isAnnotationPresent(Base.class))
{
Method method = Stream.of(this.getClass().getDeclaredMethods())
final Method method = Stream.of(this.getClass().getDeclaredMethods())
.filter(m -> m.isAnnotationPresent(Base.class))
.findFirst()
.orElseThrow(() -> new RuntimeException("Base annotation present but no method found."));
@ -40,9 +41,20 @@ public abstract class CommandBase
this.baseMethodPair = null;
}
registerAnnotations();
}
private void registerAnnotations()
{
Stream.of(this.getClass().getDeclaredMethods())
.filter(method -> method.isAnnotationPresent(Subcommand.class))
.forEach(method -> this.subcommands.put(method.getDeclaredAnnotation(Subcommand.class), method));
.forEach(method -> this.subcommands.put(
method.getDeclaredAnnotation(Subcommand.class),
method));
List.of(this.getClass().getDeclaredAnnotationsByType(Completion.class))
.stream()
.forEach(completions::add);
}
public Pair<Base, Method> getBaseMethodPair()
@ -69,4 +81,9 @@ public abstract class CommandBase
{
return this.subcommands;
}
Set<Completion> getCompletions()
{
return this.completions;
}
}

View File

@ -1,14 +1,13 @@
package me.totalfreedom.command;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
public class CommandHandler
{
private final JavaPlugin plugin;
public CommandHandler(JavaPlugin plugin)
public CommandHandler(final JavaPlugin plugin)
{
this.plugin = plugin;
}
@ -17,8 +16,9 @@ public class CommandHandler
// We need to find a way to resolve PluginCommands so we can
// set the executor and tab completer as necessary.
// OR we need to find an alternative way to process tab completions.
public <T extends CommandBase> void registerCommand(T command) {
BukkitDelegator delegate = new BukkitDelegator(plugin, command);
public <T extends CommandBase> void registerCommand(final T command)
{
final BukkitDelegator delegate = new BukkitDelegator(plugin, command);
Bukkit.getCommandMap().register(plugin.getName(), delegate);
}

View File

@ -0,0 +1,15 @@
package me.totalfreedom.command.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Completion
{
String[] args();
int index();
}

View File

@ -6,8 +6,6 @@ import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Subcommand
{
String name() default "";
String permission();
Class<?>[] args() default {};

View File

@ -0,0 +1,34 @@
package me.totalfreedom.data;
import me.totalfreedom.security.ban.Ban;
import me.totalfreedom.security.ban.BanID;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class BanRegistry
{
private final List<Ban> bansList = new ArrayList<>();
public boolean addBan(final Ban ban) {
return bansList.add(ban);
}
public boolean removeBan(final Ban ban) {
return bansList.remove(ban);
}
@Nullable
public Ban getBan(final BanID banID)
{
for (final Ban ban : bansList)
{
if (ban.getBanID().matches(banID))
{
return ban;
}
}
return null;
}
}

View File

@ -1,61 +0,0 @@
package me.totalfreedom.data;
import co.aikar.commands.*;
import me.totalfreedom.base.CommonsBase;
public class CommandRegistry
{
private final PaperCommandManager manager;
private final PaperCommandContexts contexts;
private final PaperCommandCompletions completions;
private final CommandReplacements replacements;
private final CommandConditions<BukkitCommandIssuer,
BukkitCommandExecutionContext,
BukkitConditionContext> conditions;
public CommandRegistry()
{
this.manager = new PaperCommandManager(CommonsBase.getInstance());
this.contexts = new PaperCommandContexts(manager);
this.completions = new PaperCommandCompletions(manager);
this.replacements = manager.getCommandReplacements();
this.conditions = manager.getCommandConditions();
}
public PaperCommandManager getManager()
{
return manager;
}
public PaperCommandContexts getContexts()
{
return contexts;
}
public PaperCommandCompletions getCompletions()
{
return completions;
}
public CommandReplacements getReplacements()
{
return replacements;
}
public CommandConditions<BukkitCommandIssuer,
BukkitCommandExecutionContext,
BukkitConditionContext> getConditions()
{
return conditions;
}
public void register(BaseCommand cmd)
{
manager.registerCommand(cmd);
}
public void unregister(BaseCommand cmd)
{
manager.unregisterCommand(cmd);
}
}

View File

@ -2,10 +2,25 @@ package me.totalfreedom.data;
import me.totalfreedom.config.Configuration;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
public class ConfigRegistry
{
Set<Configuration> configurationSet = new HashSet<>();
private final Map<String, Configuration> configurationList = new HashMap<>();
public void register(final String name, final Configuration configuration)
{
configurationList.put(name, configuration);
}
public void unregister(final String name)
{
configurationList.remove(name);
}
public Configuration getConfiguration(final String name)
{
return configurationList.get(name);
}
}

View File

@ -31,7 +31,7 @@ public class EventRegistry
{
if (clazz.isInstance(event))
{
return () -> (T) event;
return () -> clazz.cast(event);
}
}
return null;

View File

@ -1,6 +1,6 @@
package me.totalfreedom.data;
import me.totalfreedom.security.Group;
import me.totalfreedom.security.perm.Group;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import java.util.ArrayList;
@ -15,18 +15,18 @@ public class GroupRegistry
this.groups = new ArrayList<>();
}
public boolean registerGroup(Group group) {
public boolean registerGroup(final Group group) {
return groups.add(group);
}
public boolean unregisterGroup(Group group) {
public boolean unregisterGroup(final Group group) {
return groups.remove(group);
}
public Group getGroup(String name) {
PlainTextComponentSerializer s = PlainTextComponentSerializer.plainText();
for (Group group : groups) {
String n = s.serialize(group.getName());
public Group getGroup(final String name) {
final PlainTextComponentSerializer s = PlainTextComponentSerializer.plainText();
for (final Group group : groups) {
final String n = s.serialize(group.getName());
if (n.equalsIgnoreCase(name)) {
return group;
}

View File

@ -29,9 +29,9 @@ public class ModuleRegistry
}
@SuppressWarnings("unchecked")
public <T extends JavaPlugin> ModuleProvider<T> getModule(Class<T> clazz)
public <T extends JavaPlugin> ModuleProvider<T> getModule(final Class<T> clazz)
{
for (JavaPlugin plugin : plugins)
for (final JavaPlugin plugin : plugins)
{
if (clazz.isInstance(plugin))
{

View File

@ -20,7 +20,7 @@ public class ServiceRegistry
public void startAll()
{
for (Service service : this.services)
for (final Service service : this.services)
{
service.start();
}
@ -28,7 +28,7 @@ public class ServiceRegistry
public void stopAll()
{
for (Service service : this.services)
for (final Service service : this.services)
{
service.stop();
}
@ -39,7 +39,7 @@ public class ServiceRegistry
// and calling getClass() on this object would effectively be Class<T>, though we may lose
// the identity of the code signature in the process.
// In this case, that is fine.
public <T extends Service> void register(Plugin plugin, final T service)
public <T extends Service> void register(final Plugin plugin, final T service)
{
this.services.add(service);
if (!service.getClass().isInstance(service))
@ -57,12 +57,12 @@ public class ServiceRegistry
ServicePriority.Normal);
}
public <T extends Service> RegisteredServiceProvider<T> getService(Class<T> clazz)
public <T extends Service> RegisteredServiceProvider<T> getService(final Class<T> clazz)
{
return Bukkit.getServicesManager().getRegistration(clazz);
}
public void unregister(Class<? extends Service> clazz, Service service)
public void unregister(final Class<? extends Service> clazz, final Service service)
{
this.services.remove(service);
Bukkit.getServicesManager().unregister(clazz, service);

View File

@ -15,17 +15,17 @@ public class UserRegistry
this.userDataMap = new HashMap<>();
}
public UserData getUserData(User user)
public UserData getUserData(final User user)
{
return userDataMap.get(user);
}
public void registerUserData(User user, UserData userData)
public void registerUserData(final User user, final UserData userData)
{
userDataMap.put(user, userData);
}
public void unregisterUserData(User user)
public void unregisterUserData(final User user)
{
userDataMap.remove(user);
}

View File

@ -13,20 +13,30 @@ public class EventBus extends Service
private final Set<FEvent> eventSet = new HashSet<>();
private final SubscriptionBox<?> runningSubscriptions = new SubscriptionBox<>();
public EventBus(CommonsBase plugin)
public EventBus(final CommonsBase plugin)
{
super("event_bus");
this.plugin = plugin;
}
public void addEvent(FEvent event)
public void addEvent(final FEvent event)
{
eventSet.add(event);
}
public <T extends FEvent> EventSubscription<T> subscribe(Class<T> eventClass, Callback<T> callback)
public <T extends FEvent> T getEvent(final Class<T> eventClass)
{
Context<T> eventContext = () -> eventSet.stream()
final FEvent e = eventSet.stream()
.filter(event -> event.getEventClass().equals(eventClass))
.findFirst()
.orElse(null);
return eventClass.cast(e);
}
public <T extends FEvent> EventSubscription<T> subscribe(final Class<T> eventClass, final Callback<T> callback)
{
final Context<T> eventContext = () -> eventSet.stream()
.filter(event -> event.getEventClass().equals(eventClass))
.findFirst()
.map(eventClass::cast)
@ -40,7 +50,7 @@ public class EventBus extends Service
return new EventSubscription<>(eventContext.get(), callback);
}
public void unsubscribe(EventSubscription<?> subscription)
public void unsubscribe(final EventSubscription<?> subscription)
{
runningSubscriptions.removeSubscription(subscription);
}

View File

@ -1,36 +1,15 @@
package me.totalfreedom.event;
import me.totalfreedom.api.Context;
import java.util.function.Supplier;
public final class EventSubscription<T extends FEvent>
public record EventSubscription<T extends FEvent>(T event, Callback<T> callback)
{
private final T event;
private final Callback<T> callback;
public EventSubscription(T event, Callback<T> callback)
{
this.event = event;
this.callback = callback;
}
public T getEvent()
{
return event;
}
public boolean cancel()
{
return getEvent().cancel();
return event().cancel();
}
public boolean isCancelled()
{
return getEvent().isCancelled();
}
public Callback<T> getCallback() {
return callback;
return event().isCancelled();
}
}

View File

@ -1,17 +1,29 @@
package me.totalfreedom.event;
import me.totalfreedom.api.Context;
public abstract class FEvent
{
private boolean isCancelled;
private boolean triggered;
protected FEvent()
{
this.isCancelled = false;
}
public abstract void call(Callback<FEvent> callback);
public void ping()
{
this.triggered = true;
}
public void reset()
{
this.triggered = false;
}
boolean shouldCall()
{
return triggered;
}
public boolean cancel()
{

View File

@ -11,15 +11,20 @@ class SubscriptionBox<T extends FEvent>
this.subscriptions = new ArrayList<>();
}
public void addSubscription(EventSubscription<T> subscription) {
public void addSubscription(final EventSubscription<T> subscription) {
subscriptions.add(subscription);
}
public void removeSubscription(EventSubscription<?> subscription) {
public void removeSubscription(final EventSubscription<?> subscription) {
subscriptions.remove(subscription);
}
public void tick() {
subscriptions.forEach(s -> s.getCallback().call(s.getEvent()));
subscriptions.forEach(s -> {
if (!s.event().shouldCall()) return;
s.callback().call(s.event());
s.event().reset();
});
}
}

View File

@ -0,0 +1,11 @@
package me.totalfreedom.particle;
import org.bukkit.Color;
import org.jetbrains.annotations.Nullable;
public interface Trail
{
TrailType getTrailType();
@Nullable Color getColor();
}

View File

@ -0,0 +1,32 @@
package me.totalfreedom.particle;
import org.bukkit.Particle;
public enum TrailType
{
DEFAULT(Particle.REDSTONE),
HEART(Particle.HEART),
FLAME(Particle.FLAME),
RAINBOW(Particle.REDSTONE),
MUSIC(Particle.NOTE),
SNOW(Particle.SNOWBALL),
SPELL(Particle.SPELL_MOB),
SPELL_AMBIENT(Particle.SPELL_MOB_AMBIENT),
PORTAL(Particle.PORTAL),
ENCHANTMENT(Particle.ENCHANTMENT_TABLE),
STROBE(Particle.DUST_COLOR_TRANSITION),
VIBRATION(Particle.VIBRATION),
SPARK(Particle.ELECTRIC_SPARK);
final Particle type;
TrailType(final Particle type)
{
this.type = type;
}
public Particle getType()
{
return type;
}
}

View File

@ -6,6 +6,7 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
@ -13,7 +14,7 @@ import java.util.stream.Stream;
public class ContextProvider
{
public Object fromString(String string)
public Object fromString(final String string)
{
return Stream.of(toBoolean(string),
toDouble(string),
@ -30,7 +31,7 @@ public class ContextProvider
.orElse(string);
}
private @Nullable Boolean toBoolean(String string)
private @Nullable Boolean toBoolean(final String string)
{
try
{
@ -41,7 +42,7 @@ public class ContextProvider
}
}
private @Nullable Double toDouble(String string)
private @Nullable Double toDouble(final String string)
{
try
{
@ -52,7 +53,7 @@ public class ContextProvider
}
}
private @Nullable Integer toInt(String string)
private @Nullable Integer toInt(final String string)
{
try
{
@ -63,7 +64,7 @@ public class ContextProvider
}
}
private @Nullable Long toLong(String string)
private @Nullable Long toLong(final String string)
{
try
{
@ -74,7 +75,7 @@ public class ContextProvider
}
}
private @Nullable Float toFloat(String string)
private @Nullable Float toFloat(final String string)
{
try
{
@ -85,35 +86,48 @@ public class ContextProvider
}
}
private @Nullable Player toPlayer(String string)
private @Nullable Player toPlayer(final String string)
{
return Bukkit.getPlayer(string);
}
private @Nullable CommandSender toCommandSender(String string)
private @Nullable CommandSender toCommandSender(final String string)
{
if (toPlayer(string) == null) return null;
return toPlayer(string);
}
private @Nullable World toWorld(String string)
private @Nullable World toWorld(final String string)
{
return Bukkit.getWorld(string);
}
private @Nullable Location toLocation(String string)
// If we decide to, we can "modify" this to use spaces
// and adjust our inputs accordingly.
/**
* When using this method, the input string must be formatted as
* <br>
* <code>worldName,x,y,z</code>
* <br>
*
* @param string The string to parse
* @return A location object if xyz is valid
*/
private @Nullable Location toLocation(final String string)
{
String[] split = string.split(",");
if (split.length != 4 || toWorld(split[0]) == null) return null;
if (toDouble(split[1]) == null
|| toDouble(split[2]) == null
|| toDouble(split[3]) == null) return null;
final String[] split = string.split(",");
return new Location(toWorld(split[0]), toDouble(split[1]), toDouble(split[2]), toDouble(split[3]));
if (split.length != 4 || toWorld(split[0]) == null) return null;
final double x = Double.parseDouble(split[1]);
final double y = Double.parseDouble(split[2]);
final double z = Double.parseDouble(split[3]);
return new Location(toWorld(split[0]), x, y, z);
}
private @Nullable Component toComponent(String string)
private @NotNull Component toComponent(final String string)
{
return Component.text(string);
}

View File

@ -0,0 +1,78 @@
package me.totalfreedom.security.ban;
import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.UUID;
/**
* Represents a physical ban entry. This is used to store information about a ban,
* such as the player who was banned, the reason for why they were banned, the individual who issued the ban,
* when the ban expires, and when the ban was created.
* <br>
* Ban information is stored in the Database with the {@link BanID} as the PRIMARY KEY.
*/
public interface Ban
{
/**
* Gets the ID of this ban. This is an object which represents a string prefixed with either a T or a P,
* and suffixed with a 6-10 digit numerical code. This is used to identify the ban in the database, and for
* easier ban referencing.
*
* @return The ID of this ban.
*/
BanID getBanID();
/**
* Gets the UUID of the player who was banned. This is formatted as a UUID
* which allows us to retrieve the particular player instance, if applicable, and also
* have a true identifier to check against user logins.
*
* @return The UUID of the player who was banned.
*/
UUID getOffenderID();
/**
* Gets the reason that the player was banned for. Typically, the default reason is "You are banned!".
* We've forced implementations to require a reason, as it's important to know why a player was banned.
*
* @return The reason that the player was banned for.
*/
String getReason();
/**
* Gets the username of the individual who issued the ban. This is not a reliable way to store data, but
* in our case, we should not need to interact with the ban issuer from the code. This is simply for
* reference purposes.
*
* @return The username of the individual who issued the ban.
*/
String getBanIssuer();
/**
* Gets the {@link Instant} which this ban was created.
*
* @return The ban's creation time.
*/
Instant getCreationTime();
/**
* Gets the {@link Instant} which this ban is due to expire, if applicable.
* This method is annotated as {@link Nullable}, as permanent bans do not have an expiry date.
*
* @return The ban's expiry time, or null if the ban is permanent.
*/
@Nullable
Instant getExpiry();
/**
* Checks if the ban has expired. This will return false if:
* <ul>
* <li>The {@link Instant} returned by {@link #getExpiry()} is null.</li>
* <li>The {@link Instant} returned by {@link #getExpiry()} is after the current time.</li>
* </ul>
*
* @return True if the ban has expired, false otherwise.
*/
boolean isExpired();
}

View File

@ -0,0 +1,52 @@
package me.totalfreedom.security.ban;
/**
* Represents an ID for a ban. These are formatted either as:
* <p>
* P-00129381
* <br>
* T-00128381
* <br>
* </p>
* Where P marks a ban as permanent, and T marks a ban as temporary.
*/
public interface BanID
{
/**
* This method returns the full Ban ID.
*
* @return The actual ID.
*/
String getID();
/**
* This method returns the ban type denominator character for the Ban ID.
* This would either be T or P, where T = temporary and P = permanent.
*
* @return The ban type denominator character for the Ban ID.
*/
char getIDPrefix();
/**
* Gets the numerical tag of this ban ID.
* This would be the numerical section of the full Ban ID.
*
* @return The numerical tag of this ban ID.
*/
int getNumericalTag();
/**
* Checks the prefix of the Ban ID to see whether if it is permanent.
*
* @return true if the Ban ID is prefixed with a P, false otherwise.
*/
boolean isPermanent();
default boolean matches(BanID other) {
if (other == null) {
return false;
}
return (getIDPrefix() == other.getIDPrefix())
&& (getNumericalTag() == other.getNumericalTag());
}
}

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security;
package me.totalfreedom.security.perm;
import net.kyori.adventure.text.Component;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security;
package me.totalfreedom.security.perm;
import org.bukkit.permissions.Permission;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security;
package me.totalfreedom.security.perm;
public interface NodeBuilder
{

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security;
package me.totalfreedom.security.perm;
public enum NodeType
{

View File

@ -1,6 +1,5 @@
package me.totalfreedom.security;
package me.totalfreedom.security.perm;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permissible;
import java.util.Set;

View File

@ -2,6 +2,7 @@ package me.totalfreedom.service;
import me.totalfreedom.base.CommonsBase;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Executor;
@ -26,7 +27,7 @@ public class FreedomExecutor
return asyncExecutor;
}
public Executor scheduled(long delay, long period)
public Executor scheduled(final long delay, final long period)
{
return r -> Bukkit.getScheduler()
.runTaskTimer(
@ -36,7 +37,7 @@ public class FreedomExecutor
period);
}
public Executor scheduledAsync(long delay, long period)
public Executor scheduledAsync(final long delay, final long period)
{
return r -> Bukkit.getScheduler()
.runTaskTimerAsynchronously(
@ -46,12 +47,12 @@ public class FreedomExecutor
period);
}
public void runSync(Task task)
public void runSync(@NotNull final Task task)
{
getSync().execute(task);
}
public void runAsync(Task task)
public void runAsync(@NotNull final Task task)
{
getAsync().execute(task);
}

View File

@ -7,7 +7,7 @@ public abstract class Service
private final String name;
private boolean isActive = false;
protected Service(String name)
protected Service(final String name)
{
this.name = name;

View File

@ -7,15 +7,15 @@ import java.util.concurrent.CompletableFuture;
public interface SQL
{
CompletableFuture<Connection> getConnection(String url);
CompletableFuture<Connection> getConnection(final String url);
CompletableFuture<PreparedStatement> prepareStatement(String query, Object... args);
CompletableFuture<PreparedStatement> prepareStatement(final String query, final Object... args);
CompletableFuture<ResultSet> executeQuery(String query, Object... args);
CompletableFuture<ResultSet> executeQuery(final String query, final Object... args);
CompletableFuture<Integer> executeUpdate(String query, Object... args);
CompletableFuture<Integer> executeUpdate(final String query, final Object... args);
CompletableFuture<Boolean> execute(String query, Object... args);
CompletableFuture<Boolean> execute(final String query, final Object... args);
CompletableFuture<Boolean> createTable(String table, String... columns);
CompletableFuture<Boolean> createTable(final String table, final String... columns);
}

View File

@ -9,7 +9,7 @@ public interface SQLProperties
default Properties getDefaultProperties()
{
Properties properties = new Properties();
final Properties properties = new Properties();
properties.setProperty("driver", "sqlite");
properties.setProperty("host", "localhost");
properties.setProperty("port", "3306");

View File

@ -1,8 +1,8 @@
package me.totalfreedom.user;
import me.totalfreedom.security.perm.PermissionHolder;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.EconomicEntityData;
import me.totalfreedom.security.PermissionHolder;
import net.kyori.adventure.text.Component;
public interface User extends PermissionHolder, EconomicEntity

View File

@ -1,7 +1,7 @@
package me.totalfreedom.user;
import me.totalfreedom.security.perm.Group;
import me.totalfreedom.economy.EconomicEntityData;
import me.totalfreedom.security.Group;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

View File

@ -17,22 +17,22 @@ public class FreedomAdventure
private static final PlainTextComponentSerializer PLAIN_TEXT_COMPONENT_SERIALIZER = PlainTextComponentSerializer.plainText();
public static String toPlainText(Component component)
public static String toPlainText(final Component component)
{
return PLAIN_TEXT_COMPONENT_SERIALIZER.serialize(component);
}
public static String toPlainText(Supplier<Component> supplier)
public static String toPlainText(final Supplier<Component> supplier)
{
return toPlainText(supplier.get());
}
public static Supplier<String> supplyPlainText(Supplier<Component> supplier)
public static Supplier<String> supplyPlainText(final Supplier<Component> supplier)
{
return new StringRepresentationSupplier(supplier.get());
}
public static Supplier<String> supplyPlainText(Component component)
public static Supplier<String> supplyPlainText(final Component component)
{
return new StringRepresentationSupplier(component);
}

View File

@ -16,17 +16,17 @@ public class FreedomLogger implements Audience
private final Logger logger;
private boolean debug = false;
private FreedomLogger(String moduleName)
private FreedomLogger(final String moduleName)
{
this.logger = LoggerFactory.getLogger("FreedomNetworkSuite::" + moduleName);
}
public static FreedomLogger getLogger(String moduleName)
public static FreedomLogger getLogger(final String moduleName)
{
return new FreedomLogger(moduleName);
}
public void setDebugMode(boolean debug)
public void setDebugMode(final boolean debug)
{
this.debug = debug;
}
@ -36,7 +36,7 @@ public class FreedomLogger implements Audience
*
* @param message The message to send.
*/
public void info(String message)
public void info(final String message)
{
logger.info(message);
}
@ -47,9 +47,9 @@ public class FreedomLogger implements Audience
* @param component The component to send.
* @return A plain text representation of the message
*/
public String infoComponent(Component component)
public String infoComponent(final Component component)
{
String plainText = FreedomAdventure.toPlainText(component);
final String plainText = FreedomAdventure.toPlainText(component);
logger.info(plainText);
return plainText;
@ -63,7 +63,7 @@ public class FreedomLogger implements Audience
* @param message The message to send.
* @return A component representation of the message.
*/
public Component info(Supplier<String> message)
public Component info(final Supplier<String> message)
{
logger.info(message.get());
return Component.text(message.get());
@ -77,7 +77,7 @@ public class FreedomLogger implements Audience
* @param component The component to send.
* @return A string representation of the message.
*/
public String infoComponent(Supplier<Component> component)
public String infoComponent(final Supplier<Component> component)
{
return this.infoComponent(component.get());
}
@ -87,7 +87,7 @@ public class FreedomLogger implements Audience
*
* @param message The message to send.
*/
public void warn(String message)
public void warn(final String message)
{
logger.warn(message);
}
@ -97,9 +97,9 @@ public class FreedomLogger implements Audience
*
* @param component The component to send.
*/
public void warnComponent(Component component)
public void warnComponent(final Component component)
{
String plainText = FreedomAdventure.toPlainText(component);
final String plainText = FreedomAdventure.toPlainText(component);
logger.warn(plainText);
}
@ -111,7 +111,7 @@ public class FreedomLogger implements Audience
*
* @param message The message to send.
*/
public void error(String message)
public void error(final String message)
{
logger.error(message);
}
@ -121,9 +121,9 @@ public class FreedomLogger implements Audience
*
* @param component The message to send.
*/
public String errorComponent(Component component)
public String errorComponent(final Component component)
{
String plainText = FreedomAdventure.toPlainText(component);
final String plainText = FreedomAdventure.toPlainText(component);
logger.error(plainText);
@ -135,7 +135,7 @@ public class FreedomLogger implements Audience
*
* @param th The exception to log.
*/
public void error(Throwable th)
public void error(final Throwable th)
{
logger.error("An error occurred:\n", th);
}
@ -150,7 +150,7 @@ public class FreedomLogger implements Audience
* @param message The message to send.
* @return A component representation of the message.
*/
public Component error(Supplier<String> message)
public Component error(final Supplier<String> message)
{
logger.error(message.get());
return Component.text(message.get());
@ -164,7 +164,7 @@ public class FreedomLogger implements Audience
* @param component The component to send.
* @return A String representation of the component.
*/
public String errorComponent(Supplier<Component> component)
public String errorComponent(final Supplier<Component> component)
{
return this.errorComponent(component.get());
}
@ -175,7 +175,7 @@ public class FreedomLogger implements Audience
*
* @param message The message to send.
*/
public void debug(String message)
public void debug(final String message)
{
if (debug)
logger.debug(message);
@ -187,9 +187,9 @@ public class FreedomLogger implements Audience
*
* @param component The component to send.
*/
public String debugComponent(Component component)
public String debugComponent(final Component component)
{
String plainText = FreedomAdventure.toPlainText(component);
final String plainText = FreedomAdventure.toPlainText(component);
this.debug(plainText);
@ -205,7 +205,7 @@ public class FreedomLogger implements Audience
* @param message The message to send.
* @return A component representation of the message.
*/
public Component debug(Supplier<String> message)
public Component debug(final Supplier<String> message)
{
if (debug)
{
@ -222,7 +222,7 @@ public class FreedomLogger implements Audience
* @param component The component to send.
* @return A String representation of the message.
*/
public String debugComponent(Supplier<Component> component)
public String debugComponent(final Supplier<Component> component)
{
if (debug)
{
@ -233,9 +233,9 @@ public class FreedomLogger implements Audience
@Override
public void sendMessage(@NotNull ComponentLike message)
public void sendMessage(@NotNull final ComponentLike message)
{
Component component = ComponentLike.unbox(message);
final Component component = ComponentLike.unbox(message);
if (component == null)
{
@ -247,25 +247,25 @@ public class FreedomLogger implements Audience
}
@Override
public void sendMessage(@NotNull Component message)
public void sendMessage(@NotNull final Component message)
{
this.infoComponent(message);
}
@Override
public void sendMessage(@NotNull Component message, ChatType.@NotNull Bound boundChatType)
public void sendMessage(@NotNull final Component message, final ChatType.@NotNull Bound boundChatType)
{
this.infoComponent(message);
}
@Override
public void sendMessage(@NotNull ComponentLike message, ChatType.@NotNull Bound boundChatType)
public void sendMessage(@NotNull final ComponentLike message, final ChatType.@NotNull Bound boundChatType)
{
this.sendMessage(message);
}
@Override
public void sendMessage(@NotNull SignedMessage signedMessage, ChatType.@NotNull Bound boundChatType)
public void sendMessage(@NotNull final SignedMessage signedMessage, final ChatType.@NotNull Bound boundChatType)
{
this.info(signedMessage.message()); // TODO: We might want to investigate whether this logs the ENTIRE message, including unsigned & signed content, or only the signed part. This method was written in the assumption that it provided all content.
}

View File

@ -8,7 +8,7 @@ public class Identity
private final UUID id;
public Identity(String key)
public Identity(final String key)
{
this.key = key;
this.id = UUID.nameUUIDFromBytes(key.getBytes());

View File

@ -1,22 +1,5 @@
package me.totalfreedom.utils;
public class Pair<K, V>
public record Pair<K, V>(K key, V value)
{
private final K key;
private final V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey()
{
return key;
}
public V getValue()
{
return value;
}
}

View File

@ -13,24 +13,24 @@ public class Shaper
private final double end;
private final World world;
public Shaper(World world, double start, double end)
public Shaper(final World world, final double start, final double end)
{
this.start = start;
this.end = end;
this.world = world;
}
public List<Location> generate(int count, DoubleUnaryOperator x, DoubleUnaryOperator y, DoubleUnaryOperator z)
public List<Location> generate(final int count, final DoubleUnaryOperator x, final DoubleUnaryOperator y, final DoubleUnaryOperator z)
{
double step = (start - end) / (count - 1);
LinkedList<Location> lset = new LinkedList<>();
final double step = (start - end) / (count - 1);
final LinkedList<Location> lset = new LinkedList<>();
for (int i = 0; i < count; i++)
{
double t = start + i * step;
double xp = x.applyAsDouble(t);
double yp = y.applyAsDouble(t);
double zp = z.applyAsDouble(t);
final double t = start + i * step;
final double xp = x.applyAsDouble(t);
final double yp = y.applyAsDouble(t);
final double zp = z.applyAsDouble(t);
lset.add(new Location(world, xp, yp, zp));
}

15
checkstyle.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"https://www.checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="TreeWalker">
<module name="FinalLocalVariable">
<property name="validateEnhancedForLoopVariable" value="true"/>
</module>
<module name="FinalParameters"/>
<module name="AvoidStaticImport"/>
<module name="UnusedImports"/>
<module name="AvoidStarImportCheck"/>
</module>
</module>