diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a05d85a..fffd44b 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -22,13 +22,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' - - name: Build with Gradle - uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - with: - arguments: build + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Build with Gradle + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + with: + arguments: build diff --git a/Corvo/src/main/java/me/totalfreedom/corvo/Corvo.java b/Corvo/src/main/java/me/totalfreedom/corvo/Corvo.java index eb9f414..ba1670b 100644 --- a/Corvo/src/main/java/me/totalfreedom/corvo/Corvo.java +++ b/Corvo/src/main/java/me/totalfreedom/corvo/Corvo.java @@ -6,18 +6,20 @@ import org.bukkit.plugin.java.JavaPlugin; public class Corvo extends JavaPlugin { @Override - public void onEnable() { + public void onDisable() + { CommonsBase.getInstance() - .getRegistrations() - .getModuleRegistry() - .addModule(this); + .getRegistrations() + .getModuleRegistry() + .removeModule(this); } @Override - public void onDisable() { + public void onEnable() + { CommonsBase.getInstance() - .getRegistrations() - .getModuleRegistry() - .removeModule(this); + .getRegistrations() + .getModuleRegistry() + .addModule(this); } } diff --git a/Datura/src/main/java/me/totalfreedom/datura/Datura.java b/Datura/src/main/java/me/totalfreedom/datura/Datura.java index e1006f6..918935a 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/Datura.java +++ b/Datura/src/main/java/me/totalfreedom/datura/Datura.java @@ -20,18 +20,40 @@ public class Datura extends JavaPlugin public void onEnable() { CommonsBase.getInstance() - .getRegistrations() - .getModuleRegistry() - .addModule(this); + .getRegistrations() + .getModuleRegistry() + .addModule(this); - CommonsBase.getInstance().getRegistrations().getServiceRegistry().register(this, locker); - CommonsBase.getInstance().getRegistrations().getServiceRegistry().register(this, cager); + CommonsBase.getInstance() + .getRegistrations() + .getServiceRegistry() + .register(this, locker); + CommonsBase.getInstance() + .getRegistrations() + .getServiceRegistry() + .register(this, cager); - Bukkit.getPluginManager().registerEvents(halter, this); + Bukkit.getPluginManager() + .registerEvents(halter, this); } public MySQL getSQL() { return sql; } + + public Halter getHalter() + { + return halter; + } + + public Locker getLocker() + { + return locker; + } + + public Cager getCager() + { + return cager; + } } diff --git a/Datura/src/main/java/me/totalfreedom/datura/banning/BanUID.java b/Datura/src/main/java/me/totalfreedom/datura/banning/BanUID.java deleted file mode 100644 index 7f0c4b5..0000000 --- a/Datura/src/main/java/me/totalfreedom/datura/banning/BanUID.java +++ /dev/null @@ -1,66 +0,0 @@ -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'; - } -} diff --git a/Datura/src/main/java/me/totalfreedom/datura/banning/SimpleBan.java b/Datura/src/main/java/me/totalfreedom/datura/banning/SimpleBan.java deleted file mode 100644 index ff67d94..0000000 --- a/Datura/src/main/java/me/totalfreedom/datura/banning/SimpleBan.java +++ /dev/null @@ -1,82 +0,0 @@ -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/cmd/KickCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/KickCommand.java deleted file mode 100644 index 0746fb2..0000000 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/KickCommand.java +++ /dev/null @@ -1,26 +0,0 @@ -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 ") -@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."); - } -} diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java new file mode 100644 index 0000000..f346e83 --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java @@ -0,0 +1,41 @@ +package me.totalfreedom.datura.cmd; + +import me.totalfreedom.command.Commander; +import me.totalfreedom.command.annotation.Completion; +import me.totalfreedom.command.annotation.Info; +import me.totalfreedom.command.annotation.Permissive; +import me.totalfreedom.command.annotation.Subcommand; +import me.totalfreedom.datura.Datura; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +@Info(name = "locker", description = "Lock a player, preventing them from interacting with their game client.", + usage = "/locker ", aliases = {"lock", "lockup"}) +@Permissive(perm = "datura.locker") +public final class LockerCommand extends Commander +{ + public LockerCommand(final @NotNull Datura plugin) + { + super(plugin); + } + + @Completion(args = {"%player%"}, index = 0) + @Completion(args = {"on", "off"}, index = 1) + @Subcommand(permission = "datura.locker", args = {Player.class, String.class}) + public void lockPlayer(final CommandSender sender, final Player player, final String string) + { + if (string.equalsIgnoreCase("on")) + { + ((Datura) getPlugin()).getLocker() + .lock(player); + + sender.sendPlainMessage("Locked " + player.getName() + "."); + } else if (string.equalsIgnoreCase("off")) + { + ((Datura) getPlugin()).getLocker() + .unlock(player); + sender.sendPlainMessage("Unlocked " + player.getName() + "."); + } + } +} 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 42144f0..3ed35ff 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java @@ -5,39 +5,37 @@ import me.totalfreedom.security.perm.NodeType; public class DefaultNodes { - private DefaultNodes() { + public static final Node OP = new PermissionNodeBuilder() + .key("freedom.master_key") + .value(true) + .type(NodeType.PERMISSION) + .negated(false) + .wildcard(true) + .build(); + public static final Node NON_OP = new PermissionNodeBuilder() + .key("freedom.default") + .value(true) + .type(NodeType.PERMISSION) + .negated(false) + .wildcard(false) + .build(); + public static final Node ALL = new PermissionNodeBuilder() + .key("*") + .value(true) + .type(NodeType.PERMISSION) + .negated(false) + .wildcard(true) + .build(); + public static final Node NONE = new PermissionNodeBuilder() + .key("freedom.none") + .value(true) + .type(NodeType.PERMISSION) + .negated(false) + .wildcard(false) + .build(); + + private DefaultNodes() + { throw new AssertionError(); } - - public static final Node OP = new PermissionNodeBuilder() - .key("freedom.master_key") - .value(true) - .type(NodeType.PERMISSION) - .negated(false) - .wildcard(true) - .build(); - - public static final Node NON_OP = new PermissionNodeBuilder() - .key("freedom.default") - .value(true) - .type(NodeType.PERMISSION) - .negated(false) - .wildcard(false) - .build(); - - public static final Node ALL = new PermissionNodeBuilder() - .key("*") - .value(true) - .type(NodeType.PERMISSION) - .negated(false) - .wildcard(true) - .build(); - - public static final Node NONE = new PermissionNodeBuilder() - .key("freedom.none") - .value(true) - .type(NodeType.PERMISSION) - .negated(false) - .wildcard(false) - .build(); } 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 c22f124..b518f24 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java @@ -28,11 +28,11 @@ public class FreedomGroup implements Group private final PermissionAttachment attachment; public FreedomGroup(final Component name, - final Component prefix, - final Component abbreviation, - final int weight, - final boolean isDefault, - final boolean isHidden) + final Component prefix, + final Component abbreviation, + final int weight, + final boolean isDefault, + final boolean isHidden) { this.name = name; this.prefix = prefix; @@ -44,6 +44,12 @@ public class FreedomGroup implements Group this.attachment = new PermissionAttachment(CommonsBase.getInstance(), this); } + @Override + public UUID getUniqueId() + { + return UUID.nameUUIDFromBytes(getName().toString() + .getBytes()); + } @Override public Component getName() @@ -81,12 +87,6 @@ public class FreedomGroup implements Group return isHidden; } - @Override - public UUID getUniqueId() - { - return UUID.nameUUIDFromBytes(getName().toString().getBytes()); - } - @Override public Set permissions() { @@ -109,9 +109,10 @@ public class FreedomGroup implements Group public boolean isPermissionSet(@NotNull final String name) { final Node node = permissions().stream() - .filter(n -> n.key().equalsIgnoreCase(name)) - .findFirst() - .orElse(null); + .filter(n -> n.key() + .equalsIgnoreCase(name)) + .findFirst() + .orElse(null); return node != null && node.value(); } @@ -120,10 +121,11 @@ public class FreedomGroup implements Group public boolean isPermissionSet(@NotNull final Permission perm) { final Node node = permissions() - .stream() - .filter(n -> n.bukkit().equals(perm)) - .findFirst() - .orElse(null); + .stream() + .filter(n -> n.bukkit() + .equals(perm)) + .findFirst() + .orElse(null); return node != null && node.value(); } @@ -132,9 +134,10 @@ public class FreedomGroup implements Group public boolean hasPermission(@NotNull final String name) { final Node node = permissions().stream() - .filter(n -> n.key().equalsIgnoreCase(name)) - .findFirst() - .orElse(null); + .filter(n -> n.key() + .equalsIgnoreCase(name)) + .findFirst() + .orElse(null); return node != null && node.value(); } @@ -143,10 +146,11 @@ public class FreedomGroup implements Group public boolean hasPermission(@NotNull final Permission perm) { final Node node = permissions() - .stream() - .filter(n -> n.bukkit().equals(perm)) - .findFirst() - .orElse(null); + .stream() + .filter(n -> n.bukkit() + .equals(perm)) + .findFirst() + .orElse(null); return node != null && node.value(); } @@ -164,7 +168,8 @@ public class FreedomGroup implements Group * @return This group's PermissionAttachment. */ @Override - public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, final boolean value) + public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, + final boolean value) { attachment.setPermission(name, value); return attachment; @@ -177,7 +182,8 @@ public class FreedomGroup implements Group } @Override - public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, final boolean value, final 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; @@ -205,23 +211,23 @@ public class FreedomGroup implements Group public @NotNull Set getEffectivePermissions() { return permissions() - .stream() - .map(n -> new PermissionAttachmentInfo( - this, - n.key(), - attachment, - n.value())) - .collect(Collectors.toSet()); + .stream() + .map(n -> new PermissionAttachmentInfo( + this, + n.key(), + attachment, + n.value())) + .collect(Collectors.toSet()); } @Override public boolean isOp() { final Node node = permissions() - .stream() - .filter(n -> n.equals(DefaultNodes.OP)) - .findFirst() - .orElse(null); + .stream() + .filter(n -> n.equals(DefaultNodes.OP)) + .findFirst() + .orElse(null); return node != null && node.value(); } 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 3bef6b8..2a5d82a 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java @@ -43,10 +43,10 @@ public class FreedomUser implements User this.displayName = player.displayName(); final Datura datura = CommonsBase.getInstance() - .getRegistrations() - .getModuleRegistry() - .getModule(Datura.class) - .getModule(); + .getRegistrations() + .getModuleRegistry() + .getModule(Datura.class) + .getModule(); UserData data = SimpleUserData.fromSQL(datura.getSQL(), uuid.toString()); @@ -58,16 +58,29 @@ public class FreedomUser implements User this.userData = data; CommonsBase.getInstance() - .getRegistrations() - .getUserRegistry() - .registerUserData(this, userData); + .getRegistrations() + .getUserRegistry() + .registerUserData(this, userData); } @Override - public UserData getUserData() { + public UserData getUserData() + { return userData; } + @Override + public Component getDisplayName() + { + return displayName; + } + + @Override + public boolean isOnline() + { + return Bukkit.getPlayer(uuid) != null; + } + @Override public UUID getUniqueId() { @@ -96,18 +109,6 @@ public class FreedomUser implements User return permissions.remove(node); } - @Override - public Component getDisplayName() - { - return displayName; - } - - @Override - public boolean isOnline() - { - return Bukkit.getPlayer(uuid) != null; - } - @Override public boolean isPermissionSet(@NotNull final String name) { @@ -137,7 +138,8 @@ public class FreedomUser implements User } @Override - public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, final boolean value) + public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, + final boolean value) { final Player player = Bukkit.getPlayer(uuid); if (player != null) @@ -161,7 +163,8 @@ public class FreedomUser implements User } @Override - public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, final boolean value, final int ticks) + public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, + final boolean value, final int ticks) { final Player player = Bukkit.getPlayer(uuid); if (player != null) 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 1f2b91e..7353c19 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java @@ -9,29 +9,31 @@ record PermissionNode(String key, boolean value, long expiry, NodeType type, - boolean wildcard, - boolean negated) implements Node + boolean wildcard) implements Node { @Override public Permission bukkit() { return new Permission(key(), - value() ? PermissionDefault.TRUE : PermissionDefault.FALSE); + value() + ? PermissionDefault.TRUE + : PermissionDefault.FALSE); } @Override public boolean compare(final Node node) { - return node.key().equalsIgnoreCase(key()) - && node.value() == value() - && node.type() == type(); + return node.key() + .equalsIgnoreCase(key()) + && node.value() == value() + && node.type() == type(); } @Override public boolean isExpired() { - if (isPermanent()) + if (!isTemporary()) { return false; } @@ -39,15 +41,9 @@ record PermissionNode(String key, return System.currentTimeMillis() > expiry(); } - @Override - public boolean isPermanent() - { - return expiry() == -1; - } - @Override public boolean isTemporary() { - return !isPermanent(); + return expiry() > -1; } } diff --git a/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java b/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java index 7ffc02b..ec584f1 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java +++ b/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java @@ -14,8 +14,8 @@ import org.bukkit.event.player.PlayerQuitEvent; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -31,7 +31,8 @@ public class Cager extends Service super("cage_service"); this.cagedPlayers = new HashSet<>(); this.cageLocations = new HashMap<>(); - Bukkit.getPluginManager().registerEvents(new CageListener(), CommonsBase.getInstance()); + Bukkit.getPluginManager() + .registerEvents(new CageListener(), CommonsBase.getInstance()); } /** @@ -49,6 +50,39 @@ public class Cager extends Service cageLocations.put(uuid, createCage(player.getLocation(), Material.GLASS)); } + /** + * This method generates a cube centered around the passed location, + * made of the provided material. This method returns the passed location object. + * We use the {@link 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 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(final Location location, final Material material) + { + final Shaper shaper = new Shaper(location.getWorld(), 0.0, 4.0); + final List 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)); + cubed.addAll(shaper.generate(5, t -> 4.0, t -> t, t -> t)); + 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 (final Location l : cubed) + { + location.getWorld() + .getBlockAt(l) + .setType(material); + } + + return location.clone(); // Return the passed location as that is the center of the cube. + } + public void cagePlayer(final UUID uuid, final Material material) { final Player player = Bukkit.getPlayer(uuid); @@ -92,12 +126,14 @@ public class Cager extends Service final Location cageLocation = getCageLocation(player); final boolean inside; - if (!player.getWorld().equals(cageLocation.getWorld())) + if (!player.getWorld() + .equals(cageLocation.getWorld())) { inside = false; } else { - inside = player.getLocation().distanceSquared(cageLocation) > (Math.pow(2.5, 2.0)); + inside = player.getLocation() + .distanceSquared(cageLocation) > (Math.pow(2.5, 2.0)); } if (!inside) @@ -119,43 +155,13 @@ public class Cager extends Service return cageLocations.get(player.getUniqueId()); } - /** - * This method generates a cube centered around the passed location, - * made of the provided material. This method returns the passed location object. - * We use the {@link 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 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(final Location location, final Material material) - { - final Shaper shaper = new Shaper(location.getWorld(), 0.0, 4.0); - final List 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)); - cubed.addAll(shaper.generate(5, t -> 4.0, t -> t, t -> t)); - 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 (final Location l : cubed) - { - location.getWorld().getBlockAt(l).setType(material); - } - - return location.clone(); // Return the passed location as that is the center of the cube. - } - private final class CageListener implements Listener { @EventHandler public void blockBreakEvent(final BlockBreakEvent event) { - if (cagedPlayers.contains(event.getPlayer().getUniqueId())) + if (cagedPlayers.contains(event.getPlayer() + .getUniqueId())) { event.setCancelled(true); } @@ -164,9 +170,11 @@ public class Cager extends Service @EventHandler public void playerLeaveEvent(final PlayerQuitEvent event) { - if (cagedPlayers.contains(event.getPlayer().getUniqueId())) + if (cagedPlayers.contains(event.getPlayer() + .getUniqueId())) { - uncagePlayer(event.getPlayer().getUniqueId()); + uncagePlayer(event.getPlayer() + .getUniqueId()); } } } diff --git a/Datura/src/main/java/me/totalfreedom/datura/punishment/Halter.java b/Datura/src/main/java/me/totalfreedom/datura/punishment/Halter.java index 73047d1..11ef9be 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/punishment/Halter.java +++ b/Datura/src/main/java/me/totalfreedom/datura/punishment/Halter.java @@ -25,7 +25,8 @@ public class Halter implements Listener @EventHandler public void playerMove(final PlayerMoveEvent event) { - if (haltedPlayers.contains(event.getPlayer().getUniqueId())) + if (haltedPlayers.contains(event.getPlayer() + .getUniqueId())) { event.setCancelled(true); } diff --git a/Datura/src/main/java/me/totalfreedom/datura/punishment/Locker.java b/Datura/src/main/java/me/totalfreedom/datura/punishment/Locker.java index 36fda9b..4aa2eca 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/punishment/Locker.java +++ b/Datura/src/main/java/me/totalfreedom/datura/punishment/Locker.java @@ -22,15 +22,23 @@ public class Locker extends Service super("locker-service"); } - public void lock(final UUID uuid) + public void lock(final Player player) { - lockedPlayers.add(uuid); + lockedPlayers.add(player.getUniqueId()); + } + + public void unlock(final Player player) + { + lockedPlayers.remove(player.getUniqueId()); } @Override public void tick() { - lockedPlayers.removeIf(uuid -> !CommonsBase.getInstance().getServer().getOfflinePlayer(uuid).isOnline()); + lockedPlayers.removeIf(uuid -> !CommonsBase.getInstance() + .getServer() + .getOfflinePlayer(uuid) + .isOnline()); for (final UUID uuid : lockedPlayers) { @@ -43,8 +51,10 @@ public class Locker extends Service private void lockingMethod(@NotNull final Player player) { - final double x = player.getLocation().getX(); - final double z = player.getLocation().getZ(); + final double x = player.getLocation() + .getX(); + final double z = player.getLocation() + .getZ(); if ((x / z % 0.001) < 1) { @@ -65,13 +75,15 @@ public class Locker extends Service player.openInventory(Bukkit.createInventory(null, 54)); player.closeInventory(InventoryCloseEvent.Reason.UNKNOWN); - player.teleport(player.getLocation().clone()); + player.teleport(player.getLocation() + .clone()); final SplittableRandom random = new SplittableRandom(); - player.getEyeLocation().add(new Vector( - random.nextDouble(-1.0, 1.0), - random.nextDouble(-1.0, 1.0), - random.nextDouble(-1.0, 1.0) - )); + player.getEyeLocation() + .add(new Vector( + random.nextDouble(-1.0, 1.0), + random.nextDouble(-1.0, 1.0), + random.nextDouble(-1.0, 1.0) + )); } } diff --git a/Datura/src/main/java/me/totalfreedom/datura/sql/DBBan.java b/Datura/src/main/java/me/totalfreedom/datura/sql/DBBan.java deleted file mode 100644 index 2f2fb13..0000000 --- a/Datura/src/main/java/me/totalfreedom/datura/sql/DBBan.java +++ /dev/null @@ -1,89 +0,0 @@ -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 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(); - } -} 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 68ca550..9662cfb 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java +++ b/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java @@ -2,6 +2,7 @@ package me.totalfreedom.datura.sql; import me.totalfreedom.base.CommonsBase; import me.totalfreedom.sql.SQL; +import me.totalfreedom.utils.Identity; import java.sql.Connection; import java.sql.DriverManager; @@ -13,10 +14,18 @@ import java.util.concurrent.CompletionException; public class MySQL implements SQL { - private String url = "jdbc:mysql://"; + /** + * Using StringBuilder for finality. + */ + private final StringBuilder url = new StringBuilder("jdbc:mysql://"); - public MySQL(final String host, final int port, final String database) { - url += host + ":" + port + "/" + database; + public MySQL(final String host, final int port, final String database) + { + url.append(host) + .append(':') + .append(port) + .append('/') + .append(database); } /** @@ -26,85 +35,130 @@ public class MySQL implements SQL * @param username The username to add * @param password The password to add */ - public void addCredentials(final String username, final String password) { - if (url.contains("?user=")) { - url = url.split("\\x3f")[0]; + public void addCredentials(final String username, final String password) + { + if (url.toString() + .contains("?user=")) + { + final String split = url.toString() + .split("\\x3f")[0]; + url.setLength(0); + url.append(split); } - url += "?user=" + username + "&password=" + password; + url.append("?user=") + .append(username) + .append("&password=") + .append(password); } - @Override - public CompletableFuture getConnection(final String url) + public CompletableFuture getRow(final String table, final String column, final Identity identity) { - return CompletableFuture.supplyAsync(() -> { - try { - return DriverManager.getConnection(url); - } catch (SQLException ex) { - throw new CompletionException("Failed to connect to the database: " - + url + "\n", ex); - } - }, CommonsBase.getInstance().getExecutor().getAsync()); + return executeQuery("SELECT * FROM ? WHERE ? = ?", table, column, identity.getId()); } @Override public CompletableFuture prepareStatement(final String query, final Object... args) { - return getConnection(url) - .thenApplyAsync(connection -> { - try { - final PreparedStatement statement = connection.prepareStatement(query); - for (int i = 0; i < args.length; i++) { - statement.setObject(i + 1, args[i]); - } - return statement; - } catch (SQLException ex) { - throw new CompletionException("Failed to prepare statement: " - + query + "\n", ex); - } - }, CommonsBase.getInstance().getExecutor().getAsync()); + return getConnection() + .thenApplyAsync(connection -> + { + try + { + final PreparedStatement statement = connection.prepareStatement(query); + for (int i = 0; i < args.length; i++) + { + statement.setObject(i + 1, args[i]); + } + return statement; + } + catch (SQLException ex) + { + throw new CompletionException("Failed to prepare statement: " + + query + "\n", ex); + } + }, CommonsBase.getInstance() + .getExecutor() + .getAsync()); + } + + private CompletableFuture getConnection() + { + return CompletableFuture.supplyAsync(() -> + { + try + { + return DriverManager.getConnection(url.toString()); + } + catch (SQLException ex) + { + throw new CompletionException("Failed to connect to the database: " + + url.toString() + "\n", ex); + } + }, CommonsBase.getInstance() + .getExecutor() + .getAsync()); } @Override public CompletableFuture executeQuery(final String query, final Object... args) { return prepareStatement(query, args) - .thenApplyAsync(statement -> { - try { - return statement.executeQuery(); - } catch (SQLException ex) { - throw new CompletionException("Failed to retrieve a result set from query: " - + query + "\n", ex); - } - }, CommonsBase.getInstance().getExecutor().getAsync()); + .thenApplyAsync(statement -> + { + try + { + return statement.executeQuery(); + } + catch (SQLException ex) + { + throw new CompletionException( + "Failed to retrieve a result set from query: " + + query + "\n", ex); + } + }, CommonsBase.getInstance() + .getExecutor() + .getAsync()); } @Override public CompletableFuture executeUpdate(final String query, final Object... args) { return prepareStatement(query, args) - .thenApplyAsync(statement -> { - try { - return statement.executeUpdate(); - } catch (SQLException ex) { - throw new CompletionException("Failed to execute update: " - + query + "\n", ex); - } - }, CommonsBase.getInstance().getExecutor().getAsync()); + .thenApplyAsync(statement -> + { + try + { + return statement.executeUpdate(); + } + catch (SQLException ex) + { + throw new CompletionException("Failed to execute update: " + + query + "\n", ex); + } + }, CommonsBase.getInstance() + .getExecutor() + .getAsync()); } @Override public CompletableFuture execute(final String query, final Object... args) { return prepareStatement(query, args) - .thenApplyAsync(statement -> { - try { - return statement.execute(); - } catch (SQLException ex) { - throw new CompletionException("Failed to execute statement: " - + query + "\n", ex); - } - }, CommonsBase.getInstance().getExecutor().getAsync()); + .thenApplyAsync(statement -> + { + try + { + return statement.execute(); + } + catch (SQLException ex) + { + throw new CompletionException("Failed to execute statement: " + + query + "\n", ex); + } + }, CommonsBase.getInstance() + .getExecutor() + .getAsync()); } @Override @@ -113,9 +167,11 @@ public class MySQL implements SQL final StringBuilder query = new StringBuilder(); query.append("CREATE TABLE IF NOT EXISTS ? ("); - for (int i = 0; i < columns.length; i++) { + for (int i = 0; i < columns.length; i++) + { query.append("?"); - if (i != columns.length - 1) { + if (i != columns.length - 1) + { query.append(", "); } } @@ -123,4 +179,90 @@ public class MySQL implements SQL return execute(query.toString(), table, columns); } + + public CompletableFuture getColumn(final String table, final String column, final String key, + final Identity identity, final Class type) + { + return executeQuery("SELECT ? FROM ? WHERE ? = ?", column, table, key, identity.getId()) + .thenApplyAsync(resultSet -> + { + try + { + if (resultSet.next()) + { + return resultSet.getObject(column, type); + } + } + catch (SQLException ex) + { + throw new CompletionException( + "Failed to retrieve column: " + column + " from table: " + table + " " + + "where primary key: " + key + " is equal to: " + identity.getId() + "\n", + ex); + } + return null; + }, CommonsBase.getInstance() + .getExecutor() + .getAsync()); + } + + public CompletableFuture updateColumn(final String table, final String column, final Object value, + final String key, final Identity identity) + { + return executeUpdate("UPDATE ? SET ? = ? WHERE ? = ?", table, column, value, key, identity.getId()) + .thenApplyAsync(result -> result > 0, CommonsBase.getInstance() + .getExecutor() + .getAsync()); + } + + public CompletableFuture deleteRow(final String table, final String key, final Identity identity) + { + return executeUpdate("DELETE FROM ? WHERE ? = ?", table, key, identity.getId()) + .thenApplyAsync(result -> result > 0, CommonsBase.getInstance() + .getExecutor() + .getAsync()); + } + + public CompletableFuture insertRow(final String table, final Object... values) + { + final StringBuilder query = new StringBuilder(); + query.append("INSERT INTO ? VALUES ("); + for (int i = 0; i < values.length; i++) + { + query.append("?"); + if (i != values.length - 1) + { + query.append(", "); + } + } + query.append(")"); + return execute(query.toString(), table, values); + } + + public CompletableFuture insertRow(final String table, final String[] columns, final Object... values) + { + final StringBuilder query = new StringBuilder(); + query.append("INSERT INTO ? ("); + for (int i = 0; i < columns.length; i++) + { + query.append("?"); + if (i != columns.length - 1) + { + query.append(", "); + } + } + query.append(") VALUES ("); + for (int i = 0; i < values.length; i++) + { + query.append("?"); + if (i != values.length - 1) + { + query.append(", "); + } + } + query.append(")"); + return execute(query.toString(), table, columns, values); + } + + } diff --git a/Datura/src/main/java/me/totalfreedom/datura/sql/Result.java b/Datura/src/main/java/me/totalfreedom/datura/sql/Result.java new file mode 100644 index 0000000..9fd214b --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/sql/Result.java @@ -0,0 +1,14 @@ +package me.totalfreedom.datura.sql; + + +import com.google.errorprone.annotations.Immutable; + +/** + * Represents a single result from a result set. + */ +@Immutable +public record Result(String name, Object value) +{ +} + + 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 b1c7c0d..be92bd7 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java @@ -38,20 +38,22 @@ public class SimpleUserData implements UserData this.username = player.getName(); this.user = new FreedomUser(player); - CommonsBase.getInstance().getEventBus().addEvent(event); + CommonsBase.getInstance() + .getEventBus() + .addEvent(event); } private SimpleUserData( - final UUID uuid, - final String username, - final User user, - final Group group, - final long playtime, - final boolean frozen, - final boolean canInteract, - final boolean caged, - final long balance, - final boolean transactionsFrozen) + final UUID uuid, + final String username, + final User user, + final Group group, + final long playtime, + final boolean frozen, + final boolean canInteract, + final boolean caged, + final long balance, + final boolean transactionsFrozen) { this.uuid = uuid; this.username = username; @@ -68,57 +70,64 @@ public class SimpleUserData implements UserData public static SimpleUserData fromSQL(final SQL sql, final String uuid) { return sql.executeQuery("SELECT * FROM users WHERE UUID = ?", uuid) - .thenApplyAsync(result -> - { - try - { - if (result.next()) - { - final String g = result.getString("group"); + .thenApplyAsync(result -> + { + try + { + if (result.next()) + { + final String g = result.getString("group"); - final UUID u = UUID.fromString(uuid); - final String username = result.getString("username"); + final UUID u = UUID.fromString(uuid); + final String username = result.getString("username"); - final 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!"); + if (player == null) + throw new IllegalStateException( + "Player should be online but they are not!"); - final User user = new FreedomUser(player); - final Group group = CommonsBase.getInstance() - .getRegistrations() - .getGroupRegistry() - .getGroup(g); + final User user = new FreedomUser(player); + final Group group = CommonsBase.getInstance() + .getRegistrations() + .getGroupRegistry() + .getGroup(g); - 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) - { - 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); + 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) + { + 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); - } + FreedomLogger.getLogger("Datura") + .error(sb); + } - final Player player = Bukkit.getPlayer(UUID.fromString(uuid)); - if (player == null) throw new IllegalStateException("Player should be online but they are not!"); - return new SimpleUserData(player); - }, CommonsBase.getInstance() - .getExecutor() - .getAsync()) - .join(); + 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() + .getExecutor() + .getAsync()) + .join(); } @Override @@ -230,6 +239,12 @@ public class SimpleUserData implements UserData return balance.get(); } + @Override + public void setBalance(final long newBalance) + { + balance.set(newBalance); + } + @Override public long addToBalance(final long amount) { @@ -241,10 +256,4 @@ public class SimpleUserData implements UserData { return balance.addAndGet(-amount); } - - @Override - public void setBalance(final long newBalance) - { - balance.set(newBalance); - } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java b/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java index 06e9b8a..3309ef4 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java @@ -9,8 +9,8 @@ public class Fossil extends JavaPlugin public void onEnable() { CommonsBase.getInstance() - .getRegistrations() - .getModuleRegistry() - .addModule(this); + .getRegistrations() + .getModuleRegistry() + .addModule(this); } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransaction.java b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransaction.java index 6c6f9ac..93bf7b7 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransaction.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransaction.java @@ -7,9 +7,9 @@ import java.util.concurrent.atomic.AtomicLong; public class SimpleTransaction implements Transaction { + protected final AtomicLong balance; private final EconomicEntity source; private final EconomicEntity destination; - protected final AtomicLong balance; public SimpleTransaction(final EconomicEntity source, final EconomicEntity destination, final long balance) { diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionLogger.java b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionLogger.java index 8ef43e9..7ebb9cc 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionLogger.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionLogger.java @@ -1,10 +1,10 @@ package me.totalfreedom.fossil.economy; import me.totalfreedom.audience.MutableAudienceForwarder; -import me.totalfreedom.economy.TransactionResult; import me.totalfreedom.economy.CompletedTransaction; -import me.totalfreedom.economy.TransactionLogger; import me.totalfreedom.economy.EconomicEntity; +import me.totalfreedom.economy.TransactionLogger; +import me.totalfreedom.economy.TransactionResult; import me.totalfreedom.utils.FreedomLogger; import net.kyori.adventure.text.Component; @@ -24,17 +24,19 @@ public class SimpleTransactionLogger implements TransactionLogger final EconomicEntity destination = completedTransaction.getDestination(); final long transactionAmount = completedTransaction.getBalance(); - transactionLoggingStatementBuilder.append(resultSuccess ? "Successful" : "Unsuccessful") - .append(" (") - .append(resultMessage) - .append(") ") - .append(" transaction between ") - .append(source.getName()) - .append(" ") - .append(destination.getName()) - .append(" where the volume of currency transferred was $") - .append(transactionAmount) - .append("."); + transactionLoggingStatementBuilder.append(resultSuccess + ? "Successful" + : "Unsuccessful") + .append(" (") + .append(resultMessage) + .append(") ") + .append(" transaction between ") + .append(source.getName()) + .append(" ") + .append(destination.getName()) + .append(" where the volume of currency transferred was $") + .append(transactionAmount) + .append("."); final Component message = Component.text(transactionLoggingStatementBuilder.toString()); diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionResult.java b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionResult.java index 935ea22..381936c 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionResult.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionResult.java @@ -7,16 +7,21 @@ import net.kyori.adventure.text.format.NamedTextColor; public class SimpleTransactionResult implements TransactionResult { public static final TransactionResult SUCCESSFUL = new SimpleTransactionResult("Successful transaction.", true); - public static final TransactionResult UNAUTHORIZED = new SimpleTransactionResult("Unauthorized transaction.", false); - public static final TransactionResult AMOUNT_TOO_SMALL = new SimpleTransactionResult("Transaction balance too small.", false); - public static final TransactionResult INSUFFICIENT_FUNDS = new SimpleTransactionResult("The source has an insufficient balance to carry out this transaction.", false); + public static final TransactionResult UNAUTHORIZED = new SimpleTransactionResult("Unauthorized transaction.", + false); + public static final TransactionResult AMOUNT_TOO_SMALL = new SimpleTransactionResult( + "Transaction balance too small.", false); + public static final TransactionResult INSUFFICIENT_FUNDS = new SimpleTransactionResult( + "The source has an insufficient balance to carry out this transaction.", false); private final String message; private final Component component; private final boolean successful; public SimpleTransactionResult(final String message, final boolean successful) { - this(message, Component.text(message, successful ? NamedTextColor.GREEN : NamedTextColor.RED), successful); + this(message, Component.text(message, successful + ? NamedTextColor.GREEN + : NamedTextColor.RED), successful); } public SimpleTransactionResult(final String message, final Component component, final boolean successful) diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/shop/Shoppe.java b/Fossil/src/main/java/me/totalfreedom/fossil/shop/Shoppe.java new file mode 100644 index 0000000..d586412 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/shop/Shoppe.java @@ -0,0 +1,5 @@ +package me.totalfreedom.fossil.shop; + +public class Shoppe +{ +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/shop/menus/MainMenu.java b/Fossil/src/main/java/me/totalfreedom/fossil/shop/menus/MainMenu.java new file mode 100644 index 0000000..c637c56 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/shop/menus/MainMenu.java @@ -0,0 +1,11 @@ +package me.totalfreedom.fossil.shop.menus; + +import me.totalfreedom.display.AbstractMenu; + +public final class MainMenu extends AbstractMenu +{ + protected MainMenu(final int size) + { + super(size); + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/api/Context.java b/Patchwork/src/main/java/me/totalfreedom/api/Context.java index 2a837d7..e4e7731 100644 --- a/Patchwork/src/main/java/me/totalfreedom/api/Context.java +++ b/Patchwork/src/main/java/me/totalfreedom/api/Context.java @@ -16,13 +16,13 @@ import java.util.function.Function; @FunctionalInterface public interface Context { - T get(); - default Context map(@NotNull final Function mapper) { return () -> mapper.apply(get()); } + T get(); + default @Nullable String asString() { if (get() instanceof String string) @@ -56,26 +56,35 @@ public interface Context } } - default @Nullable Integer asInt() { - if (get() instanceof Integer integer) { + default @Nullable Integer asInt() + { + if (get() instanceof Integer integer) + { return integer; - } else { + } else + { return null; } } - default @Nullable Long asLong() { - if (get() instanceof Long longg) { + default @Nullable Long asLong() + { + if (get() instanceof Long longg) + { return longg; - } else { + } else + { return null; } } - default @Nullable Float asFloat() { - if (get() instanceof Float floatt) { + default @Nullable Float asFloat() + { + if (get() instanceof Float floatt) + { return floatt; - } else { + } else + { return null; } } diff --git a/Patchwork/src/main/java/me/totalfreedom/audience/MutableAudienceForwarder.java b/Patchwork/src/main/java/me/totalfreedom/audience/MutableAudienceForwarder.java index 7ade549..4048c49 100644 --- a/Patchwork/src/main/java/me/totalfreedom/audience/MutableAudienceForwarder.java +++ b/Patchwork/src/main/java/me/totalfreedom/audience/MutableAudienceForwarder.java @@ -19,7 +19,8 @@ import java.util.function.Consumer; import java.util.function.Predicate; /** - * A replacement for {@link net.kyori.adventure.audience.ForwardingAudience} that allows for audiences to be removed & added at will. Not thread safe. + * A replacement for {@link net.kyori.adventure.audience.ForwardingAudience} that allows for audiences to be removed + * & added at will. Not thread safe. *

* This is intended for use in toggleable logging systems, for example, potion spy. */ @@ -60,9 +61,9 @@ public class MutableAudienceForwarder implements Audience public @NotNull Audience filterAudience(@NotNull final Predicate filter) { return audiences.stream() - .filter(filter) - .findFirst() - .orElseThrow(); + .filter(filter) + .findFirst() + .orElseThrow(); } @Override diff --git a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java index 999c940..2d1cb5a 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java @@ -16,25 +16,23 @@ public class CommonsBase extends JavaPlugin } @Override - public void onEnable() + public void onDisable() { - getRegistrations().getServiceRegistry().register(this, eventBus); - getExecutor().getSync() - .execute(() -> getRegistrations() - .getServiceRegistry() - .startAll()); + getRegistrations().getServiceRegistry() + .stopAll(); + getRegistrations().getServiceRegistry() + .unregister(EventBus.class, eventBus); } @Override - public void onDisable() + public void onEnable() { - getRegistrations().getServiceRegistry().stopAll(); - getRegistrations().getServiceRegistry().unregister(EventBus.class, eventBus); - } - - public Registration getRegistrations() - { - return registration; + getRegistrations().getServiceRegistry() + .register(this, eventBus); + getExecutor().getSync() + .execute(() -> getRegistrations() + .getServiceRegistry() + .startAll()); } public FreedomExecutor getExecutor() @@ -42,6 +40,11 @@ public class CommonsBase extends JavaPlugin return executor; } + public Registration getRegistrations() + { + return registration; + } + public EventBus getEventBus() { return eventBus; diff --git a/Patchwork/src/main/java/me/totalfreedom/base/Registration.java b/Patchwork/src/main/java/me/totalfreedom/base/Registration.java index 03c4dd3..7d8b8cb 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/Registration.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/Registration.java @@ -1,12 +1,11 @@ package me.totalfreedom.base; -import me.totalfreedom.data.GroupRegistry; -import me.totalfreedom.data.BanRegistry; import me.totalfreedom.data.ConfigRegistry; +import me.totalfreedom.data.EventRegistry; +import me.totalfreedom.data.GroupRegistry; import me.totalfreedom.data.ModuleRegistry; import me.totalfreedom.data.ServiceRegistry; import me.totalfreedom.data.UserRegistry; -import me.totalfreedom.data.EventRegistry; public class Registration { @@ -15,7 +14,6 @@ public class Registration private final ServiceRegistry serviceRegistry; private final ModuleRegistry moduleRegistry; private final GroupRegistry groupRegistry; - private final BanRegistry banRegistry; private final ConfigRegistry configRegistry; public Registration() @@ -25,8 +23,7 @@ public class Registration this.serviceRegistry = new ServiceRegistry(); this.moduleRegistry = new ModuleRegistry(); this.groupRegistry = new GroupRegistry(); - this.banRegistry = new BanRegistry(); - this.configRegistry = new ConfigRegistry(); + this.configRegistry = new ConfigRegistry(); } public ModuleRegistry getModuleRegistry() @@ -54,11 +51,6 @@ public class Registration return groupRegistry; } - public BanRegistry getBanRegistry() - { - return banRegistry; - } - public ConfigRegistry getConfigRegistry() { return configRegistry; diff --git a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java new file mode 100644 index 0000000..a888edb --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java @@ -0,0 +1,188 @@ +package me.totalfreedom.command; + +import me.totalfreedom.api.Context; +import me.totalfreedom.command.annotation.Completion; +import me.totalfreedom.command.annotation.Subcommand; +import me.totalfreedom.provider.ContextProvider; +import me.totalfreedom.utils.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.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +public class BukkitDelegate extends Command implements PluginIdentifiableCommand +{ + private final JavaPlugin plugin; + private final Commander command; + private final boolean noConsole; + + BukkitDelegate(final Commander command) + { + super(command.getInfo() + .name()); + this.command = command; + this.plugin = command.getPlugin(); + this.setDescription(command.getInfo() + .description()); + this.setUsage(command.getInfo() + .usage()); + this.setPermission(command.getPerms() + .perm()); + this.setAliases(Arrays.asList(command.getInfo() + .aliases())); + this.permissionMessage(Component.text(command.getPerms() + .noPerms())); + this.noConsole = command.getPerms() + .onlyPlayers(); + } + + @Override + public boolean execute(@NotNull final CommandSender sender, + @NotNull final String commandLabel, + @NotNull final String[] args) + { + if (sender instanceof ConsoleCommandSender && noConsole) + { + sender.sendMessage(Component.text("This command can only be run by players.")); + return true; + } + + if (getPermission() != null && !sender.hasPermission(getPermission())) + { + Component permissionMessage = permissionMessage(); + if (permissionMessage == null) + permissionMessage = Component.text("You do not have permission to use this command."); + sender.sendMessage(permissionMessage); + return true; + } + + if (args.length > 0) + { + final ContextProvider provider = new ContextProvider(); + final Set nodes = command.getSubcommands() + .keySet(); + for (final Subcommand node : nodes) + { + processSubCommands(args, sender, provider, node); + } + + return true; + } + + if (command.getBaseMethod() != null) + { + try + { + command.getBaseMethod() + .invoke(command, sender); + } + catch (Exception ex) + { + FreedomLogger.getLogger("Patchwork") + .error(ex); + } + + return true; + } + + return false; + } + + private void processSubCommands(final @NotNull String @NotNull [] args, + final CommandSender sender, final ContextProvider provider, + final Subcommand node) + { + final Class[] argTypes = node.args(); + if (argTypes.length != args.length) + return; + + final Object[] objects = new Object[argTypes.length + 1]; + + for (int i = 0; i < argTypes.length; i++) + { + final Class argType = argTypes[i]; + final String arg = args[i]; + + if (argType == String.class) + continue; + + final Context context = () -> provider.fromString(arg, argType); + objects[i] = context.get(); + } + try + { + command.getSubcommands() + .get(node) + .invoke(command, sender, objects); + } + catch (Exception ex) + { + FreedomLogger.getLogger("Patchwork") + .error(ex); + } + } + + @Override + public List tabComplete(final CommandSender sender, final String alias, final String[] args) + { + final Set completions = command.getCompletions(); + final List 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() + { + return this.plugin; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegator.java b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegator.java deleted file mode 100644 index 93ca292..0000000 --- a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegator.java +++ /dev/null @@ -1,171 +0,0 @@ -package me.totalfreedom.command; - -import me.totalfreedom.api.Context; -import me.totalfreedom.command.annotation.Completion; -import me.totalfreedom.command.annotation.Subcommand; -import me.totalfreedom.provider.ContextProvider; -import me.totalfreedom.utils.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.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -public class BukkitDelegator extends Command implements PluginIdentifiableCommand -{ - private final JavaPlugin plugin; - private final CommandBase command; - private final boolean noConsole; - - BukkitDelegator(final JavaPlugin plugin, final CommandBase command) - { - super(command.getInfo().name()); - this.command = command; - this.plugin = command.getPlugin(); - this.setDescription(command.getInfo().description()); - this.setUsage(command.getInfo().usage()); - this.setPermission(command.getPerms().perm()); - this.setAliases(Arrays.asList(command.getInfo().aliases())); - this.permissionMessage(Component.text(command.getPerms().noPerms())); - this.noConsole = command.getPerms().onlyPlayers(); - } - - @Override - public boolean execute(@NotNull final CommandSender sender, - @NotNull final String commandLabel, - @NotNull final String[] args) - { - if (commandLabel.isEmpty() || !commandLabel.equalsIgnoreCase(getName())) - return false; - - if (sender instanceof ConsoleCommandSender && noConsole) - { - sender.sendMessage(Component.text("This command can only be run by players.")); - return true; - } - - if (getPermission() != null && !sender.hasPermission(getPermission())) - { - Component permissionMessage = permissionMessage(); - if (permissionMessage == null) - permissionMessage = Component.text("You do not have permission to use this command."); - sender.sendMessage(permissionMessage); - return true; - } - - if (args.length > 0) - { - final ContextProvider provider = new ContextProvider(); - final Set 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++) - { - final Class argType = argTypes[i]; - final String arg = args[i]; - if (argType == String.class) - continue; - - 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(); - } - try - { - command.getSubcommands().get(node).invoke(command, objects); - } catch (Exception ex) - { - FreedomLogger.getLogger("Patchwork") - .error(ex); - } - } - - return false; - } - - if (command.getBaseMethodPair() != null) - { - try - { - command.getBaseMethodPair().value().invoke(command, sender); - } catch (Exception ex) - { - FreedomLogger.getLogger("Patchwork") - .error(ex); - } - } - - return true; - } - - @Override - public List tabComplete(final CommandSender sender, final String alias, final String[] args) - { - final Set completions = command.getCompletions(); - final List 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() - { - return this.plugin; - } -} diff --git a/Patchwork/src/main/java/me/totalfreedom/command/CommandBase.java b/Patchwork/src/main/java/me/totalfreedom/command/CommandBase.java deleted file mode 100644 index 3e0accc..0000000 --- a/Patchwork/src/main/java/me/totalfreedom/command/CommandBase.java +++ /dev/null @@ -1,89 +0,0 @@ -package me.totalfreedom.command; - -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.*; -import java.util.stream.Stream; - -public abstract class CommandBase -{ - private final JavaPlugin plugin; - private final Info info; - private final Permissive perms; - private final Map subcommands; - private final Set completions; - private final Pair baseMethodPair; - - protected CommandBase(final JavaPlugin plugin) - { - this.info = this.getClass().getDeclaredAnnotation(Info.class); - this.perms = this.getClass().getDeclaredAnnotation(Permissive.class); - this.plugin = plugin; - this.subcommands = new HashMap<>(); - this.completions = new HashSet<>(); - - if (this.getClass().isAnnotationPresent(Base.class)) - { - 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.")); - - this.baseMethodPair = new Pair<>(method.getDeclaredAnnotation(Base.class), method); - } else - { - 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)); - - List.of(this.getClass().getDeclaredAnnotationsByType(Completion.class)) - .stream() - .forEach(completions::add); - } - - public Pair getBaseMethodPair() - { - return baseMethodPair; - } - - Info getInfo() - { - return this.info; - } - - Permissive getPerms() - { - return this.perms; - } - - public JavaPlugin getPlugin() - { - return this.plugin; - } - - Map getSubcommands() - { - return this.subcommands; - } - - Set getCompletions() - { - return this.completions; - } -} diff --git a/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java b/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java index 9471dc7..c2714bf 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java @@ -12,14 +12,11 @@ public class CommandHandler this.plugin = plugin; } - // TODO: Figure out how to use CommandExecutor and TabCompleter. - // 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 void registerCommand(final T command) + public void registerCommand(final T command) { - final BukkitDelegator delegate = new BukkitDelegator(plugin, command); + final BukkitDelegate delegate = new BukkitDelegate(command); - Bukkit.getCommandMap().register(plugin.getName(), delegate); + Bukkit.getCommandMap() + .register(plugin.getName(), delegate); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/command/Commander.java b/Patchwork/src/main/java/me/totalfreedom/command/Commander.java new file mode 100644 index 0000000..62f6d56 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/command/Commander.java @@ -0,0 +1,108 @@ +package me.totalfreedom.command; + +import me.totalfreedom.command.annotation.Base; +import me.totalfreedom.command.annotation.Completion; +import me.totalfreedom.command.annotation.Info; +import me.totalfreedom.command.annotation.Permissive; +import me.totalfreedom.command.annotation.Subcommand; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + +public abstract class Commander +{ + private final JavaPlugin plugin; + private final Info info; + private final Permissive perms; + private final Map subcommands; + private final Set completions; + private final Method baseMethod; + + protected Commander(final @NotNull JavaPlugin plugin) + { + this.info = this.getClass() + .getDeclaredAnnotation(Info.class); + this.perms = this.getClass() + .getDeclaredAnnotation(Permissive.class); + this.plugin = plugin; + this.subcommands = new HashMap<>(); + this.completions = new HashSet<>(); + + if (this.getClass() + .isAnnotationPresent(Base.class)) + { + 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.")); + + this.baseMethod = method; + } else + { + this.baseMethod = 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)); + + List.of(this.getClass() + .getDeclaredAnnotationsByType(Completion.class)) + .stream() + .forEach(completions::add); + } + + @Nullable + public Method getBaseMethod() + { + return baseMethod; + } + + @NotNull + Info getInfo() + { + return this.info; + } + + @NotNull + Permissive getPerms() + { + return this.perms; + } + + @NotNull + public JavaPlugin getPlugin() + { + return this.plugin; + } + + @NotNull + Map getSubcommands() + { + return this.subcommands; + } + + @Nullable + Set getCompletions() + { + return this.completions; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completion.java b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completion.java index 82002af..253fc86 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completion.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completion.java @@ -1,11 +1,13 @@ package me.totalfreedom.command.annotation; import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target(ElementType.TYPE) +@Target(ElementType.METHOD) +@Repeatable(Completions.class) @Retention(RetentionPolicy.RUNTIME) public @interface Completion { diff --git a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completions.java b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completions.java new file mode 100644 index 0000000..632156d --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completions.java @@ -0,0 +1,13 @@ +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.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Completions +{ + Completion[] value(); +} diff --git a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Subcommand.java b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Subcommand.java index 76fb1d3..3010844 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Subcommand.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Subcommand.java @@ -1,8 +1,11 @@ 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.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Subcommand { diff --git a/Patchwork/src/main/java/me/totalfreedom/data/BanRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/BanRegistry.java deleted file mode 100644 index ad2c159..0000000 --- a/Patchwork/src/main/java/me/totalfreedom/data/BanRegistry.java +++ /dev/null @@ -1,34 +0,0 @@ -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 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; - } -} diff --git a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java index 990e878..8e8643e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java @@ -15,26 +15,32 @@ public class GroupRegistry this.groups = new ArrayList<>(); } - public boolean registerGroup(final Group group) { + public boolean registerGroup(final Group group) + { return groups.add(group); } - public boolean unregisterGroup(final Group group) { + public boolean unregisterGroup(final Group group) + { return groups.remove(group); } - public Group getGroup(final String name) { + public Group getGroup(final String name) + { final PlainTextComponentSerializer s = PlainTextComponentSerializer.plainText(); - for (final Group group : groups) { + for (final Group group : groups) + { final String n = s.serialize(group.getName()); - if (n.equalsIgnoreCase(name)) { + if (n.equalsIgnoreCase(name)) + { return group; } } return null; } - public List getGroups() { + public List getGroups() + { return groups; } } diff --git a/Patchwork/src/main/java/me/totalfreedom/data/ModuleRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/ModuleRegistry.java index 06d3e19..34f024a 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/ModuleRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/ModuleRegistry.java @@ -24,7 +24,8 @@ public class ModuleRegistry this.plugins.add(plugin); } - public void removeModule(final JavaPlugin plugin) { + public void removeModule(final JavaPlugin plugin) + { this.plugins.remove(plugin); } diff --git a/Patchwork/src/main/java/me/totalfreedom/data/ServiceRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/ServiceRegistry.java index 7381779..589db1d 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/ServiceRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/ServiceRegistry.java @@ -42,29 +42,34 @@ public class ServiceRegistry public void register(final Plugin plugin, final T service) { this.services.add(service); - if (!service.getClass().isInstance(service)) + if (!service.getClass() + .isInstance(service)) { throw new UnknownError(""" - A critical issue has been encountered: - The service %s is not an instance of itself. - This is a critical issue and should be reported immediately. - """.formatted(service.getClass().getName())); + A critical issue has been encountered: + The service %s is not an instance of itself. + This is a critical issue and should be reported immediately. + """.formatted(service.getClass() + .getName())); } - Bukkit.getServicesManager().register( - (Class) service.getClass(), - service, - plugin, - ServicePriority.Normal); + Bukkit.getServicesManager() + .register( + (Class) service.getClass(), + service, + plugin, + ServicePriority.Normal); } public RegisteredServiceProvider getService(final Class clazz) { - return Bukkit.getServicesManager().getRegistration(clazz); + return Bukkit.getServicesManager() + .getRegistration(clazz); } public void unregister(final Class clazz, final Service service) { this.services.remove(service); - Bukkit.getServicesManager().unregister(clazz, service); + Bukkit.getServicesManager() + .unregister(clazz, service); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java b/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java new file mode 100644 index 0000000..d39e5dc --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java @@ -0,0 +1,121 @@ +package me.totalfreedom.display; + +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public abstract class AbstractMenu +{ + private static final Map invByUUID = new HashMap<>(); + private static final Map openInvs = new HashMap<>(); + private final Map actionMap; + private final Displayable displayable; + private final UUID displayableUUID; + + protected AbstractMenu(final int size) + { + actionMap = new HashMap<>(); + this.displayable = new Displayable(size); + this.displayableUUID = UUID.randomUUID(); + + invByUUID.put(getDisplayableUUID(), this); + } + + public UUID getDisplayableUUID() + { + return displayableUUID; + } + + public static Map getInvByUUID() + { + return invByUUID; + } + + public static Map getOpenInvs() + { + return openInvs; + } + + public void setItem(final int slot, final @NotNull ItemStack stack) + { + setItem(slot, stack, null); + } + + public void setItem(final int slot, final @NotNull ItemStack stack, final @Nullable ClickAction action) + { + getDisplayable().setItem(slot, stack); + if (action != null) + { + actionMap.put(slot, action); + } + } + + public Displayable getDisplayable() + { + return displayable; + } + + public void open(final @NotNull Player player) + { + player.openInventory(getDisplayable()); + openInvs.put(player.getUniqueId(), getDisplayableUUID()); + } + + public void delete() + { + Bukkit.getOnlinePlayers() + .forEach(player -> + { + if (openInvs.get(player.getUniqueId()) + .equals(getDisplayableUUID())) + { + close(player); + } + }); + + invByUUID.remove(getDisplayableUUID()); + } + + public void close(final @NotNull Player player) + { + player.closeInventory(); + openInvs.remove(player.getUniqueId()); + } + + public Map getActions() + { + return actionMap; + } + + public ItemStack newItem(final @NotNull Material material, final @NotNull Component name) + { + return this.newItem(material, name, new Component[0]); + } + + public ItemStack newItem(final @NotNull Material material, final @NotNull Component name, + final @NotNull Component... lore) + { + final ItemStack item = new ItemStack(material, 1); + final ItemMeta meta = item.getItemMeta(); + if (meta == null) + { + return item; + } + meta.displayName(name); + final List metaLore = Arrays.asList(lore); + meta.lore(metaLore); + item.setItemMeta(meta); + return item; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java b/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java new file mode 100644 index 0000000..2d6d21f --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java @@ -0,0 +1,9 @@ +package me.totalfreedom.display; + +import org.bukkit.entity.Player; + +@FunctionalInterface +public interface ClickAction +{ + void onClick(final Player player); +} diff --git a/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java b/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java index a60fad8..2ae19e8 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java @@ -1,5 +1,6 @@ package me.totalfreedom.display; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.HumanEntity; import org.bukkit.event.inventory.InventoryType; @@ -14,11 +15,11 @@ import java.util.HashMap; import java.util.List; import java.util.ListIterator; -public abstract class Displayable implements Inventory, InventoryHolder +public final class Displayable implements Inventory, InventoryHolder { private final int size; - private final ItemStack[] contents; + private ItemStack[] contents; protected Displayable(final int size) { @@ -27,9 +28,9 @@ public abstract class Displayable implements Inventory, InventoryHolder throw new IllegalArgumentException("Invalid size for Displayable inventory"); } - this.size = (size % 9 == 0) - ? size - : size + (9 - size % 9); + // If the size is not a multiple of nine, find the difference to the next highest multiple of 9 and make up + // the difference. + this.size = (size % 9 == 0) ? size : size + (9 - size % 9); this.contents = new ItemStack[size]; } @@ -78,7 +79,8 @@ public abstract class Displayable implements Inventory, InventoryHolder } @Override - public @NotNull HashMap addItem(final @NotNull ItemStack... items) throws IllegalArgumentException + public @NotNull HashMap addItem(final @NotNull ItemStack... items) + throws IllegalArgumentException { final HashMap remainingItems = new HashMap<>(); @@ -116,7 +118,8 @@ public abstract class Displayable implements Inventory, InventoryHolder } @Override - public @NotNull HashMap removeItem(final @NotNull ItemStack... items) throws IllegalArgumentException + public @NotNull HashMap removeItem(final @NotNull ItemStack... items) + throws IllegalArgumentException { final HashMap removedItems = new HashMap<>(); @@ -148,13 +151,21 @@ public abstract class Displayable implements Inventory, InventoryHolder if (remainingAmount < item.getAmount()) { - removedItems.put(removedItems.size(), new ItemStack(item.getType(), item.getAmount() - remainingAmount)); + removedItems.put(removedItems.size(), + new ItemStack(item.getType(), item.getAmount() - remainingAmount)); } } return removedItems; } + @Override + public @NotNull HashMap removeItemAnySlot(final @NotNull ItemStack... items) + throws IllegalArgumentException + { + return removeItem(items); + } + @Override public @Nullable ItemStack @NotNull [] getContents() { @@ -176,39 +187,15 @@ public abstract class Displayable implements Inventory, InventoryHolder } @Override - public @NotNull ListIterator iterator() + public @Nullable ItemStack @NotNull [] getStorageContents() { - return iterator(0); + return contents; } @Override - public @NotNull ListIterator iterator(final int index) + public void setStorageContents(final @Nullable ItemStack @NotNull [] items) throws IllegalArgumentException { - return List.of(contents).listIterator(index); - } - - @Override - public @NotNull InventoryType getType() - { - return InventoryType.CHEST; - } - - @Override - public @Nullable InventoryHolder getHolder() - { - return this; - } - - @Override - public @Nullable InventoryHolder getHolder(final boolean useSnapshot) - { - return this; - } - - @Override - public @NotNull List getViewers() - { - return new ArrayList<>(); + this.contents = items; } @Override @@ -272,7 +259,7 @@ public abstract class Displayable implements Inventory, InventoryHolder if (content != null && content.isSimilar(item)) { totalAmount += content.getAmount(); - if (totalAmount >= amount) + if (totalAmount == amount) { return true; } @@ -304,7 +291,8 @@ public abstract class Displayable implements Inventory, InventoryHolder } @Override - public @NotNull HashMap all(final @NotNull Material material) throws IllegalArgumentException + public @NotNull HashMap all(final @NotNull Material material) + throws IllegalArgumentException { final HashMap matchingItems = new HashMap<>(); for (int i = 0; i < size; i++) @@ -439,4 +427,53 @@ public abstract class Displayable implements Inventory, InventoryHolder { return 0; } + + @Override + public @NotNull List getViewers() + { + return new ArrayList<>(); + } + + @Override + public @NotNull InventoryType getType() + { + return InventoryType.CHEST; + } + + @Override + public @Nullable InventoryHolder getHolder() + { + return this; + } + + @Override + public @Nullable InventoryHolder getHolder(final boolean useSnapshot) + { + return this; + } + + @Override + public @NotNull ListIterator iterator() + { + return iterator(0); + } + + @Override + public @NotNull ListIterator iterator(final int index) + { + return List.of(contents) + .listIterator(index); + } + + @Override + public @Nullable Location getLocation() + { + return null; + } + + @Override + public @NotNull Inventory getInventory() + { + return this; + } } diff --git a/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java b/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java index 577adc4..9a5eb2a 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java @@ -16,7 +16,8 @@ public class DisplayableView extends InventoryView private final InventoryType type; private String title; - public DisplayableView(final Player player, final Displayable top, final Displayable bottom) { + public DisplayableView(final Player player, final Displayable top, final Displayable bottom) + { this.player = player; this.top = top; this.bottom = bottom; diff --git a/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntityData.java b/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntityData.java index 308a6c0..061c4a7 100644 --- a/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntityData.java +++ b/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntityData.java @@ -6,9 +6,9 @@ public interface EconomicEntityData long getBalance(); + void setBalance(final long newBalance); + long addToBalance(final long amount); long removeFromBalance(final long amount); - - void setBalance(final long newBalance); } diff --git a/Patchwork/src/main/java/me/totalfreedom/economy/MutableTransaction.java b/Patchwork/src/main/java/me/totalfreedom/economy/MutableTransaction.java index 8548fa7..ba09b9e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/economy/MutableTransaction.java +++ b/Patchwork/src/main/java/me/totalfreedom/economy/MutableTransaction.java @@ -1,7 +1,8 @@ package me.totalfreedom.economy; /** - * Please ensure that all modifications of {@link MutableTransaction} happen BEFORE it is passed to a {@link Transactor} implementation + * Please ensure that all modifications of {@link MutableTransaction} happen BEFORE it is passed to a + * {@link Transactor} implementation */ public interface MutableTransaction extends Transaction { diff --git a/Patchwork/src/main/java/me/totalfreedom/event/EventBus.java b/Patchwork/src/main/java/me/totalfreedom/event/EventBus.java index ad4c006..67b8514 100644 --- a/Patchwork/src/main/java/me/totalfreedom/event/EventBus.java +++ b/Patchwork/src/main/java/me/totalfreedom/event/EventBus.java @@ -27,9 +27,10 @@ public class EventBus extends Service public T getEvent(final Class eventClass) { final FEvent e = eventSet.stream() - .filter(event -> event.getEventClass().equals(eventClass)) - .findFirst() - .orElse(null); + .filter(event -> event.getEventClass() + .equals(eventClass)) + .findFirst() + .orElse(null); return eventClass.cast(e); } @@ -37,10 +38,11 @@ public class EventBus extends Service public EventSubscription subscribe(final Class eventClass, final Callback callback) { final Context eventContext = () -> eventSet.stream() - .filter(event -> event.getEventClass().equals(eventClass)) - .findFirst() - .map(eventClass::cast) - .orElse(null); + .filter(event -> event.getEventClass() + .equals(eventClass)) + .findFirst() + .map(eventClass::cast) + .orElse(null); if (eventContext.get() == null) { diff --git a/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java b/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java index f072e3c..6feb564 100644 --- a/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java +++ b/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java @@ -7,24 +7,32 @@ class SubscriptionBox { private final List> subscriptions; - public SubscriptionBox() { + public SubscriptionBox() + { this.subscriptions = new ArrayList<>(); } - public void addSubscription(final EventSubscription subscription) { + public void addSubscription(final EventSubscription subscription) + { subscriptions.add(subscription); } - public void removeSubscription(final EventSubscription subscription) { + public void removeSubscription(final EventSubscription subscription) + { subscriptions.remove(subscription); } - public void tick() { - subscriptions.forEach(s -> { - if (!s.event().shouldCall()) return; + public void tick() + { + subscriptions.forEach(s -> + { + if (!s.event() + .shouldCall()) return; - s.callback().call(s.event()); - s.event().reset(); - }); + s.callback() + .call(s.event()); + s.event() + .reset(); + }); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java b/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java index 68707fb..891a56e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java +++ b/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java @@ -1,11 +1,31 @@ package me.totalfreedom.particle; import org.bukkit.Color; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.UUID; + public interface Trail { + @NotNull + UUID getAssocPlayerUUID(); + + // Nullable because the player may not be online and trail selections should be persistent whether they are + // active or not. + @Nullable + Player getAssocPlayer(); + + @NotNull TrailType getTrailType(); - @Nullable Color getColor(); + @NotNull + Color getColor(); + + void setColor(@NotNull Color color); + + boolean isActive(); + + void setActive(boolean active); } diff --git a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java index 9c278f5..189fe37 100644 --- a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java +++ b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java @@ -14,21 +14,22 @@ import java.util.stream.Stream; public class ContextProvider { - public Object fromString(final String string) + public T fromString(final String string, final Class clazz) { return Stream.of(toBoolean(string), - toDouble(string), - toInt(string), - toLong(string), - toFloat(string), - toPlayer(string), - toWorld(string), - toLocation(string), - toCommandSender(string), - toComponent(string)) - .filter(Objects::nonNull) - .findFirst() - .orElse(string); + toDouble(string), + toInt(string), + toLong(string), + toFloat(string), + toPlayer(string), + toWorld(string), + toLocation(string), + toCommandSender(string), + toComponent(string)) + .filter(Objects::nonNull) + .findFirst() + .map(clazz::cast) + .orElse(null); } private @Nullable Boolean toBoolean(final String string) @@ -36,7 +37,8 @@ public class ContextProvider try { return Boolean.parseBoolean(string); - } catch (Exception e) + } + catch (Exception ignored) { return null; } @@ -47,7 +49,8 @@ public class ContextProvider try { return Double.parseDouble(string); - } catch (Exception e) + } + catch (Exception ignored) { return null; } @@ -58,7 +61,8 @@ public class ContextProvider try { return Integer.parseInt(string); - } catch (Exception e) + } + catch (Exception ignored) { return null; } @@ -69,7 +73,8 @@ public class ContextProvider try { return Long.parseLong(string); - } catch (Exception e) + } + catch (Exception ignored) { return null; } @@ -80,7 +85,8 @@ public class ContextProvider try { return Float.parseFloat(string); - } catch (Exception e) + } + catch (Exception ignored) { return null; } @@ -91,20 +97,11 @@ public class ContextProvider return Bukkit.getPlayer(string); } - private @Nullable CommandSender toCommandSender(final String string) - { - if (toPlayer(string) == null) return null; - - return toPlayer(string); - } - private @Nullable World toWorld(final String string) { return Bukkit.getWorld(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 *
@@ -127,6 +124,13 @@ public class ContextProvider return new Location(toWorld(split[0]), x, y, z); } + private @Nullable CommandSender toCommandSender(final String string) + { + if (toPlayer(string) == null) return null; + + return toPlayer(string); + } + private @NotNull Component toComponent(final String string) { return Component.text(string); diff --git a/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java b/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java index 79c175f..b6f004a 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java @@ -3,10 +3,10 @@ package me.totalfreedom.security.ban; /** * Represents an ID for a ban. These are formatted either as: *

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

* Where P marks a ban as permanent, and T marks a ban as temporary. */ @@ -19,6 +19,23 @@ public interface BanID */ String getID(); + /** + * 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()); + } + /** * 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. @@ -34,19 +51,4 @@ public interface BanID * @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/perm/Node.java b/Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java index d31f054..d661221 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java @@ -21,11 +21,7 @@ public interface Node boolean isExpired(); - boolean isPermanent(); - boolean isTemporary(); boolean wildcard(); - - boolean negated(); } diff --git a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java index bc728ff..6c6542d 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java @@ -13,38 +13,30 @@ public class FreedomExecutor public FreedomExecutor() { - syncExecutor = r -> Bukkit.getScheduler().runTask(CommonsBase.getInstance(), r); - asyncExecutor = r -> Bukkit.getScheduler().runTaskAsynchronously(CommonsBase.getInstance(), r); - } - - public Executor getSync() - { - return syncExecutor; - } - - public Executor getAsync() - { - return asyncExecutor; + syncExecutor = r -> Bukkit.getScheduler() + .runTask(CommonsBase.getInstance(), r); + asyncExecutor = r -> Bukkit.getScheduler() + .runTaskAsynchronously(CommonsBase.getInstance(), r); } public Executor scheduled(final long delay, final long period) { return r -> Bukkit.getScheduler() - .runTaskTimer( - CommonsBase.getInstance(), - r, - delay, - period); + .runTaskTimer( + CommonsBase.getInstance(), + r, + delay, + period); } public Executor scheduledAsync(final long delay, final long period) { return r -> Bukkit.getScheduler() - .runTaskTimerAsynchronously( - CommonsBase.getInstance(), - r, - delay, - period); + .runTaskTimerAsynchronously( + CommonsBase.getInstance(), + r, + delay, + period); } public void runSync(@NotNull final Task task) @@ -52,8 +44,18 @@ public class FreedomExecutor getSync().execute(task); } + public Executor getSync() + { + return syncExecutor; + } + public void runAsync(@NotNull final Task task) { getAsync().execute(task); } + + public Executor getAsync() + { + return asyncExecutor; + } } diff --git a/Patchwork/src/main/java/me/totalfreedom/service/Service.java b/Patchwork/src/main/java/me/totalfreedom/service/Service.java index ff4c9fc..df33c00 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/Service.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/Service.java @@ -17,24 +17,24 @@ public abstract class Service { isActive = true; CommonsBase.getInstance() - .getExecutor() - .getSync() - .execute(() -> - { - while (isActive) - { - tick(); - } - }); + .getExecutor() + .getSync() + .execute(() -> + { + while (isActive) + { + tick(); + } + }); } + public abstract void tick(); + public void stop() { isActive = false; } - public abstract void tick(); - public String getName() { return name; diff --git a/Patchwork/src/main/java/me/totalfreedom/sql/SQL.java b/Patchwork/src/main/java/me/totalfreedom/sql/SQL.java index 717f685..4e9adc1 100644 --- a/Patchwork/src/main/java/me/totalfreedom/sql/SQL.java +++ b/Patchwork/src/main/java/me/totalfreedom/sql/SQL.java @@ -1,14 +1,11 @@ package me.totalfreedom.sql; -import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.concurrent.CompletableFuture; public interface SQL { - CompletableFuture getConnection(final String url); - CompletableFuture prepareStatement(final String query, final Object... args); CompletableFuture executeQuery(final String query, final Object... args); diff --git a/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java b/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java index b7ee58d..2a3a448 100644 --- a/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java +++ b/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java @@ -19,6 +19,15 @@ public interface SQLProperties return properties; } + default String toURLPlain() + { + return String.format("jdbc:%s://%s:%s/%s", + this.getDriver(), + this.getHost(), + this.getPort(), + this.getDatabase()); + } + String getDriver(); String getHost(); @@ -27,27 +36,18 @@ public interface SQLProperties String getDatabase(); - String getUsername(); - - String getPassword(); - - default String toURLPlain() - { - return String.format("jdbc:%s://%s:%s/%s", - this.getDriver(), - this.getHost(), - this.getPort(), - this.getDatabase()); - } - default String toURLWithLogin() { return String.format("jdbc:%s://%s:%s/%s?user=%s&password=%s", - this.getDriver(), - this.getHost(), - this.getPort(), - this.getDatabase(), - this.getUsername(), - this.getPassword()); + this.getDriver(), + this.getHost(), + this.getPort(), + this.getDatabase(), + this.getUsername(), + this.getPassword()); } + + String getUsername(); + + String getPassword(); } diff --git a/Patchwork/src/main/java/me/totalfreedom/user/User.java b/Patchwork/src/main/java/me/totalfreedom/user/User.java index b83876e..20f58e6 100644 --- a/Patchwork/src/main/java/me/totalfreedom/user/User.java +++ b/Patchwork/src/main/java/me/totalfreedom/user/User.java @@ -1,12 +1,18 @@ package me.totalfreedom.user; -import me.totalfreedom.security.perm.PermissionHolder; import me.totalfreedom.economy.EconomicEntity; import me.totalfreedom.economy.EconomicEntityData; +import me.totalfreedom.security.perm.PermissionHolder; import net.kyori.adventure.text.Component; public interface User extends PermissionHolder, EconomicEntity { + @Override + default EconomicEntityData getEconomicData() + { + return getUserData(); + } + // Implement a few EconomicEntity methods in the User interface @Override default String getName() @@ -14,12 +20,6 @@ public interface User extends PermissionHolder, EconomicEntity return getUserData().getUsername(); } - @Override - default EconomicEntityData getEconomicData() - { - return getUserData(); - } - UserData getUserData(); Component getDisplayName(); diff --git a/Patchwork/src/main/java/me/totalfreedom/user/UserData.java b/Patchwork/src/main/java/me/totalfreedom/user/UserData.java index e7b4253..1ceb5ed 100644 --- a/Patchwork/src/main/java/me/totalfreedom/user/UserData.java +++ b/Patchwork/src/main/java/me/totalfreedom/user/UserData.java @@ -1,7 +1,7 @@ package me.totalfreedom.user; -import me.totalfreedom.security.perm.Group; import me.totalfreedom.economy.EconomicEntityData; +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/FreedomAdventure.java b/Patchwork/src/main/java/me/totalfreedom/utils/FreedomAdventure.java index fc28035..727869f 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomAdventure.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/FreedomAdventure.java @@ -6,27 +6,29 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import java.util.function.Supplier; /** - * This class contains the only reference to plain text component serializer, and allows access to it via wrapper functions. + * This class contains the only reference to plain text component serializer, and allows access to it via wrapper + * functions. */ public class FreedomAdventure { + private static final PlainTextComponentSerializer PLAIN_TEXT_COMPONENT_SERIALIZER = + PlainTextComponentSerializer.plainText(); + private FreedomAdventure() { throw new UnsupportedOperationException("Instantiation of a static utility class is not supported."); } - private static final PlainTextComponentSerializer PLAIN_TEXT_COMPONENT_SERIALIZER = PlainTextComponentSerializer.plainText(); + public static String toPlainText(final Supplier supplier) + { + return toPlainText(supplier.get()); + } public static String toPlainText(final Component component) { return PLAIN_TEXT_COMPONENT_SERIALIZER.serialize(component); } - public static String toPlainText(final Supplier supplier) - { - return toPlainText(supplier.get()); - } - public static Supplier supplyPlainText(final Supplier supplier) { return new StringRepresentationSupplier(supplier.get()); diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java b/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java index 4ec4b82..0f2345e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java @@ -31,30 +31,6 @@ public class FreedomLogger implements Audience this.debug = debug; } - /** - * This method allows you to log a message to the console. - * - * @param message The message to send. - */ - public void info(final String message) - { - logger.info(message); - } - - /** - * This method allows you to log a component to the console. - * - * @param component The component to send. - * @return A plain text representation of the message - */ - public String infoComponent(final Component component) - { - final String plainText = FreedomAdventure.toPlainText(component); - - logger.info(plainText); - return plainText; - } - /** * This method allows you to log a message to the console, * while also returning a Component that could be used to @@ -80,6 +56,28 @@ public class FreedomLogger implements Audience public String infoComponent(final Supplier component) { return this.infoComponent(component.get()); + } /** + * This method allows you to log a message to the console. + * + * @param message The message to send. + */ + public void info(final String message) + { + logger.info(message); + } + + /** + * This method allows you to log a component to the console. + * + * @param component The component to send. + * @return A plain text representation of the message + */ + public String infoComponent(final Component component) + { + final String plainText = FreedomAdventure.toPlainText(component); + + logger.info(plainText); + return plainText; } /** @@ -116,20 +114,6 @@ public class FreedomLogger implements Audience logger.error(message); } - /** - * This method logs an error component to the console. - * - * @param component The message to send. - */ - public String errorComponent(final Component component) - { - final String plainText = FreedomAdventure.toPlainText(component); - - logger.error(plainText); - - return plainText; - } - /** * This method allows you to log an exception directly to the console. * @@ -170,28 +154,15 @@ public class FreedomLogger implements Audience } /** - * This method allows you to log a debug message to the console. - * This method will only log if debug mode is enabled. + * This method logs an error component to the console. * - * @param message The message to send. + * @param component The message to send. */ - public void debug(final String message) - { - if (debug) - logger.debug(message); - } - - /** - * This method allows you to log a debug component to the console. - * This method will only log if debug mode is enabled. - * - * @param component The component to send. - */ - public String debugComponent(final Component component) + public String errorComponent(final Component component) { final String plainText = FreedomAdventure.toPlainText(component); - this.debug(plainText); + logger.error(plainText); return plainText; } @@ -231,6 +202,35 @@ public class FreedomLogger implements Audience return ""; } + /** + * This method allows you to log a debug component to the console. + * This method will only log if debug mode is enabled. + * + * @param component The component to send. + */ + public String debugComponent(final Component component) + { + final String plainText = FreedomAdventure.toPlainText(component); + + this.debug(plainText); + + return plainText; + } + + /** + * This method allows you to log a debug message to the console. + * This method will only log if debug mode is enabled. + * + * @param message The message to send. + */ + public void debug(final String message) + { + if (debug) + logger.debug(message); + } + + + @Override public void sendMessage(@NotNull final ComponentLike message) @@ -267,6 +267,9 @@ public class FreedomLogger implements Audience @Override 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. + 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. } } diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/KyoriConstants.java b/Patchwork/src/main/java/me/totalfreedom/utils/KyoriConstants.java index 6748faf..46bb8d8 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/KyoriConstants.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/KyoriConstants.java @@ -9,7 +9,8 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; /** - * This class contains different methods to provide {@link ChatType.Bound} instances for sending messages to players in game. + * This class contains different methods to provide {@link ChatType.Bound} instances for sending messages to players + * in game. * This is now a requirement for all message requests to players due to the new chat signature system. *
* Even though Scissors has this feature disabled, upstream (Paper) and Kyori Adventure @@ -30,13 +31,6 @@ public final class KyoriConstants { } - public static ChatType.Bound fromPlugin(final JavaPlugin plugin) - { - final String name = plugin.getName(); - final Component component = Component.text(name, NamedTextColor.GOLD); - return type.bind(component); - } - /** * Represents a Chat Bound for a plugin. *
@@ -53,6 +47,13 @@ public final class KyoriConstants return fromPlugin(plugin); } + public static ChatType.Bound fromPlugin(final JavaPlugin plugin) + { + final String name = plugin.getName(); + final Component component = Component.text(name, NamedTextColor.GOLD); + return type.bind(component); + } + /** * Represents a Chat Bound for a player. * Chat bounds are required for sending messages to players. @@ -73,6 +74,7 @@ public final class KyoriConstants *
* The chat bound is a representation of a validated chat signature, * which is tied directly to the user's account name. In our case, this is the player's name. + * * @param sender The console to get the bound for. * @return A ChatType.Bound instance for the console. */ diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/Shaper.java b/Patchwork/src/main/java/me/totalfreedom/utils/Shaper.java index 66ecd9d..7f3dfdc 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/Shaper.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/Shaper.java @@ -20,7 +20,8 @@ public class Shaper this.world = world; } - public List generate(final int count, final DoubleUnaryOperator x, final DoubleUnaryOperator y, final DoubleUnaryOperator z) + public List generate(final int count, final DoubleUnaryOperator x, final DoubleUnaryOperator y, + final DoubleUnaryOperator z) { final double step = (start - end) / (count - 1); final LinkedList lset = new LinkedList<>(); diff --git a/README.md b/README.md index 8d9dc51..345f2ac 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,27 @@ [Google GSON]: https://github.com/google/gson "Google GSON" + [Jetbrains Annotations]: https://github.com/JetBrains/JetBrains.Annotations "JetBrains Annotations" + [Lombok]: https://github.com/projectlombok/lombok "Lombok" + [Apache Commons]: https://github.com/apache/commons-lang "Apache Commons" + [SLF4J]: https://github.com/qos-ch/slf4j "SLF4J" + [Paper]: https://github.com/PaperMC/Paper "Paper" + [Kyori Adventure]: https://github.com/KyoriPowered/adventure "Kyori Adventure" + [Reflections API]: https://github.com/ronmamo/reflections "Reflections API" + [TotalFreedomMod]: https://github.com/AtlasMediaGroup/TotalFreedomMod "TotalFreedomMod" ##### + ![Header Image](https://media.discordapp.net/attachments/436759124953399296/1107175759941996544/20230514_002037_0000.png) ### + [](https://discord.gg/4PdtmrVNRx) ![GitHub contributors](https://img.shields.io/github/contributors/SimplexDevelopment/FreedomNetworkSuite?style=for-the-badge) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/SimplexDevelopment/FreedomNetworkSuite?style=for-the-badge) @@ -21,6 +31,7 @@ ![Codacy grade](https://img.shields.io/codacy/grade/7a0fa4694878444dabc6cc2804fbf125?style=for-the-badge) ### + [](https://docs.google.com/document/d/197fwNo076RsCiPW6e6QWaGEzTGnDcRuf5FBA6lNeiPE) [](https://github.com/SimplexDevelopment/FreedomNetworkSuite/blob/kitchen-sink/LICENSE.md) ![GitHub top language](https://img.shields.io/github/languages/top/SimplexDevelopment/FreedomNetworkSuite?style=for-the-badge&logo=github) @@ -40,16 +51,18 @@ Honorable mention: [](https://github.com/plexusorg/Plex) This proof-of-concept also uses the following libraries: - - [Google GSON] for Json interpretation - - [Jetbrains Annotations] for additional compiler annotations - - [Lombok] for boilerplate generation - - [Apache Commons] for various utilities - - [SLF4J] for logging - - [Paper] for the server implementation - - [Kyori Adventure] for chat formatting - - [Reflections API] for reflections + +- [Google GSON] for Json interpretation +- [Jetbrains Annotations] for additional compiler annotations +- [Lombok] for boilerplate generation +- [Apache Commons] for various utilities +- [SLF4J] for logging +- [Paper] for the server implementation +- [Kyori Adventure] for chat formatting +- [Reflections API] for reflections # Developers + [](https://github.com/Paldiu)
[](https://github.com/VideoGameSmash12) @@ -57,7 +70,9 @@ This proof-of-concept also uses the following libraries: [](https://github.com/allinkdev) # To Do List + Patchwork: + - [x] Logging System - [x] SQL API - [x] Economy API @@ -72,6 +87,7 @@ Patchwork: - [ ] Event API Datura: + - [ ] Permission Handling - [ ] Permission Registration & Assignment - [ ] SQL Data Handling @@ -81,6 +97,7 @@ Datura: - [ ] Punishment Systems (e.x. Locker, Halter, Muter, Cager) Fossil: + - [x] Economy Implementation - [ ] Particle Implementation / Trails - [ ] Command Implementations @@ -89,6 +106,7 @@ Fossil: - [ ] Jumppads Corvo: + - [ ] Service Implementation - [ ] Service Handling - [ ] Task Implementation