diff --git a/Datura/src/main/java/me/totalfreedom/datura/banning/BanUID.java b/Datura/src/main/java/me/totalfreedom/datura/banning/BanUID.java new file mode 100644 index 0000000..1869664 --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/banning/BanUID.java @@ -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(); + + 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'; + } +} diff --git a/Datura/src/main/java/me/totalfreedom/datura/banning/SimpleBan.java b/Datura/src/main/java/me/totalfreedom/datura/banning/SimpleBan.java new file mode 100644 index 0000000..ff67d94 --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/banning/SimpleBan.java @@ -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; + } +} diff --git a/Datura/src/main/java/me/totalfreedom/datura/event/UserDataUpdateEvent.java b/Datura/src/main/java/me/totalfreedom/datura/event/UserDataUpdateEvent.java new file mode 100644 index 0000000..3679532 --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/event/UserDataUpdateEvent.java @@ -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(UserData data) + { + this.data = data; + } + + public UserData getData() + { + return data; + } + + @Override + public Class getEventClass() + { + return UserDataUpdateEvent.class; + } +} diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java b/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java index af259bf..42144f0 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java @@ -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 { diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java index 9c6b98b..4ffd8c1 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java @@ -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; diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java index c1c30af..f77b201 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java @@ -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; diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java index 0e97d98..255da0a 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java @@ -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; diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNodeBuilder.java b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNodeBuilder.java index 75dcc77..11606fe 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNodeBuilder.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNodeBuilder.java @@ -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 { diff --git a/Datura/src/main/java/me/totalfreedom/datura/sql/DBBan.java b/Datura/src/main/java/me/totalfreedom/datura/sql/DBBan.java new file mode 100644 index 0000000..efc99ba --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/sql/DBBan.java @@ -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(SQL sql) + { + this.sql = sql; + } + + public CompletableFuture fromSQL(BanID id) + { + return sql.executeQuery("SELECT * FROM bans WHERE id = ?", id.getID()) + .thenApplyAsync(result -> + { + try + { + if (result.next()) + { + UUID uuid = UUID.fromString(result.getString("uuid")); + Instant timestamp = Instant.parse(result.getString("timestamp")); + + final Instant expiry; + 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(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(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(); + } +} diff --git a/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java b/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java index 5adbe09..baaf132 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java +++ b/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java @@ -1,5 +1,6 @@ package me.totalfreedom.datura.sql; +import me.totalfreedom.base.CommonsBase; import me.totalfreedom.sql.SQL; import java.sql.*; @@ -39,7 +40,7 @@ public class MySQL implements SQL throw new CompletionException("Failed to connect to the database: " + url + "\n", ex); } - }); + }, CommonsBase.getInstance().getExecutor().getAsync()); } @Override @@ -57,7 +58,7 @@ public class MySQL implements SQL throw new CompletionException("Failed to prepare statement: " + query + "\n", ex); } - }); + }, CommonsBase.getInstance().getExecutor().getAsync()); } @Override @@ -71,7 +72,7 @@ public class MySQL implements SQL throw new CompletionException("Failed to retrieve a result set from query: " + query + "\n", ex); } - }); + }, CommonsBase.getInstance().getExecutor().getAsync()); } @Override @@ -85,7 +86,7 @@ public class MySQL implements SQL throw new CompletionException("Failed to execute update: " + query + "\n", ex); } - }); + }, CommonsBase.getInstance().getExecutor().getAsync()); } @Override @@ -99,7 +100,7 @@ public class MySQL implements SQL throw new CompletionException("Failed to execute statement: " + query + "\n", ex); } - }); + }, CommonsBase.getInstance().getExecutor().getAsync()); } @Override diff --git a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java index cb6db2a..ad3b174 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java @@ -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; @@ -21,6 +22,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; @@ -32,6 +34,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( @@ -86,17 +90,16 @@ public class SimpleUserData implements UserData } } 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)); + 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)); @@ -135,6 +138,7 @@ public class SimpleUserData implements UserData @Override public void setGroup(@Nullable Group group) { + event.ping(); this.group = group; } @@ -147,18 +151,21 @@ public class SimpleUserData implements UserData @Override public void setPlaytime(long playtime) { + event.ping(); this.playtime = playtime; } @Override public void addPlaytime(long playtime) { + event.ping(); this.playtime += playtime; } @Override public void resetPlaytime() { + event.ping(); this.playtime = 0L; } @@ -171,6 +178,7 @@ public class SimpleUserData implements UserData @Override public void setFrozen(boolean frozen) { + event.ping(); this.frozen = true; } @@ -183,6 +191,7 @@ public class SimpleUserData implements UserData @Override public void setInteractionState(boolean canInteract) { + event.ping(); this.canInteract = canInteract; } @@ -195,6 +204,7 @@ public class SimpleUserData implements UserData @Override public void setCaged(boolean caged) { + event.ping(); this.caged = caged; } } diff --git a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java index 5e8fc94..999c940 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java @@ -41,4 +41,9 @@ public class CommonsBase extends JavaPlugin { return executor; } + + public EventBus getEventBus() + { + return eventBus; + } } diff --git a/Patchwork/src/main/java/me/totalfreedom/data/BanRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/BanRegistry.java new file mode 100644 index 0000000..b2ad3cf --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/data/BanRegistry.java @@ -0,0 +1,35 @@ +package me.totalfreedom.data; + +import me.totalfreedom.security.ban.Ban; +import me.totalfreedom.security.ban.BanID; +import me.totalfreedom.sql.SQL; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class BanRegistry +{ + private final List bansList = new ArrayList<>(); + + public boolean addBan(Ban ban) { + return bansList.add(ban); + } + + public boolean removeBan(Ban ban) { + return bansList.remove(ban); + } + + @Nullable + public Ban getBan(BanID banID) + { + for (Ban ban : bansList) + { + if (ban.getBanID().matches(banID)) + { + return ban; + } + } + return null; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java index b6b8d91..2395758 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java @@ -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 configurationSet = new HashSet<>(); + private final Map configurationList = new HashMap<>(); + + public void register(String name, Configuration configuration) + { + configurationList.put(name, configuration); + } + + public void unregister(String name) + { + configurationList.remove(name); + } + + public Configuration getConfiguration(String name) + { + return configurationList.get(name); + } } diff --git a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java index 74d4c6e..578d422 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java @@ -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; diff --git a/Patchwork/src/main/java/me/totalfreedom/event/EventBus.java b/Patchwork/src/main/java/me/totalfreedom/event/EventBus.java index 1333b71..e4b0461 100644 --- a/Patchwork/src/main/java/me/totalfreedom/event/EventBus.java +++ b/Patchwork/src/main/java/me/totalfreedom/event/EventBus.java @@ -24,6 +24,16 @@ public class EventBus extends Service eventSet.add(event); } + public T getEvent(Class eventClass) + { + FEvent e = eventSet.stream() + .filter(event -> event.getEventClass().equals(eventClass)) + .findFirst() + .orElse(null); + + return eventClass.cast(e); + } + public EventSubscription subscribe(Class eventClass, Callback callback) { Context eventContext = () -> eventSet.stream() diff --git a/Patchwork/src/main/java/me/totalfreedom/event/EventSubscription.java b/Patchwork/src/main/java/me/totalfreedom/event/EventSubscription.java index 0915187..ac7bad1 100644 --- a/Patchwork/src/main/java/me/totalfreedom/event/EventSubscription.java +++ b/Patchwork/src/main/java/me/totalfreedom/event/EventSubscription.java @@ -1,36 +1,15 @@ package me.totalfreedom.event; -import me.totalfreedom.api.Context; - -import java.util.function.Supplier; - -public final class EventSubscription +public record EventSubscription(T event, Callback callback) { - private final T event; - private final Callback callback; - - public EventSubscription(T event, Callback 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 getCallback() { - return callback; + return event().isCancelled(); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/event/FEvent.java b/Patchwork/src/main/java/me/totalfreedom/event/FEvent.java index 0889d7b..9aa68d7 100644 --- a/Patchwork/src/main/java/me/totalfreedom/event/FEvent.java +++ b/Patchwork/src/main/java/me/totalfreedom/event/FEvent.java @@ -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 callback); + public void ping() + { + this.triggered = true; + } + + public void reset() + { + this.triggered = false; + } + + boolean shouldCall() + { + return triggered; + } public boolean cancel() { diff --git a/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java b/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java index c55325e..ffb6bef 100644 --- a/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java +++ b/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java @@ -1,5 +1,7 @@ package me.totalfreedom.event; +import com.sun.source.tree.ContinueTree; + import java.util.ArrayList; import java.util.List; @@ -20,6 +22,11 @@ class SubscriptionBox } 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(); + }); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java index a8e14a4..0e7c76b 100644 --- a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java +++ b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java @@ -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; @@ -113,7 +114,7 @@ public class ContextProvider return new Location(toWorld(split[0]), toDouble(split[1]), toDouble(split[2]), toDouble(split[3])); } - private @Nullable Component toComponent(String string) + private @NotNull Component toComponent(String string) { return Component.text(string); } diff --git a/Patchwork/src/main/java/me/totalfreedom/security/ban/Ban.java b/Patchwork/src/main/java/me/totalfreedom/security/ban/Ban.java new file mode 100644 index 0000000..438b5f8 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/security/ban/Ban.java @@ -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. + *
+ * 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: + *
    + *
  • The {@link Instant} returned by {@link #getExpiry()} is null.
  • + *
  • The {@link Instant} returned by {@link #getExpiry()} is after the current time.
  • + *
+ * + * @return True if the ban has expired, false otherwise. + */ + boolean isExpired(); +} diff --git a/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java b/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java new file mode 100644 index 0000000..79c175f --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java @@ -0,0 +1,52 @@ +package me.totalfreedom.security.ban; + +/** + * Represents an ID for a ban. These are formatted either as: + *

+ * P-00129381 + *
+ * T-00128381 + *
+ *

+ * 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()); + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/security/Group.java b/Patchwork/src/main/java/me/totalfreedom/security/perm/Group.java similarity index 86% rename from Patchwork/src/main/java/me/totalfreedom/security/Group.java rename to Patchwork/src/main/java/me/totalfreedom/security/perm/Group.java index d09ba61..a0f1dcd 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/Group.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/perm/Group.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security; +package me.totalfreedom.security.perm; import net.kyori.adventure.text.Component; diff --git a/Patchwork/src/main/java/me/totalfreedom/security/Node.java b/Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java similarity index 91% rename from Patchwork/src/main/java/me/totalfreedom/security/Node.java rename to Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java index af7a014..d31f054 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/Node.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security; +package me.totalfreedom.security.perm; import org.bukkit.permissions.Permission; diff --git a/Patchwork/src/main/java/me/totalfreedom/security/NodeBuilder.java b/Patchwork/src/main/java/me/totalfreedom/security/perm/NodeBuilder.java similarity index 88% rename from Patchwork/src/main/java/me/totalfreedom/security/NodeBuilder.java rename to Patchwork/src/main/java/me/totalfreedom/security/perm/NodeBuilder.java index c0503ff..6769556 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/NodeBuilder.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/perm/NodeBuilder.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security; +package me.totalfreedom.security.perm; public interface NodeBuilder { diff --git a/Patchwork/src/main/java/me/totalfreedom/security/NodeType.java b/Patchwork/src/main/java/me/totalfreedom/security/perm/NodeType.java similarity index 70% rename from Patchwork/src/main/java/me/totalfreedom/security/NodeType.java rename to Patchwork/src/main/java/me/totalfreedom/security/perm/NodeType.java index 11293a9..31c5b83 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/NodeType.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/perm/NodeType.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security; +package me.totalfreedom.security.perm; public enum NodeType { diff --git a/Patchwork/src/main/java/me/totalfreedom/security/PermissionHolder.java b/Patchwork/src/main/java/me/totalfreedom/security/perm/PermissionHolder.java similarity index 80% rename from Patchwork/src/main/java/me/totalfreedom/security/PermissionHolder.java rename to Patchwork/src/main/java/me/totalfreedom/security/perm/PermissionHolder.java index 8095794..f15ec15 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/PermissionHolder.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/perm/PermissionHolder.java @@ -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; diff --git a/Patchwork/src/main/java/me/totalfreedom/user/User.java b/Patchwork/src/main/java/me/totalfreedom/user/User.java index 222e2a9..839abf5 100644 --- a/Patchwork/src/main/java/me/totalfreedom/user/User.java +++ b/Patchwork/src/main/java/me/totalfreedom/user/User.java @@ -1,6 +1,6 @@ package me.totalfreedom.user; -import me.totalfreedom.security.PermissionHolder; +import me.totalfreedom.security.perm.PermissionHolder; import net.kyori.adventure.text.Component; public interface User extends PermissionHolder diff --git a/Patchwork/src/main/java/me/totalfreedom/user/UserData.java b/Patchwork/src/main/java/me/totalfreedom/user/UserData.java index ac2e277..75dea74 100644 --- a/Patchwork/src/main/java/me/totalfreedom/user/UserData.java +++ b/Patchwork/src/main/java/me/totalfreedom/user/UserData.java @@ -1,6 +1,6 @@ package me.totalfreedom.user; -import me.totalfreedom.security.Group; +import me.totalfreedom.security.perm.Group; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/MICheck.java b/Patchwork/src/main/java/me/totalfreedom/utils/MICheck.java new file mode 100644 index 0000000..f9210e8 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/utils/MICheck.java @@ -0,0 +1,14 @@ +package me.totalfreedom.utils; + +public class MICheck +{ + public double maintainabilityIndex(double fileLength, double vocabulary, double cyclomaticComplexity, double linesOfCode) { + double halsteadVolume = fileLength * (Math.log(vocabulary) / Math.log(2)); + double maintainabilityIndexUnbounded = 171 - 5.2 * Math.log(halsteadVolume) - 0.23 * cyclomaticComplexity - 16.2 * Math.log(linesOfCode); + return Math.max(0, maintainabilityIndexUnbounded * 100 / 171); + } + + public double complexity(double decisionPoints) { + return decisionPoints + 1; + } +}