From b95a06fa7c41d7af5bce602c1bad73e549f6ea94 Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Thu, 25 May 2023 13:13:32 -0500 Subject: [PATCH 01/14] Start implementing GUI API --- .../me/totalfreedom/display/Displayable.java | 442 ++++++++++++++++++ .../totalfreedom/display/DisplayableView.java | 68 +++ 2 files changed, 510 insertions(+) create mode 100644 Patchwork/src/main/java/me/totalfreedom/display/Displayable.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java diff --git a/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java b/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java new file mode 100644 index 0000000..a60fad8 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java @@ -0,0 +1,442 @@ +package me.totalfreedom.display; + +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; + +public abstract class Displayable implements Inventory, InventoryHolder +{ + + private final int size; + private final ItemStack[] contents; + + protected Displayable(final int size) + { + if (size < 1 || size > 54) + { + throw new IllegalArgumentException("Invalid size for Displayable inventory"); + } + + this.size = (size % 9 == 0) + ? size + : size + (9 - size % 9); + + this.contents = new ItemStack[size]; + } + + @Override + public int getSize() + { + return size; + } + + @Override + public int getMaxStackSize() + { + return 64; + } + + /** + * @param size The new maximum stack size for items in this inventory. + * @deprecated This method is not supported by Displayable inventories. + */ + @Override + @Deprecated(since = "1.19.4") + public void setMaxStackSize(final int size) + { + // No implementation required + } + + @Override + public @Nullable ItemStack getItem(final int index) + { + if (index < 0 || index >= size) + { + return null; + } + return contents[index]; + } + + @Override + public void setItem(final int index, final @Nullable ItemStack item) + { + if (index < 0 || index >= size) + { + return; + } + contents[index] = item; + } + + @Override + public @NotNull HashMap addItem(final @NotNull ItemStack... items) throws IllegalArgumentException + { + final HashMap remainingItems = new HashMap<>(); + + for (final ItemStack item : items) + { + int remainingAmount = item.getAmount(); + + for (int i = 0; i < size; i++) + { + final ItemStack current = contents[i]; + + if (current == null) + { + final int maxStackSize = item.getMaxStackSize(); + final int amountToAdd = Math.min(remainingAmount, maxStackSize); + final ItemStack clone = item.clone(); + clone.setAmount(amountToAdd); + contents[i] = clone; + remainingAmount -= amountToAdd; + + if (remainingAmount == 0) + { + break; + } + } + } + + if (remainingAmount > 0) + { + remainingItems.put(remainingItems.size(), new ItemStack(item.getType(), remainingAmount)); + } + } + + return remainingItems; + } + + @Override + public @NotNull HashMap removeItem(final @NotNull ItemStack... items) throws IllegalArgumentException + { + final HashMap removedItems = new HashMap<>(); + + for (final ItemStack item : items) + { + int remainingAmount = item.getAmount(); + + for (int i = 0; i < size; i++) + { + final ItemStack current = contents[i]; + + if (current != null && current.isSimilar(item)) + { + final int amountToRemove = Math.min(remainingAmount, current.getAmount()); + current.setAmount(current.getAmount() - amountToRemove); + remainingAmount -= amountToRemove; + + if (current.getAmount() <= 0) + { + contents[i] = null; + } + + if (remainingAmount == 0) + { + break; + } + } + } + + if (remainingAmount < item.getAmount()) + { + removedItems.put(removedItems.size(), new ItemStack(item.getType(), item.getAmount() - remainingAmount)); + } + } + + return removedItems; + } + + @Override + public @Nullable ItemStack @NotNull [] getContents() + { + return contents.clone(); + } + + @Override + public void setContents(final @Nullable ItemStack @NotNull [] items) throws IllegalArgumentException + { + if (items == null) + { + throw new IllegalArgumentException("Items cannot be null"); + } + if (items.length != size) + { + throw new IllegalArgumentException("Invalid size of items array"); + } + System.arraycopy(items, 0, contents, 0, size); + } + + @Override + public @NotNull ListIterator iterator() + { + return iterator(0); + } + + @Override + public @NotNull ListIterator iterator(final int index) + { + 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<>(); + } + + @Override + public boolean contains(final @NotNull Material material) throws IllegalArgumentException + { + for (final ItemStack item : contents) + { + if (item != null && item.getType() == material) + { + return true; + } + } + return false; + } + + @Override + public boolean contains(final @Nullable ItemStack item) + { + if (item == null) + { + return false; + } + for (final ItemStack content : contents) + { + if (content != null && content.isSimilar(item)) + { + return true; + } + } + return false; + } + + @Override + public boolean contains(final @NotNull Material material, final int amount) throws IllegalArgumentException + { + int totalAmount = 0; + for (final ItemStack item : contents) + { + if (item != null && item.getType() == material) + { + totalAmount += item.getAmount(); + if (totalAmount >= amount) + { + return true; + } + } + } + return false; + } + + @Override + public boolean contains(final @Nullable ItemStack item, final int amount) + { + if (item == null) + { + return false; + } + int totalAmount = 0; + for (final ItemStack content : contents) + { + if (content != null && content.isSimilar(item)) + { + totalAmount += content.getAmount(); + if (totalAmount >= amount) + { + return true; + } + } + } + return false; + } + + @Override + public boolean containsAtLeast(final @Nullable ItemStack item, final int amount) + { + if (item == null) + { + return false; + } + int totalAmount = 0; + for (final ItemStack content : contents) + { + if (content != null && content.isSimilar(item)) + { + totalAmount += content.getAmount(); + if (totalAmount >= amount) + { + return true; + } + } + } + return false; + } + + @Override + public @NotNull HashMap all(final @NotNull Material material) throws IllegalArgumentException + { + final HashMap matchingItems = new HashMap<>(); + for (int i = 0; i < size; i++) + { + final ItemStack item = contents[i]; + if (item != null && item.getType() == material) + { + matchingItems.put(i, item); + } + } + return matchingItems; + } + + @Override + public @NotNull HashMap all(final @Nullable ItemStack item) + { + final HashMap matchingItems = new HashMap<>(); + if (item != null) + { + for (int i = 0; i < size; i++) + { + final ItemStack content = contents[i]; + if (content != null && content.isSimilar(item)) + { + matchingItems.put(i, content); + } + } + } + return matchingItems; + } + + @Override + public int first(final @NotNull Material material) throws IllegalArgumentException + { + for (int i = 0; i < size; i++) + { + final ItemStack item = contents[i]; + if (item != null && item.getType() == material) + { + return i; + } + } + return -1; + } + + @Override + public int first(final @NotNull ItemStack item) + { + for (int i = 0; i < size; i++) + { + final ItemStack content = contents[i]; + if (content != null && content.isSimilar(item)) + { + return i; + } + } + return -1; + } + + @Override + public int firstEmpty() + { + for (int i = 0; i < size; i++) + { + if (contents[i] == null) + { + return i; + } + } + return -1; + } + + @Override + public boolean isEmpty() + { + for (final ItemStack content : contents) + { + if (content != null) + { + return false; + } + } + return true; + } + + @Override + public void remove(final @NotNull Material material) throws IllegalArgumentException + { + for (int i = 0; i < size; i++) + { + final ItemStack item = contents[i]; + if (item != null && item.getType() == material) + { + contents[i] = null; + } + } + } + + @Override + public void remove(final @NotNull ItemStack item) + { + for (int i = 0; i < size; i++) + { + final ItemStack content = contents[i]; + if (content != null && content.isSimilar(item)) + { + contents[i] = null; + } + } + } + + @Override + public void clear(final int index) + { + if (index >= 0 && index < size) + { + contents[index] = null; + } + } + + @Override + public void clear() + { + for (int i = 0; i < size; i++) + { + contents[i] = null; + } + } + + @Override + public int close() + { + return 0; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java b/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java new file mode 100644 index 0000000..577adc4 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java @@ -0,0 +1,68 @@ +package me.totalfreedom.display; + +import me.totalfreedom.utils.FreedomAdventure; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.jetbrains.annotations.NotNull; + +public class DisplayableView extends InventoryView +{ + private final Displayable top; + private final Displayable bottom; + private final Player player; + private final InventoryType type; + private String title; + + public DisplayableView(final Player player, final Displayable top, final Displayable bottom) { + this.player = player; + this.top = top; + this.bottom = bottom; + this.type = InventoryType.CHEST; + this.title = FreedomAdventure.toPlainText(type.defaultTitle()); + } + + @Override + public @NotNull Inventory getTopInventory() + { + return top; + } + + @Override + public @NotNull Inventory getBottomInventory() + { + return bottom; + } + + @Override + public @NotNull HumanEntity getPlayer() + { + return player; + } + + @Override + public @NotNull InventoryType getType() + { + return type; + } + + @Override + public @NotNull String getTitle() + { + return title; + } + + @Override + public @NotNull String getOriginalTitle() + { + return FreedomAdventure.toPlainText(type.defaultTitle()); + } + + @Override + public void setTitle(final @NotNull String title) + { + this.title = title; + } +} From def84bd7471c174e86be468ed600666d01f7e506 Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Tue, 30 May 2023 17:39:54 -0500 Subject: [PATCH 02/14] updates :8ball: --- .github/workflows/gradle.yml | 20 +- .../java/me/totalfreedom/corvo/Corvo.java | 18 +- .../java/me/totalfreedom/datura/Datura.java | 34 ++- .../totalfreedom/datura/banning/BanUID.java | 66 ----- .../datura/banning/SimpleBan.java | 82 ------ .../totalfreedom/datura/cmd/KickCommand.java | 26 -- .../datura/cmd/LockerCommand.java | 41 +++ .../datura/perms/DefaultNodes.java | 64 +++-- .../datura/perms/FreedomGroup.java | 82 +++--- .../datura/perms/FreedomUser.java | 47 ++-- .../datura/perms/PermissionNode.java | 24 +- .../totalfreedom/datura/punishment/Cager.java | 84 +++--- .../datura/punishment/Halter.java | 3 +- .../datura/punishment/Locker.java | 34 ++- .../me/totalfreedom/datura/sql/DBBan.java | 89 ------ .../me/totalfreedom/datura/sql/MySQL.java | 254 ++++++++++++++---- .../me/totalfreedom/datura/sql/Result.java | 14 + .../datura/user/SimpleUserData.java | 131 ++++----- .../java/me/totalfreedom/fossil/Fossil.java | 6 +- .../fossil/economy/SimpleTransaction.java | 2 +- .../economy/SimpleTransactionLogger.java | 28 +- .../economy/SimpleTransactionResult.java | 13 +- .../me/totalfreedom/fossil/shop/Shoppe.java | 5 + .../fossil/shop/menus/MainMenu.java | 11 + .../java/me/totalfreedom/api/Context.java | 31 ++- .../audience/MutableAudienceForwarder.java | 9 +- .../me/totalfreedom/base/CommonsBase.java | 31 ++- .../me/totalfreedom/base/Registration.java | 14 +- .../totalfreedom/command/BukkitDelegate.java | 188 +++++++++++++ .../totalfreedom/command/BukkitDelegator.java | 171 ------------ .../me/totalfreedom/command/CommandBase.java | 89 ------ .../totalfreedom/command/CommandHandler.java | 11 +- .../me/totalfreedom/command/Commander.java | 108 ++++++++ .../command/annotation/Completion.java | 4 +- .../command/annotation/Completions.java | 13 + .../command/annotation/Subcommand.java | 3 + .../me/totalfreedom/data/BanRegistry.java | 34 --- .../me/totalfreedom/data/GroupRegistry.java | 18 +- .../me/totalfreedom/data/ModuleRegistry.java | 3 +- .../me/totalfreedom/data/ServiceRegistry.java | 29 +- .../me/totalfreedom/display/AbstractMenu.java | 121 +++++++++ .../me/totalfreedom/display/ClickAction.java | 9 + .../me/totalfreedom/display/Displayable.java | 113 +++++--- .../totalfreedom/display/DisplayableView.java | 3 +- .../economy/EconomicEntityData.java | 4 +- .../economy/MutableTransaction.java | 3 +- .../java/me/totalfreedom/event/EventBus.java | 16 +- .../totalfreedom/event/SubscriptionBox.java | 26 +- .../java/me/totalfreedom/particle/Trail.java | 22 +- .../provider/ContextProvider.java | 58 ++-- .../me/totalfreedom/security/ban/BanID.java | 40 +-- .../me/totalfreedom/security/perm/Node.java | 4 - .../totalfreedom/service/FreedomExecutor.java | 46 ++-- .../java/me/totalfreedom/service/Service.java | 22 +- .../main/java/me/totalfreedom/sql/SQL.java | 3 - .../me/totalfreedom/sql/SQLProperties.java | 38 +-- .../main/java/me/totalfreedom/user/User.java | 14 +- .../java/me/totalfreedom/user/UserData.java | 2 +- .../totalfreedom/utils/FreedomAdventure.java | 16 +- .../me/totalfreedom/utils/FreedomLogger.java | 115 ++++---- .../me/totalfreedom/utils/KyoriConstants.java | 18 +- .../java/me/totalfreedom/utils/Shaper.java | 3 +- README.md | 34 ++- 63 files changed, 1469 insertions(+), 1195 deletions(-) delete mode 100644 Datura/src/main/java/me/totalfreedom/datura/banning/BanUID.java delete mode 100644 Datura/src/main/java/me/totalfreedom/datura/banning/SimpleBan.java delete mode 100644 Datura/src/main/java/me/totalfreedom/datura/cmd/KickCommand.java create mode 100644 Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java delete mode 100644 Datura/src/main/java/me/totalfreedom/datura/sql/DBBan.java create mode 100644 Datura/src/main/java/me/totalfreedom/datura/sql/Result.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/shop/Shoppe.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/shop/menus/MainMenu.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java delete mode 100644 Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegator.java delete mode 100644 Patchwork/src/main/java/me/totalfreedom/command/CommandBase.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/command/Commander.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/command/annotation/Completions.java delete mode 100644 Patchwork/src/main/java/me/totalfreedom/data/BanRegistry.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java 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 From a632eb778c4d975b2992b47ddfd5a62f22e2b507 Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Thu, 1 Jun 2023 23:02:01 -0500 Subject: [PATCH 03/14] Start implementations --- .../fossil/items/ClownfishItem.java | 28 ++++ .../totalfreedom/fossil/items/ShopItem.java | 34 +++++ .../totalfreedom/fossil/items/TrailItem.java | 21 +++ .../me/totalfreedom/fossil/trail/Trailer.java | 41 ++++++ .../fossil/trail/types/BasicTrail.java | 32 +++++ .../fossil/trail/types/RainbowTrail.java | 46 +++++++ .../fossil/trail/types/SimpleTrail.java | 90 +++++++++++++ .../fossil/trail/types/TrailProvider.java | 12 ++ .../me/totalfreedom/api/Interpolator.java | 7 + .../java/me/totalfreedom/particle/Trail.java | 112 ++++++++++++++-- .../utils/InterpolationUtils.java | 120 ++++++++++++++++++ 11 files changed, 535 insertions(+), 8 deletions(-) create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/items/ClownfishItem.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/items/ShopItem.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/items/TrailItem.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/trail/Trailer.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/trail/types/BasicTrail.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/trail/types/RainbowTrail.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/trail/types/SimpleTrail.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/api/Interpolator.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/items/ClownfishItem.java b/Fossil/src/main/java/me/totalfreedom/fossil/items/ClownfishItem.java new file mode 100644 index 0000000..834d8c1 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/items/ClownfishItem.java @@ -0,0 +1,28 @@ +package me.totalfreedom.fossil.items; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class ClownfishItem extends ShopItem +{ + public ClownfishItem() + { + super(Material.TROPICAL_FISH); + } + + @Override + public void runAction(final @NotNull Player user, final @Nullable Entity target) + { + if (target == null) return; + + final Location location = user.getEyeLocation().clone(); + final Vector vector = location.getDirection().multiply(2); + + target.setVelocity(vector); + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/items/ShopItem.java b/Fossil/src/main/java/me/totalfreedom/fossil/items/ShopItem.java new file mode 100644 index 0000000..04f6bb9 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/items/ShopItem.java @@ -0,0 +1,34 @@ +package me.totalfreedom.fossil.items; + +import org.bukkit.Material; +import org.bukkit.entity.Entity; +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; + +public abstract class ShopItem +{ + private final ItemStack item; + private final ItemMeta meta; + + protected ShopItem(final Material material) + { + this.item = new ItemStack(material, 1); + + this.meta = this.item.getItemMeta(); + } + + public abstract void runAction(@NotNull final Player user, @Nullable final Entity target); + + public ItemStack getItem() + { + return this.item; + } + + public ItemMeta getMeta() + { + return this.meta; + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/items/TrailItem.java b/Fossil/src/main/java/me/totalfreedom/fossil/items/TrailItem.java new file mode 100644 index 0000000..a9e6a7d --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/items/TrailItem.java @@ -0,0 +1,21 @@ +package me.totalfreedom.fossil.items; + +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class TrailItem extends ShopItem +{ + public TrailItem(final Material material) + { + super(material); + } + + @Override + public void runAction(final @NotNull Player user, final @Nullable Entity target) + { + + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/Trailer.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/Trailer.java new file mode 100644 index 0000000..ae51c0b --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/Trailer.java @@ -0,0 +1,41 @@ +package me.totalfreedom.fossil.trail; + +import me.totalfreedom.particle.Trail; +import me.totalfreedom.particle.TrailType; +import me.totalfreedom.service.Service; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class Trailer extends Service +{ + private final List trailList = new ArrayList<>(); + + public Trailer() { + super("trailer_service"); + } + + public void addTrail(final Trail trail) { + this.trailList.add(trail); + } + + public void removeTrail(final Trail trail) { + this.trailList.remove(trail); + } + + @Override + public void tick() + { + for (final Trail trail : trailList) { + if (trail.getAssociatedPlayer().isOnline()) { + final Player player = (Player) trail.getAssociatedPlayer(); + + } + } + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/BasicTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/BasicTrail.java new file mode 100644 index 0000000..94fbb46 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/BasicTrail.java @@ -0,0 +1,32 @@ +package me.totalfreedom.fossil.trail.types; + +import me.totalfreedom.particle.TrailType; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.entity.Player; + +public final class BasicTrail extends SimpleTrail +{ + protected BasicTrail(final Player player) + { + super(player, TrailType.DEFAULT); + super.setColor(Color.RED); + } + + @Override + public void spawnParticle() + { + // Exit immediately if either condition is false. + if (!isActive() || !getAssociatedPlayer().isOnline()) return; + + // Trail is active and the player is online. + final Particle particle = getTrailType().getType(); + final Particle.DustOptions options = new Particle.DustOptions(getColor(), 3); + final Player player = (Player) getAssociatedPlayer(); + final Location location = player.getLocation() + .clone() + .subtract(0, 1, 0); + location.getWorld().spawnParticle(particle, location, 1, 0.0, 0.5, 0.0, options); + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/RainbowTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/RainbowTrail.java new file mode 100644 index 0000000..36b9108 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/RainbowTrail.java @@ -0,0 +1,46 @@ +package me.totalfreedom.fossil.trail.types; + +import me.totalfreedom.particle.TrailType; +import me.totalfreedom.utils.InterpolationUtils; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.entity.Player; + +import java.util.Iterator; + +public final class RainbowTrail extends SimpleTrail +{ + private Iterator currentColor; + + protected RainbowTrail(final Player player) + { + super(player, TrailType.DEFAULT); + setColors(InterpolationUtils.rainbow(40 % 7)); + this.currentColor = getColors().iterator(); + } + + @Override + public void spawnParticle() + { + // Exit immediately if either case is false. + if (!isActive() || !getAssociatedPlayer().isOnline()) return; + + // Re-initialize the color iterator if the iterator has previously reached the end of its index. + if (!currentColor.hasNext()) + { + this.currentColor = getColors().iterator(); + } + + final Color color = currentColor.next(); + final Player player = (Player) getAssociatedPlayer(); + final Particle particle = getTrailType().getType(); + final Particle.DustOptions options = new Particle.DustOptions(color, 3); + final Location location = player.getLocation() + .clone() + .subtract(0, 1, 0); + + location.getWorld() + .spawnParticle(particle, location, 1, 0.0, 0.5, 0.0, options); + } +} \ No newline at end of file diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/SimpleTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/SimpleTrail.java new file mode 100644 index 0000000..c217c64 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/SimpleTrail.java @@ -0,0 +1,90 @@ +package me.totalfreedom.fossil.trail.types; + +import me.totalfreedom.particle.Trail; +import me.totalfreedom.particle.TrailType; +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Set; +import java.util.UUID; + +public abstract class SimpleTrail implements Trail +{ + private final UUID associatedPlayerUUID; + private final TrailType trailType; + + private Color staticColor = null; + private Set gradientColor = null; + private boolean active = false; + + protected SimpleTrail(final Player player, final TrailType trailType) { + this.associatedPlayerUUID = player.getUniqueId(); + this.trailType = trailType; + } + + @Override + public @NotNull UUID getAssociatedPlayerUUID() + { + return associatedPlayerUUID; + } + + @Override + public @NotNull OfflinePlayer getAssociatedPlayer() + { + return Bukkit.getOfflinePlayer(getAssociatedPlayerUUID()); + } + + @Override + public @NotNull TrailType getTrailType() + { + return trailType; + } + + @Override + public @Nullable Color getColor() + { + return staticColor; + } + + @Override + public void setColor(@NotNull final Color color) + { + this.gradientColor = null; + this.staticColor = color; + } + + @Override + public @Nullable Set getColors() + { + return this.gradientColor; + } + + @Override + public void setColors(@NotNull final Set colors) + { + this.staticColor = null; + this.gradientColor = colors; + } + + @Override + public boolean isGradient() + { + return gradientColor != null; + } + + @Override + public boolean isActive() + { + return active; + } + + @Override + public void setActive(final boolean active) + { + this.active = active; + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java new file mode 100644 index 0000000..427bb09 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java @@ -0,0 +1,12 @@ +package me.totalfreedom.fossil.trail.types; + +import org.bukkit.entity.Player; + +public final class TrailProvider +{ + public BasicTrail basicTrail(final Player player) { + return new BasicTrail(player); + } + + +} diff --git a/Patchwork/src/main/java/me/totalfreedom/api/Interpolator.java b/Patchwork/src/main/java/me/totalfreedom/api/Interpolator.java new file mode 100644 index 0000000..7e71edc --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/api/Interpolator.java @@ -0,0 +1,7 @@ +package me.totalfreedom.api; + +@FunctionalInterface +public interface Interpolator +{ + double[] interpolate(final double from, final double to, final int max); +} diff --git a/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java b/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java index 891a56e..2581463 100644 --- a/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java +++ b/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java @@ -1,31 +1,127 @@ package me.totalfreedom.particle; +import me.totalfreedom.api.Interpolator; +import me.totalfreedom.utils.InterpolationUtils; import org.bukkit.Color; -import org.bukkit.entity.Player; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.Particle; +import org.bukkit.World; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Set; import java.util.UUID; +/** + * Represents a Trail instance for a specific player. + */ public interface Trail { + /** + * Returns the UUID of the player associated with the trail. This is for usage with our persistant storage + * container so that we can safely send and retrieve the trails without having to directly reference a player + * object. + *
+ * TL;DR Memory optimization! + * + * @return The UUID of the player associated with this trail. + */ @NotNull - UUID getAssocPlayerUUID(); + UUID getAssociatedPlayerUUID(); - // Nullable because the player may not be online and trail selections should be persistent whether they are - // active or not. - @Nullable - Player getAssocPlayer(); + /** + * Returns the player associated with this trail. Trails are user specific, and should be persistent across all + * usages. This is also used when displaying the particles, as they will be relative to the player's back, which + * is an inverse offset of the player's eye location. We use OfflinePlayer as we can make a simple check and cast + * to determine if the player is online when spawning trails. + * + * @return The player associated with this Trail. + */ + @NotNull + OfflinePlayer getAssociatedPlayer(); + /** + * Gets the Trail Type of this trail. This is used to determine what type of trail this is, and what + * {@link Particle} it should use. + * + * @return The Trail Type of this trail. + * @see TrailType + */ @NotNull TrailType getTrailType(); - @NotNull + /** + * This method is nullable because if the value of {@link #isGradient()} is true, then + * {@link #getColors()} should be used instead, as that will contain the color data for our trail. + *
+ * However, this method will also be null if the particle type is not colorable. + * + * @return The color of the trail, or null if the trail is a gradient or non-colorable. + * @see Particle + * @see #getColors(); + */ + @Nullable Color getColor(); + /** + * Sets the static color of the trail. If you are trying to use a gradient, use {@link #setColors(Set)} instead. + *
+ * + * @param color The color to set the trail to. + */ void setColor(@NotNull Color color); + /** + * This method is nullable because if the value of {@link #isGradient()} is false, then + * {@link #getColor()} should be used instead, as our trail is a single static color. + *
+ * However, this method will also be null if the particle type is not colorable. + * + * @return The colors of the trail, or null if the trail is not a gradient or non-colorable. + * @see #getColor() + * @see Particle + * @see InterpolationUtils + * @see Interpolator + */ + @Nullable + Set getColors(); + + /** + * Sets the colors of the trail. If you are trying to use a static color, use {@link #setColor(Color)} instead. + *
+ * This should be used for trails that iterate over a set of colors, such as a rainbow trail. + * + * @param colors The colors to set the trail to. It is recommended to use {@link InterpolationUtils} to generate + * interpolated gradients for this. + */ + void setColors(@NotNull Set colors); + + /** + * Validates whether this Trail is a gradient or a static trail. + *
+ * This is entirely based on whether {@link #getColors()} returns null or not. + * + * @return True if {@link #getColors()} is not null, false otherwise. + */ + boolean isGradient(); + + /** + * Gets whether the trail is active. + * + * @return True if the trail is active, false if it is not. + */ boolean isActive(); - void setActive(boolean active); + /** + * Turn the trail on or off. + * + * @param active True if the trail should be active, false if it should not. + */ + void setActive(final boolean active); + + /** + * Spawns a particle (if gradient, the next particle) on the supplied location object. + */ + void spawnParticle(); } diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java b/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java new file mode 100644 index 0000000..587f05d --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java @@ -0,0 +1,120 @@ +package me.totalfreedom.utils; + +import me.totalfreedom.api.Interpolator; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import org.bukkit.Color; + +import java.util.LinkedHashSet; +import java.util.Set; + +public class InterpolationUtils +{ + public static Set rainbow(final int length) + { + final LinkedHashSet base = new LinkedHashSet<>(); + final Set redToOrange = hsvGradient(length, Color.RED, Color.ORANGE, InterpolationUtils::linear); + final Set orangeToYellow = hsvGradient(length, Color.ORANGE, Color.YELLOW, InterpolationUtils::linear); + final Set yellowToGreen = hsvGradient(length, Color.YELLOW, Color.GREEN, InterpolationUtils::linear); + final Set greenToBlue = hsvGradient(length, Color.GREEN, Color.BLUE, InterpolationUtils::linear); + final Set blueToPurple = hsvGradient(length, Color.BLUE, Color.PURPLE, InterpolationUtils::linear); + final Set purpleToRed = hsvGradient(length, Color.PURPLE, Color.RED, InterpolationUtils::linear); + base.addAll(redToOrange); + base.addAll(orangeToYellow); + base.addAll(yellowToGreen); + base.addAll(greenToBlue); + base.addAll(blueToPurple); + base.addAll(purpleToRed); + return base; + } + + private static Set hsvGradient(final int length, final Color from, final Color to, + final Interpolator interpolator) + { + // returns a float-array where hsv[0] = hue, hsv[1] = saturation, hsv[2] = value/brightness + final float[] hsvFrom = java.awt.Color.RGBtoHSB(from.getRed(), from.getGreen(), from.getBlue(), null); + final float[] hsvTo = java.awt.Color.RGBtoHSB(to.getRed(), to.getGreen(), to.getBlue(), null); + + final double[] h = interpolator.interpolate(hsvFrom[0], hsvTo[0], length); + final double[] s = interpolator.interpolate(hsvFrom[1], hsvTo[1], length); + final double[] v = interpolator.interpolate(hsvFrom[2], hsvTo[2], length); + + final LinkedHashSet gradient = new LinkedHashSet<>(); + + for (int i = 0; i < length; i++) + { + final int rgb = java.awt.Color.HSBtoRGB((float) h[i], (float) s[i], (float) v[i]); + final Color color = Color.fromRGB(rgb); + gradient.add(color); + } + return gradient; + } + + private static double[] linear(final double from, final double to, final int max) + { + final double[] res = new double[max]; + for (int i = 0; i < max; i++) + { + res[i] = from + i * ((to - from) / (max - 1)); + } + return res; + } + + public static Set rgbGradient(final int length, final Color from, final Color to, + final Interpolator interpolator) + { + final double[] r = interpolator.interpolate(from.getRed(), to.getRed(), length); + final double[] g = interpolator.interpolate(from.getGreen(), to.getGreen(), length); + final double[] b = interpolator.interpolate(from.getBlue(), to.getBlue(), length); + + final LinkedHashSet gradient = new LinkedHashSet<>(); + + for (int i = 0; i < length; i++) + { + final Color color = Color.fromRGB((int) r[i], (int) g[i], (int) b[i]); + gradient.add(color); + } + return gradient; + } + + public static Set rainbowComponent(final int length) + { + final LinkedHashSet base = new LinkedHashSet<>(); + final Set redToOrange = componentRGBGradient(length, NamedTextColor.RED, + NamedTextColor.GOLD, InterpolationUtils::linear); + final Set orangeToYellow = componentRGBGradient(length, NamedTextColor.GOLD, + NamedTextColor.YELLOW, InterpolationUtils::linear); + final Set yellowToGreen = componentRGBGradient(length, NamedTextColor.YELLOW, + NamedTextColor.GREEN, InterpolationUtils::linear); + final Set greenToBlue = componentRGBGradient(length, NamedTextColor.GREEN, + NamedTextColor.BLUE, InterpolationUtils::linear); + final Set blueToPurple = componentRGBGradient(length, NamedTextColor.BLUE, + NamedTextColor.LIGHT_PURPLE, InterpolationUtils::linear); + final Set purpleToRed = componentRGBGradient(length, TextColor.color(75, 0, 130), + TextColor.color(255, 0, 0), InterpolationUtils::linear); + base.addAll(redToOrange); + base.addAll(orangeToYellow); + base.addAll(yellowToGreen); + base.addAll(greenToBlue); + base.addAll(blueToPurple); + base.addAll(purpleToRed); + return base; + } + + public static Set componentRGBGradient(final int length, final TextColor from, final TextColor to, + final Interpolator interpolator) + { + final double[] r = interpolator.interpolate(from.red(), to.red(), length); + final double[] g = interpolator.interpolate(from.green(), to.green(), length); + final double[] b = interpolator.interpolate(from.blue(), to.blue(), length); + + final LinkedHashSet gradient = new LinkedHashSet<>(); + + for (int i = 0; i < length; i++) + { + final TextColor color = TextColor.color((int) r[i], (int) g[i], (int) b[i]); + gradient.add(color); + } + return gradient; + } +} From 9481f88afd686f89cb2e938c45fd4012c2c210f0 Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Fri, 2 Jun 2023 17:07:14 -0500 Subject: [PATCH 04/14] Update --- .../java/me/totalfreedom/datura/Datura.java | 4 +- .../java/me/totalfreedom/fossil/Fossil.java | 17 +- .../totalfreedom/fossil/items/TrailItem.java | 4 +- .../me/totalfreedom/fossil/trail/Trailer.java | 30 +- .../fossil/trail/types/FlameTrail.java | 29 ++ .../fossil/trail/types/HeartTrail.java | 25 ++ .../fossil/trail/types/RainbowTrail.java | 2 +- .../fossil/trail/types/StrobeTrail.java | 30 ++ .../fossil/trail/types/TrailProvider.java | 1 - .../me/totalfreedom/base/CommonsBase.java | 14 +- .../me/totalfreedom/base/Registration.java | 10 +- .../me/totalfreedom/data/ServiceRegistry.java | 75 ----- .../data/ServiceTaskRegistry.java | 316 ++++++++++++++++++ .../totalfreedom/service/FreedomExecutor.java | 46 +-- .../java/me/totalfreedom/service/Service.java | 29 -- .../service/ServiceSubscription.java | 77 +++++ .../service/SubscriptionProvider.java | 45 +++ .../java/me/totalfreedom/service/Task.java | 4 - .../service/TaskSubscription.java | 143 ++++++++ .../utils/InterpolationUtils.java | 96 +++--- 20 files changed, 792 insertions(+), 205 deletions(-) create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/trail/types/HeartTrail.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/trail/types/StrobeTrail.java delete mode 100644 Patchwork/src/main/java/me/totalfreedom/data/ServiceRegistry.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/data/ServiceTaskRegistry.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java diff --git a/Datura/src/main/java/me/totalfreedom/datura/Datura.java b/Datura/src/main/java/me/totalfreedom/datura/Datura.java index 918935a..e41c339 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/Datura.java +++ b/Datura/src/main/java/me/totalfreedom/datura/Datura.java @@ -27,11 +27,11 @@ public class Datura extends JavaPlugin CommonsBase.getInstance() .getRegistrations() .getServiceRegistry() - .register(this, locker); + .registerService(this, locker); CommonsBase.getInstance() .getRegistrations() .getServiceRegistry() - .register(this, cager); + .registerService(this, cager); Bukkit.getPluginManager() .registerEvents(halter, this); diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java b/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java index 3309ef4..a638249 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java @@ -1,16 +1,25 @@ package me.totalfreedom.fossil; import me.totalfreedom.base.CommonsBase; +import me.totalfreedom.base.Registration; +import me.totalfreedom.fossil.trail.Trailer; +import me.totalfreedom.service.SubscriptionProvider; import org.bukkit.plugin.java.JavaPlugin; public class Fossil extends JavaPlugin { + private final Trailer trailer = new Trailer(); + private final Registration registration = CommonsBase.getInstance() + .getRegistrations(); + @Override public void onEnable() { - CommonsBase.getInstance() - .getRegistrations() - .getModuleRegistry() - .addModule(this); + registration.getModuleRegistry() + .addModule(this); + + registration.getServiceRegistry() + .registerService( + SubscriptionProvider.syncService(this, trailer)); } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/items/TrailItem.java b/Fossil/src/main/java/me/totalfreedom/fossil/items/TrailItem.java index a9e6a7d..ea95de6 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/items/TrailItem.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/items/TrailItem.java @@ -8,9 +8,9 @@ import org.jetbrains.annotations.Nullable; public final class TrailItem extends ShopItem { - public TrailItem(final Material material) + public TrailItem() { - super(material); + super(Material.LINGERING_POTION); } @Override diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/Trailer.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/Trailer.java index ae51c0b..b530595 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/Trailer.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/Trailer.java @@ -1,41 +1,37 @@ package me.totalfreedom.fossil.trail; import me.totalfreedom.particle.Trail; -import me.totalfreedom.particle.TrailType; import me.totalfreedom.service.Service; -import org.bukkit.entity.Player; import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.UUID; public class Trailer extends Service { - private final List trailList = new ArrayList<>(); + private final List activeTrails = new ArrayList<>(); - public Trailer() { + // Cannot be async due to interaction with the world, and API interactions MUST be synchronized. + public Trailer() + { super("trailer_service"); } - public void addTrail(final Trail trail) { - this.trailList.add(trail); + public void addTrail(final Trail trail) + { + this.activeTrails.add(trail); } - public void removeTrail(final Trail trail) { - this.trailList.remove(trail); + public void removeTrail(final Trail trail) + { + this.activeTrails.remove(trail); } @Override public void tick() { - for (final Trail trail : trailList) { - if (trail.getAssociatedPlayer().isOnline()) { - final Player player = (Player) trail.getAssociatedPlayer(); - - } + for (final Trail trail : activeTrails) + { + trail.spawnParticle(); } } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java new file mode 100644 index 0000000..fad995d --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java @@ -0,0 +1,29 @@ +package me.totalfreedom.fossil.trail.types; + +import me.totalfreedom.particle.TrailType; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +public final class FlameTrail extends SimpleTrail +{ + public FlameTrail(final Player player) + { + super(player, TrailType.FLAME); + } + + @Override + public void spawnParticle() + { + if (!getAssociatedPlayer().isOnline() || !isActive()) return; + + final Player player = (Player) getAssociatedPlayer(); + final Location location = player.getLocation() + .clone() + .subtract(0, 1, 0); + final Vector direction = location.getDirection(); + location.getWorld() + .spawnParticle(getTrailType().getType(), location, 0, direction.getX(), direction.getY(), + direction.getZ(), 0.1); + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/HeartTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/HeartTrail.java new file mode 100644 index 0000000..b8a83cc --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/HeartTrail.java @@ -0,0 +1,25 @@ +package me.totalfreedom.fossil.trail.types; + +import me.totalfreedom.particle.TrailType; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +public final class HeartTrail extends SimpleTrail +{ + public HeartTrail(final Player player) + { + super(player, TrailType.HEART); + } + + @Override + public void spawnParticle() + { + if (!getAssociatedPlayer().isOnline() || !isActive()) return; + + final Player player = (Player) getAssociatedPlayer(); + final Location location = player.getLocation() + .clone() + .subtract(0, 1, 0); + location.getWorld().spawnParticle(getTrailType().getType(), location, 1, 0.0, 0.5, 0.0); + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/RainbowTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/RainbowTrail.java index 36b9108..b020349 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/RainbowTrail.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/RainbowTrail.java @@ -35,7 +35,7 @@ public final class RainbowTrail extends SimpleTrail final Color color = currentColor.next(); final Player player = (Player) getAssociatedPlayer(); final Particle particle = getTrailType().getType(); - final Particle.DustOptions options = new Particle.DustOptions(color, 3); + final Particle.DustOptions options = new Particle.DustOptions(color, 3F); final Location location = player.getLocation() .clone() .subtract(0, 1, 0); diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/StrobeTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/StrobeTrail.java new file mode 100644 index 0000000..54b167d --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/StrobeTrail.java @@ -0,0 +1,30 @@ +package me.totalfreedom.fossil.trail.types; + +import me.totalfreedom.particle.TrailType; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.entity.Player; + +public final class StrobeTrail extends SimpleTrail +{ + private final Particle.DustTransition dustTransition; + + public StrobeTrail(final Player player, final Color from, final Color to) + { + super(player, TrailType.STROBE); + this.dustTransition = new Particle.DustTransition(from, to, 3F); + } + + @Override + public void spawnParticle() + { + if (!getAssociatedPlayer().isOnline() || !isActive()) return; + + final Player player = (Player) getAssociatedPlayer(); + final Location location = player.getLocation() + .clone() + .subtract(0, 1, 0); + location.getWorld().spawnParticle(getTrailType().getType(), location, 1, 0.0, 0.5, 0.0, dustTransition); + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java index 427bb09..2e7d8d5 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java @@ -8,5 +8,4 @@ public final class TrailProvider return new BasicTrail(player); } - } diff --git a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java index 2d1cb5a..1bc35bf 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java @@ -2,6 +2,8 @@ package me.totalfreedom.base; import me.totalfreedom.event.EventBus; import me.totalfreedom.service.FreedomExecutor; +import me.totalfreedom.service.SubscriptionProvider; +import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; public class CommonsBase extends JavaPlugin @@ -18,21 +20,23 @@ public class CommonsBase extends JavaPlugin @Override public void onDisable() { + Bukkit.getScheduler().runTaskLater(this, () -> getRegistrations() + .getServiceRegistry() + .stopAllServices(), 1L); + getRegistrations().getServiceRegistry() - .stopAll(); - getRegistrations().getServiceRegistry() - .unregister(EventBus.class, eventBus); + .unregisterService(EventBus.class); } @Override public void onEnable() { getRegistrations().getServiceRegistry() - .register(this, eventBus); + .registerService(SubscriptionProvider.asyncService(this, eventBus)); getExecutor().getSync() .execute(() -> getRegistrations() .getServiceRegistry() - .startAll()); + .startAllServices()); } public FreedomExecutor getExecutor() diff --git a/Patchwork/src/main/java/me/totalfreedom/base/Registration.java b/Patchwork/src/main/java/me/totalfreedom/base/Registration.java index 7d8b8cb..e23609a 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/Registration.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/Registration.java @@ -4,14 +4,14 @@ 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.ServiceTaskRegistry; import me.totalfreedom.data.UserRegistry; public class Registration { private final EventRegistry eventRegistry; private final UserRegistry userRegistry; - private final ServiceRegistry serviceRegistry; + private final ServiceTaskRegistry serviceTaskRegistry; private final ModuleRegistry moduleRegistry; private final GroupRegistry groupRegistry; private final ConfigRegistry configRegistry; @@ -20,7 +20,7 @@ public class Registration { this.eventRegistry = new EventRegistry(); this.userRegistry = new UserRegistry(); - this.serviceRegistry = new ServiceRegistry(); + this.serviceTaskRegistry = new ServiceTaskRegistry(); this.moduleRegistry = new ModuleRegistry(); this.groupRegistry = new GroupRegistry(); this.configRegistry = new ConfigRegistry(); @@ -41,9 +41,9 @@ public class Registration return userRegistry; } - public ServiceRegistry getServiceRegistry() + public ServiceTaskRegistry getServiceRegistry() { - return serviceRegistry; + return serviceTaskRegistry; } public GroupRegistry getGroupRegistry() diff --git a/Patchwork/src/main/java/me/totalfreedom/data/ServiceRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/ServiceRegistry.java deleted file mode 100644 index 589db1d..0000000 --- a/Patchwork/src/main/java/me/totalfreedom/data/ServiceRegistry.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.totalfreedom.data; - -import me.totalfreedom.service.Service; -import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.ServicePriority; - -import java.util.ArrayList; -import java.util.List; - -public class ServiceRegistry -{ - private final List services; - - public ServiceRegistry() - { - this.services = new ArrayList<>(); - } - - public void startAll() - { - for (final Service service : this.services) - { - service.start(); - } - } - - public void stopAll() - { - for (final Service service : this.services) - { - service.stop(); - } - } - - @SuppressWarnings("unchecked") - // Suppressing is fine here; we know that the service is of type T extends Service, - // and calling getClass() on this object would effectively be Class, though we may lose - // the identity of the code signature in the process. - // In this case, that is fine. - public void register(final Plugin plugin, final T service) - { - this.services.add(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())); - } - Bukkit.getServicesManager() - .register( - (Class) service.getClass(), - service, - plugin, - ServicePriority.Normal); - } - - public RegisteredServiceProvider getService(final Class clazz) - { - return Bukkit.getServicesManager() - .getRegistration(clazz); - } - - public void unregister(final Class clazz, final Service service) - { - this.services.remove(service); - Bukkit.getServicesManager() - .unregister(clazz, service); - } -} diff --git a/Patchwork/src/main/java/me/totalfreedom/data/ServiceTaskRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/ServiceTaskRegistry.java new file mode 100644 index 0000000..4a1b191 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/data/ServiceTaskRegistry.java @@ -0,0 +1,316 @@ +package me.totalfreedom.data; + +import me.totalfreedom.service.Service; +import me.totalfreedom.service.ServiceSubscription; +import me.totalfreedom.service.SubscriptionProvider; +import me.totalfreedom.service.Task; +import me.totalfreedom.service.TaskSubscription; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * A registry for all services and tasks registered with Patchwork. + *
+ * This class is not thread-safe, and should only be accessed from the main server thread. + *
+ *
+ * Services are tickable tasks which execute every single game tick. They are registered using + * {@link #registerService(ServiceSubscription)} and can be started using {@link #startService(Class)}. + *
+ *
+ * Tasks are runnable tasks which execute at the provided times in the {@link Task} and + * {@link TaskSubscription} classes. These define whether the Task is repeating, delayed, or just a one-time task. + * Tasks are registered using {@link #registerTask(TaskSubscription)} and can be started using + * {@link #startTask(Class)}. + *
+ *
+ * ServiceSubscriptions and TaskSubscriptions can both be easily obtained using the + * {@link SubscriptionProvider} utility class. + * + * @see Service + * @see Task + * @see ServiceSubscription + * @see TaskSubscription + * @see SubscriptionProvider + */ +public class ServiceTaskRegistry +{ + /** + * A list of all services registered with the registry. + */ + private final List> services; + /** + * A list of all tasks registered with the registry. + */ + private final List> tasks; + + /** + * Creates a new instance of the registry and initializes the service and task lists to new empty + * {@link ArrayList}s. + */ + public ServiceTaskRegistry() + { + this.services = new ArrayList<>(); + this.tasks = new ArrayList<>(); + } + + /** + * Starts all services registered with the registry. + *
+ * This method should be avoided, due to the fact that modules may have registered their services + * after this method + * has already been called. In this case, it is preferred to start + * each service using {@link #startService(Class)}. + *
+ * However, Patchwork calls this method when the server is starting up, as Patchwork is the central + * resource + * manager for registered tasks and services. Patchwork will call this method on the first server tick, so unless + * you are registering services AND starting them POST WORLD, you do not need to worry about starting + * your services. + */ + public void startAllServices() + { + for (final ServiceSubscription service : this.services) + { + service.start(); + } + } + + /** + * Starts all tasks registered with the registry. + *
+ * This method should be avoided, due to the fact that modules may have registered their tasks after + * this method + * has already been called. In this case, it is preferred to start + * each task + * using {@link #startTask(Class)}. + *
+ * However, Patchwork calls this method when the server is starting up, as Patchwork is the central + * resource + * manager for registered tasks and services. Patchwork will call this method on the first server tick, so unless + * you are registering tasks AND starting them POST WORLD, you do not need to worry about starting + * your tasks. + */ + public void startAllTasks() + { + for (final TaskSubscription task : this.tasks) + { + task.start(); + } + } + + /** + * Stops all services registered with the registry. + *
+ * This method should be avoided, due to the fact that modules should be handling their own + * registrations. + * It is preferred to use {@link #stopService(Class)} for each service you would like to stop. + *
+ * However, Patchwork calls this method when the server is shutting down, or when Patchwork is being + * disabled, as Patchwork is the central resource manager for registered tasks and services. + * Unless you are modifying service states while the server is running, you do not need to worry about + * disabling or unregistering your services. + */ + public void stopAllServices() + { + for (final ServiceSubscription service : this.services) + { + service.stop(); + } + } + + /** + * Stops all tasks registered with the registry. + *
+ * This method should be avoided, due to the fact that modules should be handling their own + * registrations. + * It is preferred to use {@link #stopTask(Class)} for each task you would like to stop. + *
+ * However, Patchwork calls this method when the server is shutting down, or when Patchwork is being + * disabled, as Patchwork is the central resource manager for registered tasks and services. + * Unless you are modifying task states while the server is running, you do not need to worry about + * disabling or unregistering your tasks. + */ + public void stopAllTasks() + { + for (final TaskSubscription task : this.tasks) + { + task.stop(); + } + } + + /** + * Registers a service with the registry. + *
+ * Services must be registered using ServiceSubscriptions, which can be easily obtained through the + * {@link SubscriptionProvider} utility class. + * + * @param service The service you are trying to register. + * @param A generic type for type inference of the service being registered. + */ + public void registerService(final ServiceSubscription service) + { + this.services.add(service); + } + + /** + * Registers a task with the registry. + *
+ * Tasks must be registered using TaskSubscriptions, which can be easily obtained through the + * {@link SubscriptionProvider} utility class. + * + * @param task The task you are trying to register. + * @param A generic type for type inference of the task being registered. + */ + public void registerTask(final TaskSubscription task) + { + this.tasks.add(task); + } + + /** + * Starts a service using the specified {@link Service} class. + *
+ * The service should already be registered with the registry as a ServiceSubscription. + * + * @param clazz The class of the service you are trying to start. + * @see ServiceSubscription + * @see #registerService(ServiceSubscription) + */ + public void startService(final Class clazz) + { + this.getService(clazz) + .start(); + } + + /** + * Gets a {@link ServiceSubscription} from the registry using the specified class. + *
+ * The class should be the service class you are trying to locate, not the class for the subscription + * itself. + *
+ * The service should have been registered previously as a ServiceSubscription. + * + * @param clazz The class of the service you are trying to locate. + * @param A generic type for type inference of the service requested. + * @return The {@link ServiceSubscription} for the specified class, or null if it could not be found. + * @see #registerService(ServiceSubscription) + * @see ServiceSubscription + */ + @Nullable + public ServiceSubscription getService(final Class clazz) + { + for (final ServiceSubscription service : this.services) + { + if (service.getService() + .getClass() + .equals(clazz)) + { + return (ServiceSubscription) service; + } + } + return null; + } + + /** + * Stops a service using the specified {@link Service} class. + *
+ * The service should already be registered with the registry as a ServiceSubscription. + * + * @param clazz The class of the service you are trying to stop. + * @see #registerService(ServiceSubscription) + * @see ServiceSubscription + */ + public void stopService(final Class clazz) + { + this.getService(clazz) + .stop(); + } + + /** + * Starts a task using the specified {@link Task} class. + *
+ * The task should already be registered with the registry as a TaskSubscription. + * + * @param clazz The class of the task you are trying to start. + * @see #registerTask(TaskSubscription) + * @see TaskSubscription + */ + public void startTask(final Class clazz) + { + this.getTask(clazz) + .start(); + } + + /** + * Gets a {@link TaskSubscription} from the registry using the specified class. + *
+ * The class should be the task class you are trying to locate, not the class for the subscription + * itself. + *
+ * The task should have been registered previously as a TaskSubscription. + * + * @param clazz The class of the task you are trying to locate. + * @param A generic type for type inference of the task requested. + * @return The {@link TaskSubscription} for the specified class, or null if it could not be found. + * @see #registerTask(TaskSubscription) + * @see TaskSubscription + */ + public TaskSubscription getTask(final Class clazz) + { + for (final TaskSubscription task : this.tasks) + { + if (task.getTask() + .getClass() + .equals(clazz)) + { + return (TaskSubscription) task; + } + } + return null; + } + + /** + * Stops a task using the specified {@link Task} class. + *
+ * The task should already be registered with the registry as a TaskSubscription. + * + * @param clazz The class of the task you are trying to stop. + * @see #registerTask(TaskSubscription) + * @see TaskSubscription + */ + public void stopTask(final Class clazz) + { + this.getTask(clazz) + .stop(); + } + + /** + * Unregisters a service from the registry. + *
+ * The service should have been registered previously as a ServiceSubscription. + * + * @param service The service you are trying to unregister. + * @see #registerService(ServiceSubscription) + * @see ServiceSubscription + */ + public void unregisterService(final Class clazz) + { + this.services.remove(getService(clazz)); + } + + /** + * Unregisters a task from the registry. + *
+ * The task should have been registered previously as a TaskSubscription. + * + * @param clazz The task you are trying to unregister. + * @see #registerTask(TaskSubscription) + * @see TaskSubscription + */ + public void unregisterTask(final Class clazz) + { + this.tasks.remove(getTask(clazz)); + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java index 6c6542d..dcaff95 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java @@ -2,7 +2,7 @@ package me.totalfreedom.service; import me.totalfreedom.base.CommonsBase; import org.bukkit.Bukkit; -import org.jetbrains.annotations.NotNull; +import org.bukkit.plugin.java.JavaPlugin; import java.util.concurrent.Executor; @@ -19,29 +19,40 @@ public class FreedomExecutor .runTaskAsynchronously(CommonsBase.getInstance(), r); } - public Executor scheduled(final long delay, final long period) + public Executor singleExecutor(final JavaPlugin plugin) { return r -> Bukkit.getScheduler() - .runTaskTimer( - CommonsBase.getInstance(), - r, - delay, - period); + .runTask(plugin, r); } - public Executor scheduledAsync(final long delay, final long period) + public Executor delayedExecutor(final JavaPlugin plugin, final long delay) { return r -> Bukkit.getScheduler() - .runTaskTimerAsynchronously( - CommonsBase.getInstance(), - r, - delay, - period); + .runTaskLater(plugin, r, delay); } - public void runSync(@NotNull final Task task) + public Executor periodicExecutor(final JavaPlugin plugin, final long delay, final long period) { - getSync().execute(task); + return r -> Bukkit.getScheduler() + .runTaskTimer(plugin, r, delay, period); + } + + public Executor asynchronousSingleExecutor(final JavaPlugin plugin) + { + return r -> Bukkit.getScheduler() + .runTaskAsynchronously(plugin, r); + } + + public Executor asynchronousDelayedExecutor(final JavaPlugin plugin, final long delay) + { + return r -> Bukkit.getScheduler() + .runTaskLaterAsynchronously(plugin, r, delay); + } + + public Executor asynchronousPeriodicExecutor(final JavaPlugin plugin, final long delay, final long period) + { + return r -> Bukkit.getScheduler() + .runTaskTimerAsynchronously(plugin, r, delay, period); } public Executor getSync() @@ -49,11 +60,6 @@ public class FreedomExecutor 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 df33c00..592eb9c 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/Service.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/Service.java @@ -1,47 +1,18 @@ package me.totalfreedom.service; -import me.totalfreedom.base.CommonsBase; - public abstract class Service { private final String name; - private boolean isActive = false; protected Service(final String name) { this.name = name; - - } - - public void start() - { - isActive = true; - CommonsBase.getInstance() - .getExecutor() - .getSync() - .execute(() -> - { - while (isActive) - { - tick(); - } - }); } public abstract void tick(); - public void stop() - { - isActive = false; - } - public String getName() { return name; } - - public boolean isActive() - { - return isActive; - } } diff --git a/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java new file mode 100644 index 0000000..8cc99cf --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java @@ -0,0 +1,77 @@ +package me.totalfreedom.service; + +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; + +import java.util.concurrent.Executor; + +public final class ServiceSubscription +{ + private final T service; + private final boolean async; + private final Executor executor; + private final int serviceId; + + private boolean isActive = false; + + ServiceSubscription(final JavaPlugin plugin, final T service, final boolean async) + { + this.service = service; + this.async = async; + + final int[] tempId = new int[1]; + + if (async) + { + this.executor = r -> + { + final BukkitTask task = Bukkit.getScheduler() + .runTaskTimerAsynchronously(plugin, r, 0, 1); + tempId[0] = task.getTaskId(); + }; + } else + { + this.executor = r -> + { + final BukkitTask task = Bukkit.getScheduler() + .runTaskTimer(plugin, r, 0, 1); + tempId[0] = task.getTaskId(); + }; + } + + this.serviceId = tempId[0]; + } + + public void start() + { + this.isActive = true; + this.executor.execute(service::tick); + } + + public void stop() + { + this.isActive = false; + Bukkit.getScheduler().cancelTask(this.getServiceId()); + } + + public T getService() + { + return service; + } + + public int getServiceId() + { + return serviceId; + } + + public boolean isAsync() + { + return async; + } + + public boolean isActive() + { + return isActive; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java b/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java new file mode 100644 index 0000000..a1478c0 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java @@ -0,0 +1,45 @@ +package me.totalfreedom.service; + +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public final class SubscriptionProvider +{ + private SubscriptionProvider() + { + throw new AssertionError(); + } + + @NotNull + @Contract(value = "_, _ -> new", pure = false) + public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin, + @NotNull final S service) + { + return new ServiceSubscription<>(plugin, service, false); + } + + @NotNull + @Contract(value = "_, _ -> new", pure = false) + public static final ServiceSubscription asyncService(@NotNull final JavaPlugin plugin, + @NotNull final S service) + { + return new ServiceSubscription<>(plugin, service, true); + } + + @NotNull + @Contract(value = "_, _ -> new", pure = false) + public static final TaskSubscription runSyncTask(@NotNull final JavaPlugin plugin, + @NotNull final T task) + { + return new TaskSubscription<>(plugin, task, false); + } + + @NotNull + @Contract(value = "_, _ -> new", pure = false) + public static final TaskSubscription runAsyncTask(@NotNull final JavaPlugin plugin, + @NotNull final T task) + { + return new TaskSubscription<>(plugin, task, true); + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/service/Task.java b/Patchwork/src/main/java/me/totalfreedom/service/Task.java index 941ae6f..b072b26 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/Task.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/Task.java @@ -2,10 +2,6 @@ package me.totalfreedom.service; public interface Task extends Runnable { - void start(); - - void stop(); - boolean isRunning(); String getName(); diff --git a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java new file mode 100644 index 0000000..e8e4b8e --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java @@ -0,0 +1,143 @@ +package me.totalfreedom.service; + +import me.totalfreedom.utils.Pair; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; + +import java.util.concurrent.Executor; + +public final class TaskSubscription +{ + private final T task; + private final int taskId; + private final boolean async; + private final Executor executor; + + private boolean isActive = false; + + TaskSubscription(final JavaPlugin plugin, final T task, final boolean async) + { + this.task = task; + this.async = async; + + final long delay = (task.isDelayed() + ? task.getDelay() + : 0); + final long period = (task.isRepeating() + ? task.getInterval() + : 0); + + final Pair integerExecutorPair = async + ? getAsync(plugin, delay, period) + : getSync(plugin, delay, period); + + this.executor = integerExecutorPair.value(); + this.taskId = integerExecutorPair.key(); + } + + private Pair getAsync(final JavaPlugin plugin, final long delay, final long period) + { + final Executor executor1; + final int[] tempId = new int[1]; + if (period != 0) + { + executor1 = r -> + { + final BukkitTask task1 = Bukkit.getScheduler() + .runTaskTimerAsynchronously(plugin, r, delay, period); + tempId[0] = task1.getTaskId(); + }; + } else if (delay != 0) + { + executor1 = r -> + { + final BukkitTask task1 = Bukkit.getScheduler() + .runTaskLaterAsynchronously(plugin, r, delay); + tempId[0] = task1.getTaskId(); + }; + } else + { + executor1 = r -> + { + final BukkitTask task1 = Bukkit.getScheduler() + .runTaskAsynchronously(plugin, r); + tempId[0] = task1.getTaskId(); + }; + } + + return new Pair<>(tempId[0], executor1); + } + + private Pair getSync(final JavaPlugin plugin, final long delay, final long period) + { + final Executor executor1; + final int[] tempId = new int[1]; + + if (period != 0) + { + executor1 = r -> + { + final BukkitTask task1 = Bukkit.getScheduler() + .runTaskTimer(plugin, r, delay, period); + tempId[0] = task1.getTaskId(); + }; + } else if (delay != 0) + { + executor1 = r -> + { + final BukkitTask task1 = Bukkit.getScheduler() + .runTaskLater(plugin, r, delay); + tempId[0] = task1.getTaskId(); + }; + } else + { + executor1 = r -> + { + final BukkitTask task1 = Bukkit.getScheduler() + .runTask(plugin, r); + tempId[0] = task1.getTaskId(); + }; + } + + return new Pair<>(tempId[0], executor1); + } + + public void start() + { + this.isActive = true; + executor.execute(task); + } + + public void stop() + { + this.isActive = false; + Bukkit.getScheduler() + .cancelTask(this.getTaskId()); + } + + public int getTaskId() + { + return taskId; + } + + public T getTask() + { + return task; + } + + public boolean isAsync() + { + return async; + } + + public Executor getExecutor() + { + return executor; + } + + public boolean isActive() + { + return isActive; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java b/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java index 587f05d..9f839ed 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java @@ -8,8 +8,13 @@ import org.bukkit.Color; import java.util.LinkedHashSet; import java.util.Set; -public class InterpolationUtils +public final class InterpolationUtils { + private InterpolationUtils() + { + throw new AssertionError(); + } + public static Set rainbow(final int length) { final LinkedHashSet base = new LinkedHashSet<>(); @@ -60,7 +65,54 @@ public class InterpolationUtils return res; } - public static Set rgbGradient(final int length, final Color from, final Color to, + public static Set rainbowComponent(final int length) + { + final LinkedHashSet base = new LinkedHashSet<>(); + final Set redToOrange = componentRGBGradient(length, NamedTextColor.RED, + NamedTextColor.GOLD, InterpolationUtils::linear); + final Set orangeToYellow = componentRGBGradient(length, NamedTextColor.GOLD, + NamedTextColor.YELLOW, InterpolationUtils::linear); + final Set yellowToGreen = componentRGBGradient(length, NamedTextColor.YELLOW, + NamedTextColor.GREEN, InterpolationUtils::linear); + final Set greenToBlue = componentRGBGradient(length, NamedTextColor.GREEN, + NamedTextColor.BLUE, InterpolationUtils::linear); + final Set blueToPurple = componentRGBGradient(length, NamedTextColor.BLUE, + NamedTextColor.LIGHT_PURPLE, + InterpolationUtils::linear); + final Set purpleToRed = componentRGBGradient(length, TextColor.color(75, 0, 130), + TextColor.color(255, 0, 0), InterpolationUtils::linear); + base.addAll(redToOrange); + base.addAll(orangeToYellow); + base.addAll(yellowToGreen); + base.addAll(greenToBlue); + base.addAll(blueToPurple); + base.addAll(purpleToRed); + return base; + } + + private static Set componentRGBGradient(final int length, final TextColor from, final TextColor to, + final Interpolator interpolator) + { + final double[] r = interpolator.interpolate(from.red(), to.red(), length); + final double[] g = interpolator.interpolate(from.green(), to.green(), length); + final double[] b = interpolator.interpolate(from.blue(), to.blue(), length); + + final LinkedHashSet gradient = new LinkedHashSet<>(); + + for (int i = 0; i < length; i++) + { + final TextColor color = TextColor.color((int) r[i], (int) g[i], (int) b[i]); + gradient.add(color); + } + return gradient; + } + + public static Set standardGradient(final int length, final Color from, final Color to) + { + return rgbGradient(length, from, to, InterpolationUtils::linear); + } + + private static Set rgbGradient(final int length, final Color from, final Color to, final Interpolator interpolator) { final double[] r = interpolator.interpolate(from.getRed(), to.getRed(), length); @@ -77,44 +129,8 @@ public class InterpolationUtils return gradient; } - public static Set rainbowComponent(final int length) + public static Set standardComponentGradient(final int length, final TextColor from, final TextColor to) { - final LinkedHashSet base = new LinkedHashSet<>(); - final Set redToOrange = componentRGBGradient(length, NamedTextColor.RED, - NamedTextColor.GOLD, InterpolationUtils::linear); - final Set orangeToYellow = componentRGBGradient(length, NamedTextColor.GOLD, - NamedTextColor.YELLOW, InterpolationUtils::linear); - final Set yellowToGreen = componentRGBGradient(length, NamedTextColor.YELLOW, - NamedTextColor.GREEN, InterpolationUtils::linear); - final Set greenToBlue = componentRGBGradient(length, NamedTextColor.GREEN, - NamedTextColor.BLUE, InterpolationUtils::linear); - final Set blueToPurple = componentRGBGradient(length, NamedTextColor.BLUE, - NamedTextColor.LIGHT_PURPLE, InterpolationUtils::linear); - final Set purpleToRed = componentRGBGradient(length, TextColor.color(75, 0, 130), - TextColor.color(255, 0, 0), InterpolationUtils::linear); - base.addAll(redToOrange); - base.addAll(orangeToYellow); - base.addAll(yellowToGreen); - base.addAll(greenToBlue); - base.addAll(blueToPurple); - base.addAll(purpleToRed); - return base; - } - - public static Set componentRGBGradient(final int length, final TextColor from, final TextColor to, - final Interpolator interpolator) - { - final double[] r = interpolator.interpolate(from.red(), to.red(), length); - final double[] g = interpolator.interpolate(from.green(), to.green(), length); - final double[] b = interpolator.interpolate(from.blue(), to.blue(), length); - - final LinkedHashSet gradient = new LinkedHashSet<>(); - - for (int i = 0; i < length; i++) - { - final TextColor color = TextColor.color((int) r[i], (int) g[i], (int) b[i]); - gradient.add(color); - } - return gradient; + return componentRGBGradient(length, from, to, InterpolationUtils::linear); } } From 9618e5bcec0545d0b9654fee9190abfb259a4e1c Mon Sep 17 00:00:00 2001 From: Video Date: Fri, 2 Jun 2023 16:28:34 -0600 Subject: [PATCH 05/14] Fixes commands, adds /cage command --- .../java/me/totalfreedom/datura/Datura.java | 5 +- .../totalfreedom/datura/cmd/CageCommand.java | 84 +++++++++++++++++++ .../datura/cmd/LockerCommand.java | 3 +- .../totalfreedom/datura/punishment/Cager.java | 2 +- .../totalfreedom/fossil/cmd/CakeCommand.java | 9 +- 5 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java diff --git a/Datura/src/main/java/me/totalfreedom/datura/Datura.java b/Datura/src/main/java/me/totalfreedom/datura/Datura.java index e41c339..5ef1440 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/Datura.java +++ b/Datura/src/main/java/me/totalfreedom/datura/Datura.java @@ -5,6 +5,7 @@ import me.totalfreedom.datura.punishment.Cager; import me.totalfreedom.datura.punishment.Halter; import me.totalfreedom.datura.punishment.Locker; import me.totalfreedom.datura.sql.MySQL; +import me.totalfreedom.service.SubscriptionProvider; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; @@ -27,11 +28,11 @@ public class Datura extends JavaPlugin CommonsBase.getInstance() .getRegistrations() .getServiceRegistry() - .registerService(this, locker); + .registerService(SubscriptionProvider.syncService(this, locker)); CommonsBase.getInstance() .getRegistrations() .getServiceRegistry() - .registerService(this, cager); + .registerService(SubscriptionProvider.syncService(this, cager)); Bukkit.getPluginManager() .registerEvents(halter, this); diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java new file mode 100644 index 0000000..444ee23 --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 TotalFreedom + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this + * software and associated documentation files (the “Software”), to deal in the Software + * without restriction, including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package 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.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; + +@Info(name = "cage", description = "Cage a player.", + usage = "/cage [material]") +@Permissive(perm = "datura.cage") +public class CageCommand extends Commander +{ + protected CageCommand(final @NotNull JavaPlugin plugin) + { + super(plugin); + } + + @Completion(args = {"%player%"}, index = 0) + @Completion(args = {"on", "off"}, index = 1) + @Subcommand(permission = "datura.cage", args = {Player.class, String.class}) + public void cagePlayer(final CommandSender sender, final Player player, final String string) + { + switch (string.toLowerCase()) + { + case "on" -> + { + ((Datura) getPlugin()).getCager().cagePlayer(player.getUniqueId()); + sender.sendPlainMessage("Caged " + player.getName() + "."); + } + case "off" -> + { + ((Datura) getPlugin()).getCager().uncagePlayer(player.getUniqueId()); + sender.sendPlainMessage("Liberated " + player.getName() + "."); + } + } + } + + @Completion(args = {"[material]"}, index = 2) + @Subcommand(permission = "datura.cage.custom", args = {Player.class, String.class, Material.class}) + public void cagePlayer(final CommandSender sender, final Player player, final String string, final Material material) + { + switch (string.toLowerCase()) + { + case "on" -> + { + ((Datura) getPlugin()).getCager().cagePlayer(player.getUniqueId(), material); + sender.sendPlainMessage("Caged " + player.getName() + "."); + } + case "off" -> + { + ((Datura) getPlugin()).getCager().uncagePlayer(player.getUniqueId()); + sender.sendPlainMessage("Liberated " + player.getName() + "."); + } + } + } +} diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java index f346e83..f1d7a99 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java @@ -31,7 +31,8 @@ public final class LockerCommand extends Commander .lock(player); sender.sendPlainMessage("Locked " + player.getName() + "."); - } else if (string.equalsIgnoreCase("off")) + } + else if (string.equalsIgnoreCase("off")) { ((Datura) getPlugin()).getLocker() .unlock(player); 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 ec584f1..5c767e8 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java +++ b/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java @@ -28,7 +28,7 @@ public class Cager extends Service public Cager() { - super("cage_service"); + super("cager-service"); this.cagedPlayers = new HashSet<>(); this.cageLocations = new HashMap<>(); Bukkit.getPluginManager() diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java b/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java index 7a6c437..c4e5bd7 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java @@ -21,7 +21,7 @@ package me.totalfreedom.fossil.cmd; -import me.totalfreedom.command.CommandBase; +import me.totalfreedom.command.Commander; import me.totalfreedom.command.annotation.Base; import me.totalfreedom.command.annotation.Info; import me.totalfreedom.command.annotation.Permissive; @@ -32,18 +32,19 @@ import org.bukkit.command.CommandSender; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; @Info(name = "cake", description = "Gives everyone cake and broadcasts a message.", usage = "/cake") @Permissive(perm = "fossil.cake") -public class CakeCommand extends CommandBase +public class CakeCommand extends Commander { - protected CakeCommand(JavaPlugin plugin) + protected CakeCommand(final @NotNull JavaPlugin plugin) { super(plugin); } @Base - public void cake(final CommandSender sender) + public void broadcastCake(final CommandSender sender) { Bukkit.broadcast(FreedomMiniMessage.deserialize(true, "But there's no sense crying over every mistake. You just keep on trying till you run out of cake.")); From ccb456ea0cdde942c97bb01cc00f29628871dbcf Mon Sep 17 00:00:00 2001 From: Video Date: Fri, 2 Jun 2023 16:57:26 -0600 Subject: [PATCH 06/14] Removes old unused UserData methods --- .../datura/user/SimpleUserData.java | 18 +----------------- .../java/me/totalfreedom/user/UserData.java | 4 ---- 2 files changed, 1 insertion(+), 21 deletions(-) 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 be92bd7..ab8446e 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java @@ -51,7 +51,6 @@ public class SimpleUserData implements UserData final long playtime, final boolean frozen, final boolean canInteract, - final boolean caged, final long balance, final boolean transactionsFrozen) { @@ -62,7 +61,6 @@ public class SimpleUserData implements UserData this.playtime = playtime; this.frozen = frozen; this.canInteract = canInteract; - this.caged = caged; this.balance = new AtomicLong(balance); this.transactionsFrozen = transactionsFrozen; } @@ -101,8 +99,7 @@ public class SimpleUserData implements UserData final boolean transactionsFrozen = result.getBoolean( "transactionsFrozen"); return new SimpleUserData(u, username, user, group, playtime, frozen, - canInteract, caged, balance, - transactionsFrozen); + canInteract, balance, transactionsFrozen); } } catch (SQLException ex) @@ -214,19 +211,6 @@ public class SimpleUserData implements UserData this.canInteract = canInteract; } - @Override - public boolean isCaged() - { - return caged; - } - - @Override - public void setCaged(final boolean caged) - { - event.ping(); - this.caged = caged; - } - @Override public boolean areTransactionsFrozen() { diff --git a/Patchwork/src/main/java/me/totalfreedom/user/UserData.java b/Patchwork/src/main/java/me/totalfreedom/user/UserData.java index 1ceb5ed..e482750 100644 --- a/Patchwork/src/main/java/me/totalfreedom/user/UserData.java +++ b/Patchwork/src/main/java/me/totalfreedom/user/UserData.java @@ -34,8 +34,4 @@ public interface UserData extends EconomicEntityData boolean canInteract(); void setInteractionState(boolean canInteract); - - boolean isCaged(); - - void setCaged(boolean caged); } From e160868967fab4f80811b0054ecf3e5d1871e16f Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Fri, 2 Jun 2023 17:58:08 -0500 Subject: [PATCH 07/14] Reformatting --- .../totalfreedom/datura/cmd/CageCommand.java | 17 +- .../datura/cmd/LockerCommand.java | 3 +- .../datura/perms/PermissionNode.java | 6 +- .../me/totalfreedom/datura/sql/MySQL.java | 180 +++++++++--------- .../datura/user/SimpleUserData.java | 98 +++++----- .../totalfreedom/fossil/cmd/CakeCommand.java | 8 +- .../economy/SimpleTransactionResult.java | 2 +- .../fossil/items/ClownfishItem.java | 6 +- .../fossil/trail/types/BasicTrail.java | 3 +- .../fossil/trail/types/FlameTrail.java | 2 +- .../fossil/trail/types/HeartTrail.java | 3 +- .../fossil/trail/types/SimpleTrail.java | 3 +- .../fossil/trail/types/StrobeTrail.java | 3 +- .../fossil/trail/types/TrailProvider.java | 3 +- .../me/totalfreedom/base/CommonsBase.java | 7 +- .../me/totalfreedom/config/Configuration.java | 4 - .../me/totalfreedom/config/YamlWrapper.java | 6 + .../me/totalfreedom/display/AbstractMenu.java | 14 +- .../me/totalfreedom/display/Displayable.java | 6 +- .../totalfreedom/event/SubscriptionBox.java | 16 +- .../java/me/totalfreedom/particle/Trail.java | 2 - .../provider/ContextProvider.java | 7 + .../service/ServiceSubscription.java | 17 +- .../me/totalfreedom/sql/SQLProperties.java | 20 +- .../me/totalfreedom/utils/FreedomLogger.java | 16 +- .../utils/FreedomMiniMessage.java | 58 +++--- .../utils/InterpolationUtils.java | 14 +- 27 files changed, 280 insertions(+), 244 deletions(-) create mode 100644 Patchwork/src/main/java/me/totalfreedom/config/YamlWrapper.java diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java index 444ee23..e8ad5c1 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java @@ -34,7 +34,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @Info(name = "cage", description = "Cage a player.", - usage = "/cage [material]") + usage = "/cage [material]") @Permissive(perm = "datura.cage") public class CageCommand extends Commander { @@ -52,12 +52,14 @@ public class CageCommand extends Commander { case "on" -> { - ((Datura) getPlugin()).getCager().cagePlayer(player.getUniqueId()); + ((Datura) getPlugin()).getCager() + .cagePlayer(player.getUniqueId()); sender.sendPlainMessage("Caged " + player.getName() + "."); } case "off" -> { - ((Datura) getPlugin()).getCager().uncagePlayer(player.getUniqueId()); + ((Datura) getPlugin()).getCager() + .uncagePlayer(player.getUniqueId()); sender.sendPlainMessage("Liberated " + player.getName() + "."); } } @@ -65,18 +67,21 @@ public class CageCommand extends Commander @Completion(args = {"[material]"}, index = 2) @Subcommand(permission = "datura.cage.custom", args = {Player.class, String.class, Material.class}) - public void cagePlayer(final CommandSender sender, final Player player, final String string, final Material material) + public void cagePlayer(final CommandSender sender, final Player player, final String string, + final Material material) { switch (string.toLowerCase()) { case "on" -> { - ((Datura) getPlugin()).getCager().cagePlayer(player.getUniqueId(), material); + ((Datura) getPlugin()).getCager() + .cagePlayer(player.getUniqueId(), material); sender.sendPlainMessage("Caged " + player.getName() + "."); } case "off" -> { - ((Datura) getPlugin()).getCager().uncagePlayer(player.getUniqueId()); + ((Datura) getPlugin()).getCager() + .uncagePlayer(player.getUniqueId()); sender.sendPlainMessage("Liberated " + player.getName() + "."); } } diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java index f1d7a99..f346e83 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java @@ -31,8 +31,7 @@ public final class LockerCommand extends Commander .lock(player); sender.sendPlainMessage("Locked " + player.getName() + "."); - } - else if (string.equalsIgnoreCase("off")) + } else if (string.equalsIgnoreCase("off")) { ((Datura) getPlugin()).getLocker() .unlock(player); 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 7353c19..22fd39b 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java @@ -16,9 +16,9 @@ record PermissionNode(String key, public Permission bukkit() { return new Permission(key(), - value() - ? PermissionDefault.TRUE - : PermissionDefault.FALSE); + value() + ? PermissionDefault.TRUE + : PermissionDefault.FALSE); } @Override 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 9662cfb..5827a8e 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java +++ b/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java @@ -62,42 +62,42 @@ public class MySQL implements SQL { 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()); + { + 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()); + { + 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 @@ -105,20 +105,20 @@ public class MySQL implements SQL { 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()); + { + 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 @@ -126,19 +126,19 @@ public class MySQL implements SQL { 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()); + { + try + { + return statement.executeUpdate(); + } + catch (SQLException ex) + { + throw new CompletionException("Failed to execute update: " + + query + "\n", ex); + } + }, CommonsBase.getInstance() + .getExecutor() + .getAsync()); } @Override @@ -146,19 +146,19 @@ public class MySQL implements SQL { 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()); + { + try + { + return statement.execute(); + } + catch (SQLException ex) + { + throw new CompletionException("Failed to execute statement: " + + query + "\n", ex); + } + }, CommonsBase.getInstance() + .getExecutor() + .getAsync()); } @Override @@ -185,25 +185,25 @@ public class MySQL implements SQL { 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()); + { + 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, 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 be92bd7..512792f 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java @@ -71,62 +71,62 @@ public class SimpleUserData implements UserData { return sql.executeQuery("SELECT * FROM users WHERE UUID = ?", uuid) .thenApplyAsync(result -> - { - try - { - if (result.next()) - { - final String g = result.getString("group"); + { + 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()) + 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(); } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java b/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java index c4e5bd7..6c7c364 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java @@ -46,13 +46,17 @@ public class CakeCommand extends Commander @Base public void broadcastCake(final CommandSender sender) { - Bukkit.broadcast(FreedomMiniMessage.deserialize(true, "But there's no sense crying over every mistake. You just keep on trying till you run out of cake.")); + Bukkit.broadcast(FreedomMiniMessage.deserialize(true, + "But there's no sense crying over every mistake. You just keep on trying till you run out of " + + "cake.")); final ItemStack stack = new ItemStack(Material.CAKE, 1); final ItemMeta meta = stack.getItemMeta(); meta.displayName(FreedomMiniMessage.deserialize(true, "The Lie")); stack.setItemMeta(meta); - Bukkit.getOnlinePlayers().forEach(player -> player.getInventory().addItem(stack)); + Bukkit.getOnlinePlayers() + .forEach(player -> player.getInventory() + .addItem(stack)); } } 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 381936c..eeb629c 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionResult.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionResult.java @@ -8,7 +8,7 @@ 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); + false); public static final TransactionResult AMOUNT_TOO_SMALL = new SimpleTransactionResult( "Transaction balance too small.", false); public static final TransactionResult INSUFFICIENT_FUNDS = new SimpleTransactionResult( diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/items/ClownfishItem.java b/Fossil/src/main/java/me/totalfreedom/fossil/items/ClownfishItem.java index 834d8c1..0bf1131 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/items/ClownfishItem.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/items/ClownfishItem.java @@ -20,8 +20,10 @@ public final class ClownfishItem extends ShopItem { if (target == null) return; - final Location location = user.getEyeLocation().clone(); - final Vector vector = location.getDirection().multiply(2); + final Location location = user.getEyeLocation() + .clone(); + final Vector vector = location.getDirection() + .multiply(2); target.setVelocity(vector); } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/BasicTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/BasicTrail.java index 94fbb46..6d6ee9b 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/BasicTrail.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/BasicTrail.java @@ -27,6 +27,7 @@ public final class BasicTrail extends SimpleTrail final Location location = player.getLocation() .clone() .subtract(0, 1, 0); - location.getWorld().spawnParticle(particle, location, 1, 0.0, 0.5, 0.0, options); + location.getWorld() + .spawnParticle(particle, location, 1, 0.0, 0.5, 0.0, options); } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java index fad995d..d8e7ba9 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java @@ -24,6 +24,6 @@ public final class FlameTrail extends SimpleTrail final Vector direction = location.getDirection(); location.getWorld() .spawnParticle(getTrailType().getType(), location, 0, direction.getX(), direction.getY(), - direction.getZ(), 0.1); + direction.getZ(), 0.1); } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/HeartTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/HeartTrail.java index b8a83cc..968a6ef 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/HeartTrail.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/HeartTrail.java @@ -20,6 +20,7 @@ public final class HeartTrail extends SimpleTrail final Location location = player.getLocation() .clone() .subtract(0, 1, 0); - location.getWorld().spawnParticle(getTrailType().getType(), location, 1, 0.0, 0.5, 0.0); + location.getWorld() + .spawnParticle(getTrailType().getType(), location, 1, 0.0, 0.5, 0.0); } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/SimpleTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/SimpleTrail.java index c217c64..6988ba5 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/SimpleTrail.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/SimpleTrail.java @@ -21,7 +21,8 @@ public abstract class SimpleTrail implements Trail private Set gradientColor = null; private boolean active = false; - protected SimpleTrail(final Player player, final TrailType trailType) { + protected SimpleTrail(final Player player, final TrailType trailType) + { this.associatedPlayerUUID = player.getUniqueId(); this.trailType = trailType; } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/StrobeTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/StrobeTrail.java index 54b167d..1e444c5 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/StrobeTrail.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/StrobeTrail.java @@ -25,6 +25,7 @@ public final class StrobeTrail extends SimpleTrail final Location location = player.getLocation() .clone() .subtract(0, 1, 0); - location.getWorld().spawnParticle(getTrailType().getType(), location, 1, 0.0, 0.5, 0.0, dustTransition); + location.getWorld() + .spawnParticle(getTrailType().getType(), location, 1, 0.0, 0.5, 0.0, dustTransition); } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java index 2e7d8d5..1110266 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/TrailProvider.java @@ -4,7 +4,8 @@ import org.bukkit.entity.Player; public final class TrailProvider { - public BasicTrail basicTrail(final Player player) { + public BasicTrail basicTrail(final Player player) + { return new BasicTrail(player); } diff --git a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java index 1bc35bf..b75d402 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java @@ -20,9 +20,10 @@ public class CommonsBase extends JavaPlugin @Override public void onDisable() { - Bukkit.getScheduler().runTaskLater(this, () -> getRegistrations() - .getServiceRegistry() - .stopAllServices(), 1L); + Bukkit.getScheduler() + .runTaskLater(this, () -> getRegistrations() + .getServiceRegistry() + .stopAllServices(), 1L); getRegistrations().getServiceRegistry() .unregisterService(EventBus.class); diff --git a/Patchwork/src/main/java/me/totalfreedom/config/Configuration.java b/Patchwork/src/main/java/me/totalfreedom/config/Configuration.java index 41e9674..6b551c1 100644 --- a/Patchwork/src/main/java/me/totalfreedom/config/Configuration.java +++ b/Patchwork/src/main/java/me/totalfreedom/config/Configuration.java @@ -1,15 +1,11 @@ package me.totalfreedom.config; -import org.bukkit.configuration.file.YamlConfiguration; - import java.io.File; import java.io.IOException; import java.util.List; public interface Configuration { - YamlConfiguration asYaml(); - void save() throws IOException; void load() throws IOException; diff --git a/Patchwork/src/main/java/me/totalfreedom/config/YamlWrapper.java b/Patchwork/src/main/java/me/totalfreedom/config/YamlWrapper.java new file mode 100644 index 0000000..eefd27c --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/config/YamlWrapper.java @@ -0,0 +1,6 @@ +package me.totalfreedom.config; + +public final class YamlWrapper +{ + +} diff --git a/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java b/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java index d39e5dc..697f7eb 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java @@ -76,13 +76,13 @@ public abstract class AbstractMenu { Bukkit.getOnlinePlayers() .forEach(player -> - { - if (openInvs.get(player.getUniqueId()) - .equals(getDisplayableUUID())) - { - close(player); - } - }); + { + if (openInvs.get(player.getUniqueId()) + .equals(getDisplayableUUID())) + { + close(player); + } + }); invByUUID.remove(getDisplayableUUID()); } diff --git a/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java b/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java index 2ae19e8..c550877 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java @@ -30,7 +30,9 @@ public final class Displayable implements Inventory, InventoryHolder // 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.size = (size % 9 == 0) + ? size + : size + (9 - size % 9); this.contents = new ItemStack[size]; } @@ -152,7 +154,7 @@ public final class Displayable implements Inventory, InventoryHolder if (remainingAmount < item.getAmount()) { removedItems.put(removedItems.size(), - new ItemStack(item.getType(), item.getAmount() - remainingAmount)); + new ItemStack(item.getType(), item.getAmount() - remainingAmount)); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java b/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java index 6feb564..c93a230 100644 --- a/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java +++ b/Patchwork/src/main/java/me/totalfreedom/event/SubscriptionBox.java @@ -25,14 +25,14 @@ class SubscriptionBox public void tick() { subscriptions.forEach(s -> - { - if (!s.event() - .shouldCall()) return; + { + 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 2581463..dc3c517 100644 --- a/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java +++ b/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java @@ -3,10 +3,8 @@ package me.totalfreedom.particle; import me.totalfreedom.api.Interpolator; import me.totalfreedom.utils.InterpolationUtils; import org.bukkit.Color; -import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.Particle; -import org.bukkit.World; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java index 189fe37..aa61ac0 100644 --- a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java +++ b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java @@ -3,6 +3,7 @@ package me.totalfreedom.provider; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -21,6 +22,7 @@ public class ContextProvider toInt(string), toLong(string), toFloat(string), + toMaterial(string), toPlayer(string), toWorld(string), toLocation(string), @@ -92,6 +94,11 @@ public class ContextProvider } } + private @Nullable Material toMaterial(final String string) + { + return Material.matchMaterial(string); + } + private @Nullable Player toPlayer(final String string) { return Bukkit.getPlayer(string); diff --git a/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java index 8cc99cf..f6c4a83 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java @@ -3,6 +3,7 @@ package me.totalfreedom.service; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import java.util.concurrent.Executor; @@ -15,7 +16,7 @@ public final class ServiceSubscription private boolean isActive = false; - ServiceSubscription(final JavaPlugin plugin, final T service, final boolean async) + ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final boolean async) { this.service = service; this.async = async; @@ -52,12 +53,8 @@ public final class ServiceSubscription public void stop() { this.isActive = false; - Bukkit.getScheduler().cancelTask(this.getServiceId()); - } - - public T getService() - { - return service; + Bukkit.getScheduler() + .cancelTask(this.getServiceId()); } public int getServiceId() @@ -65,6 +62,12 @@ public final class ServiceSubscription return serviceId; } + @NotNull + public T getService() + { + return service; + } + public boolean isAsync() { return async; diff --git a/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java b/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java index 2a3a448..2127b1d 100644 --- a/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java +++ b/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java @@ -22,10 +22,10 @@ public interface SQLProperties default String toURLPlain() { return String.format("jdbc:%s://%s:%s/%s", - this.getDriver(), - this.getHost(), - this.getPort(), - this.getDatabase()); + this.getDriver(), + this.getHost(), + this.getPort(), + this.getDatabase()); } String getDriver(); @@ -39,12 +39,12 @@ public interface SQLProperties 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(); diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java b/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java index 0f2345e..9fd27ad 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java @@ -56,14 +56,6 @@ 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); } /** @@ -78,6 +70,14 @@ public class FreedomLogger implements Audience logger.info(plainText); return plainText; + } /** + * 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); } /** diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomMiniMessage.java b/Patchwork/src/main/java/me/totalfreedom/utils/FreedomMiniMessage.java index e615906..a3c1e34 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomMiniMessage.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/FreedomMiniMessage.java @@ -32,46 +32,54 @@ import net.kyori.adventure.text.minimessage.tag.standard.StandardTags; */ public class FreedomMiniMessage { + private static final MiniMessage unsafe = MiniMessage.miniMessage(); + private static final MiniMessage safe = MiniMessage.builder() + .tags(TagResolver.resolver( + StandardTags.color(), + StandardTags.rainbow(), + StandardTags.gradient(), + StandardTags.newline(), + StandardTags.decorations(TextDecoration.ITALIC), + StandardTags.decorations(TextDecoration.BOLD), + StandardTags.decorations(TextDecoration.STRIKETHROUGH), + StandardTags.decorations(TextDecoration.UNDERLINED) + )) + .build(); + private FreedomMiniMessage() { throw new UnsupportedOperationException("Instantiation of a static utility class is not supported."); } - private static final MiniMessage unsafe = MiniMessage.miniMessage(); - - private static final MiniMessage safe = MiniMessage.builder().tags(TagResolver.resolver( - StandardTags.color(), - StandardTags.rainbow(), - StandardTags.gradient(), - StandardTags.newline(), - StandardTags.decorations(TextDecoration.ITALIC), - StandardTags.decorations(TextDecoration.BOLD), - StandardTags.decorations(TextDecoration.STRIKETHROUGH), - StandardTags.decorations(TextDecoration.UNDERLINED) - )).build(); - /** - * Deserializes an input string using an instance of MiniMessage that is either safe (resolves only a specific set of tags) - * or unsafe (resolves all tags). - * @param safe Whether to use a safe instance of MiniMessage - * @param input An input string formatted with MiniMessage's input - * @param placeholders Custom placeholders to use when processing the input - * @return A processed Component + * Deserializes an input string using an instance of MiniMessage that is either safe (resolves only a specific + * set of tags) + * or unsafe (resolves all tags). + * + * @param safe Whether to use a safe instance of MiniMessage + * @param input An input string formatted with MiniMessage's input + * @param placeholders Custom placeholders to use when processing the input + * @return A processed Component */ public static Component deserialize(boolean safe, String input, TagResolver... placeholders) { - return (safe ? FreedomMiniMessage.safe : unsafe).deserialize(input, placeholders); + return (safe + ? FreedomMiniMessage.safe + : unsafe).deserialize(input, placeholders); } /** * Serializes an input component using an instance of MiniMessage that is either safe (resolves only a specific set - * of tags) or unsafe (resolves all tags). - * @param safe Whether to use a safe instance of MiniMessage - * @param input An already processed component - * @return A processed Component + * of tags) or unsafe (resolves all tags). + * + * @param safe Whether to use a safe instance of MiniMessage + * @param input An already processed component + * @return A processed Component */ public static String serialize(boolean safe, Component input) { - return (safe ? FreedomMiniMessage.safe : unsafe).serialize(input); + return (safe + ? FreedomMiniMessage.safe + : unsafe).serialize(input); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java b/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java index 9f839ed..2e282cb 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java @@ -69,18 +69,18 @@ public final class InterpolationUtils { final LinkedHashSet base = new LinkedHashSet<>(); final Set redToOrange = componentRGBGradient(length, NamedTextColor.RED, - NamedTextColor.GOLD, InterpolationUtils::linear); + NamedTextColor.GOLD, InterpolationUtils::linear); final Set orangeToYellow = componentRGBGradient(length, NamedTextColor.GOLD, - NamedTextColor.YELLOW, InterpolationUtils::linear); + NamedTextColor.YELLOW, InterpolationUtils::linear); final Set yellowToGreen = componentRGBGradient(length, NamedTextColor.YELLOW, - NamedTextColor.GREEN, InterpolationUtils::linear); + NamedTextColor.GREEN, InterpolationUtils::linear); final Set greenToBlue = componentRGBGradient(length, NamedTextColor.GREEN, - NamedTextColor.BLUE, InterpolationUtils::linear); + NamedTextColor.BLUE, InterpolationUtils::linear); final Set blueToPurple = componentRGBGradient(length, NamedTextColor.BLUE, - NamedTextColor.LIGHT_PURPLE, - InterpolationUtils::linear); + NamedTextColor.LIGHT_PURPLE, + InterpolationUtils::linear); final Set purpleToRed = componentRGBGradient(length, TextColor.color(75, 0, 130), - TextColor.color(255, 0, 0), InterpolationUtils::linear); + TextColor.color(255, 0, 0), InterpolationUtils::linear); base.addAll(redToOrange); base.addAll(orangeToYellow); base.addAll(yellowToGreen); From 27dafd69e63bbffae3434740f5e12ab2b411fcfa Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Sun, 4 Jun 2023 21:30:17 -0500 Subject: [PATCH 08/14] Fixings! --- .../listener/PlayerInteractionListener.java | 43 ++++ .../datura/perms/DefaultNodes.java | 4 +- .../datura/perms/FreedomGroup.java | 4 +- .../datura/perms/FreedomUser.java | 2 +- .../datura/perms/PermissionNode.java | 4 +- .../datura/perms/PermissionNodeBuilder.java | 6 +- .../datura/user/ServerEconomyHolder.java | 53 +++++ .../datura/user/SimpleUserData.java | 2 +- .../me/totalfreedom/data/GroupRegistry.java | 2 +- .../me/totalfreedom/data/UserRegistry.java | 10 + .../totalfreedom/display/BossBarDisplay.java | 204 ++++++++++++++++++ .../me/totalfreedom/display/TitleDisplay.java | 127 +++++++++++ .../logging/BlockInteraction.java | 57 +++++ .../logging/ContainerInteraction.java | 63 ++++++ .../me/totalfreedom/logging/Interaction.java | 33 +++ .../logging/InteractionFormatter.java | 139 ++++++++++++ .../security/{perm => }/Group.java | 2 +- .../security/{perm => }/Node.java | 2 +- .../security/{perm => }/NodeBuilder.java | 2 +- .../security/{perm => }/NodeType.java | 2 +- .../security/{perm => }/PermissionHolder.java | 2 +- .../me/totalfreedom/security/ban/Ban.java | 78 ------- .../me/totalfreedom/security/ban/BanID.java | 54 ----- .../java/me/totalfreedom/shop/Reactable.java | 16 ++ .../me/totalfreedom/shop/ReactionType.java | 6 + .../main/java/me/totalfreedom/user/User.java | 2 +- .../java/me/totalfreedom/user/UserData.java | 6 +- 27 files changed, 770 insertions(+), 155 deletions(-) create mode 100644 Corvo/src/main/java/me/totalfreedom/corvo/listener/PlayerInteractionListener.java create mode 100644 Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/logging/BlockInteraction.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/logging/ContainerInteraction.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/logging/Interaction.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/logging/InteractionFormatter.java rename Patchwork/src/main/java/me/totalfreedom/security/{perm => }/Group.java (86%) rename Patchwork/src/main/java/me/totalfreedom/security/{perm => }/Node.java (89%) rename Patchwork/src/main/java/me/totalfreedom/security/{perm => }/NodeBuilder.java (88%) rename Patchwork/src/main/java/me/totalfreedom/security/{perm => }/NodeType.java (70%) rename Patchwork/src/main/java/me/totalfreedom/security/{perm => }/PermissionHolder.java (87%) delete mode 100644 Patchwork/src/main/java/me/totalfreedom/security/ban/Ban.java delete mode 100644 Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/shop/ReactionType.java diff --git a/Corvo/src/main/java/me/totalfreedom/corvo/listener/PlayerInteractionListener.java b/Corvo/src/main/java/me/totalfreedom/corvo/listener/PlayerInteractionListener.java new file mode 100644 index 0000000..0704003 --- /dev/null +++ b/Corvo/src/main/java/me/totalfreedom/corvo/listener/PlayerInteractionListener.java @@ -0,0 +1,43 @@ +package me.totalfreedom.corvo.listener; + +import io.papermc.paper.event.block.BlockBreakBlockEvent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +public class PlayerInteractionListener implements Listener +{ + @EventHandler + public void playerBreakBlock(final BlockBreakEvent event) + { + + } + + @EventHandler + public void blockBreakBlock(final BlockBreakBlockEvent event) + { + + } + + @EventHandler + public void playerOpenContainer(final InventoryOpenEvent event) + { + + } + + @EventHandler + public void playerCloseContainer(final InventoryCloseEvent event) + { + + } + + @EventHandler + public void playerInteraction(final PlayerInteractEvent event) + { + + } + +} 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 3ed35ff..5119871 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java @@ -1,7 +1,7 @@ package me.totalfreedom.datura.perms; -import me.totalfreedom.security.perm.Node; -import me.totalfreedom.security.perm.NodeType; +import me.totalfreedom.security.Node; +import me.totalfreedom.security.NodeType; public class DefaultNodes { diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java index b518f24..6e9a6d6 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java @@ -1,8 +1,8 @@ package me.totalfreedom.datura.perms; import me.totalfreedom.base.CommonsBase; -import me.totalfreedom.security.perm.Group; -import me.totalfreedom.security.perm.Node; +import me.totalfreedom.security.Group; +import me.totalfreedom.security.Node; import net.kyori.adventure.text.Component; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionAttachment; diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java index 2a5d82a..cdd00f1 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java @@ -3,7 +3,7 @@ package me.totalfreedom.datura.perms; import me.totalfreedom.base.CommonsBase; import me.totalfreedom.datura.Datura; import me.totalfreedom.datura.user.SimpleUserData; -import me.totalfreedom.security.perm.Node; +import me.totalfreedom.security.Node; import me.totalfreedom.user.User; import me.totalfreedom.user.UserData; import net.kyori.adventure.text.Component; diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java index 22fd39b..2a88f40 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java @@ -1,7 +1,7 @@ package me.totalfreedom.datura.perms; -import me.totalfreedom.security.perm.Node; -import me.totalfreedom.security.perm.NodeType; +import me.totalfreedom.security.Node; +import me.totalfreedom.security.NodeType; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNodeBuilder.java b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNodeBuilder.java index 3ac7361..a89e69b 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNodeBuilder.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNodeBuilder.java @@ -1,8 +1,8 @@ package me.totalfreedom.datura.perms; -import me.totalfreedom.security.perm.Node; -import me.totalfreedom.security.perm.NodeBuilder; -import me.totalfreedom.security.perm.NodeType; +import me.totalfreedom.security.Node; +import me.totalfreedom.security.NodeBuilder; +import me.totalfreedom.security.NodeType; public class PermissionNodeBuilder implements NodeBuilder { diff --git a/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java b/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java new file mode 100644 index 0000000..6db83ee --- /dev/null +++ b/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java @@ -0,0 +1,53 @@ +package me.totalfreedom.datura.user; + +import me.totalfreedom.economy.EconomicEntity; +import me.totalfreedom.economy.EconomicEntityData; + +public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData +{ + private long balance = Long.MAX_VALUE; + + @Override + public EconomicEntityData getEconomicData() + { + return this; + } + + @Override + public String getName() + { + return "TotalFreedom-Bank"; + } + + @Override + public boolean areTransactionsFrozen() + { + return false; + } + + @Override + public long getBalance() + { + return balance; + } + + @Override + public void setBalance(final long newBalance) + { + balance = newBalance; + } + + @Override + public long addToBalance(final long amount) + { + balance += amount; + return balance; + } + + @Override + public long removeFromBalance(final long amount) + { + balance -= amount; + return balance; + } +} 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 2ecefd4..65df6a1 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java @@ -3,7 +3,7 @@ package me.totalfreedom.datura.user; import me.totalfreedom.base.CommonsBase; import me.totalfreedom.datura.event.UserDataUpdateEvent; import me.totalfreedom.datura.perms.FreedomUser; -import me.totalfreedom.security.perm.Group; +import me.totalfreedom.security.Group; import me.totalfreedom.sql.SQL; import me.totalfreedom.user.User; import me.totalfreedom.user.UserData; diff --git a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java index 8e8643e..12e6c57 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java @@ -1,6 +1,6 @@ package me.totalfreedom.data; -import me.totalfreedom.security.perm.Group; +import me.totalfreedom.security.Group; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import java.util.ArrayList; diff --git a/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java index 24bffa1..b5f47e4 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java @@ -2,6 +2,7 @@ package me.totalfreedom.data; import me.totalfreedom.user.User; import me.totalfreedom.user.UserData; +import org.bukkit.entity.Player; import java.util.HashMap; import java.util.Map; @@ -20,6 +21,15 @@ public class UserRegistry return userDataMap.get(user); } + public UserData fromPlayer(final Player player) { + return userDataMap.entrySet() + .stream() + .filter(entry -> entry.getKey().getUniqueId().equals(player.getUniqueId())) + .findFirst() + .map(Map.Entry::getValue) + .orElse(null); + } + public void registerUserData(final User user, final UserData userData) { userDataMap.put(user, userData); diff --git a/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java b/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java new file mode 100644 index 0000000..3c59ccd --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java @@ -0,0 +1,204 @@ +package me.totalfreedom.display; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.ForwardingAudience; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import org.jetbrains.annotations.Range; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class BossBarDisplay +{ + private BossBar bossBar; + + public BossBarDisplay(final BossBar bossBar) + { + this.bossBar = bossBar; + } + + public static BossBarBuilder builder() + { + return new BossBarBuilder(); + } + + public void changeColor(final BossBar.Color color) + { + this.bossBar.color(color); + } + + public void changeOverlay(final BossBar.Overlay overlay) + { + this.bossBar.overlay(overlay); + } + + public void changeName(final Component name) + { + this.bossBar.name(name); + } + + public void changeName(final String name, final TextColor color) + { + this.bossBar.name(Component.text(name, color)); + } + + public void changeName(final String name) + { + this.bossBar.name(Component.text(name)); + } + + public void showTo(final Audience audience) + { + audience.showBossBar(getBossBar()); + } + + public BossBar getBossBar() + { + return this.bossBar; + } + + public void setBossBar(final BossBar bossBar) + { + this.bossBar = bossBar; + } + + public void hideFrom(final Audience audience) + { + audience.hideBossBar(getBossBar()); + } + + public void incrementProgress(final @Range(from = 0, to = 100) float progress) + { + final float currentProgress = this.bossBar.progress(); + final float newProgress = currentProgress + (progress / 100.0F); + + if (newProgress > 1) this.bossBar.progress(1.0F); + else this.bossBar.progress(newProgress); + } + + public void decrementProgress(final @Range(from = 0, to = 100) float progress) + { + final float currentProgress = this.bossBar.progress(); + final float newProgress = currentProgress - (progress / 100.0F); + + if (newProgress < 0) this.bossBar.progress(0.0F); + else this.bossBar.progress(newProgress); + } + + public void maximumProgress() + { + this.bossBar.progress(1.0F); + } + + public void halfProgress() + { + this.bossBar.progress(0.5F); + } + + public void minimumProgress() + { + this.bossBar.progress(0.0F); + } + + public void showForwarded(final ForwardingAudience forwardingAudience) + { + forwardingAudience.showBossBar(getBossBar()); + } + + public void hideForwarded(final ForwardingAudience forwardingAudience) + { + forwardingAudience.hideBossBar(getBossBar()); + } + + private static final class BossBarBuilder + { + private final Set flags = new HashSet<>(); + private Component name; + private BossBar.Color color; + private BossBar.Overlay overlay; + @Range(from = 0, to = 1) + private float progress; + + public BossBarBuilder() + { + this.name = Component.empty(); + this.color = BossBar.Color.GREEN; + this.overlay = BossBar.Overlay.PROGRESS; + this.progress = 0.0F; + } + + public BossBarBuilder setName(final Component name) + { + this.name = name; + return this; + } + + public BossBarBuilder setName(final String name, final TextColor color) + { + this.name = Component.text(name, color); + return this; + } + + public BossBarBuilder setName(final String name) + { + this.name = Component.text(name); + return this; + } + + public BossBarBuilder addFlag(final BossBar.Flag flag) + { + this.flags.add(flag); + return this; + } + + public BossBarBuilder addFlags(final BossBar.Flag... flags) + { + this.flags.addAll(List.of(flags)); + return this; + } + + public BossBarBuilder removeFlag(final BossBar.Flag flag) + { + this.flags.remove(flag); + return this; + } + + public BossBarBuilder removeFlags(final BossBar.Flag... flags) + { + this.flags.removeAll(List.of(flags)); + return this; + } + + public BossBarBuilder clearFlags() + { + this.flags.clear(); + return this; + } + + public BossBarBuilder setColor(final BossBar.Color color) + { + this.color = color; + return this; + } + + public BossBarBuilder setOverlay(final BossBar.Overlay overlay) + { + this.overlay = overlay; + return this; + } + + public BossBarBuilder setProgress(final @Range(from = 0, to = 100) float progress) + { + this.progress = progress / 100.0F; + return this; + } + + public BossBar build() + { + return BossBar.bossBar(this.name, this.progress, this.color, this.overlay, this.flags); + } + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java b/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java new file mode 100644 index 0000000..1a7a4e4 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java @@ -0,0 +1,127 @@ +package me.totalfreedom.display; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.ForwardingAudience; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.title.Title; + +import java.time.Duration; + +public class TitleDisplay +{ + private Title title; + + public TitleDisplay(final Title title) + { + this.title = title; + } + + public static TitleBuilder builder() + { + return new TitleBuilder(); + } + + public void displayTo(final Audience audience) + { + audience.clearTitle(); + audience.showTitle(getTitle()); + } + + public Title getTitle() + { + return this.title; + } + + public void setTitle(final Title title) + { + this.title = title; + } + + public void displayForwarded(final ForwardingAudience forwardingAudience) + { + forwardingAudience.clearTitle(); + forwardingAudience.showTitle(getTitle()); + } + + private static final class TitleBuilder + { + private Component mainTitle; + private Component subTitle; + private Duration fadeIn; + private Duration fadeOut; + private Duration displayDuration; + + public TitleBuilder() + { + this.mainTitle = Component.empty(); + this.subTitle = Component.empty(); + this.fadeIn = Title.DEFAULT_TIMES.fadeIn(); + this.fadeOut = Title.DEFAULT_TIMES.fadeOut(); + this.displayDuration = Title.DEFAULT_TIMES.stay(); + } + + public TitleBuilder setMainTitle(final String title) + { + this.mainTitle = Component.text(title); + return this; + } + + public TitleBuilder setMainTitle(final String title, final TextColor titleColor) + { + this.mainTitle = Component.text(title, titleColor); + return this; + } + + public TitleBuilder setMainTitle(final Component mainTitle) + { + this.mainTitle = mainTitle; + return this; + } + + public TitleBuilder setSubTitle(final String title) + { + this.subTitle = Component.text(title); + return this; + } + + public TitleBuilder setSubTitle(final String title, final TextColor titleColor) + { + this.subTitle = Component.text(title, titleColor); + return this; + } + + public TitleBuilder setSubTitle(final Component subTitle) + { + this.subTitle = subTitle; + return this; + } + + public TitleBuilder setFadeIn(final Duration duration) + { + this.fadeIn = duration; + return this; + } + + public TitleBuilder setFadeOut(final Duration duration) + { + this.fadeOut = duration; + return this; + } + + public TitleBuilder setDisplayDuration(final Duration duration) + { + this.displayDuration = duration; + return this; + } + + public Title build() + { + return Title.title( + this.mainTitle, + this.subTitle, + Title.Times.times(this.fadeIn, this.displayDuration, this.fadeOut) + ); + } + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/logging/BlockInteraction.java b/Patchwork/src/main/java/me/totalfreedom/logging/BlockInteraction.java new file mode 100644 index 0000000..ae64341 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/logging/BlockInteraction.java @@ -0,0 +1,57 @@ +package me.totalfreedom.logging; + +import org.bukkit.Location; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.time.Instant; +import java.util.UUID; + +public final class BlockInteraction implements Interaction +{ + private final Location location; + private final UUID whoClicked; + private final Instant when; + private final BlockData originalState; + private final BlockData newState; + + public BlockInteraction(final Player player, final BlockData originalState, final BlockData newState) + { + this.location = player.getLocation(); + this.whoClicked = player.getUniqueId(); + this.when = Instant.now(); + this.originalState = originalState; + this.newState = newState; + } + + @Override + public @NotNull UUID getWhoClicked() + { + return whoClicked; + } + + @Override + public @NotNull BlockData getOriginalState() + { + return originalState; + } + + @Override + public @NotNull BlockData getNewState() + { + return newState; + } + + @Override + public @NotNull Instant getWhen() + { + return when; + } + + @Override + public @NotNull Location getLocation() + { + return location; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/logging/ContainerInteraction.java b/Patchwork/src/main/java/me/totalfreedom/logging/ContainerInteraction.java new file mode 100644 index 0000000..c09efee --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/logging/ContainerInteraction.java @@ -0,0 +1,63 @@ +package me.totalfreedom.logging; + +import org.bukkit.Location; +import org.bukkit.block.Container; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.time.Instant; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +public final class ContainerInteraction implements Interaction> +{ + private final UUID whoClicked; + private final List originalState; + private final List newState; + private final Instant when; + private final Location location; + + public ContainerInteraction(final Player player, final Container originalState, final Container newState) + { + this.whoClicked = player.getUniqueId(); + this.originalState = Collections.unmodifiableList(Arrays.asList(originalState.getInventory() + .getContents())); + this.newState = Collections.unmodifiableList(Arrays.asList(newState.getInventory() + .getContents())); + this.location = originalState.getLocation(); + this.when = Instant.now(); + } + + @Override + public @NotNull UUID getWhoClicked() + { + return whoClicked; + } + + @Override + public @NotNull List getOriginalState() + { + return originalState; + } + + @Override + public @NotNull List getNewState() + { + return newState; + } + + @Override + public @NotNull Instant getWhen() + { + return when; + } + + @Override + public @NotNull Location getLocation() + { + return location; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/logging/Interaction.java b/Patchwork/src/main/java/me/totalfreedom/logging/Interaction.java new file mode 100644 index 0000000..75aeb63 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/logging/Interaction.java @@ -0,0 +1,33 @@ +package me.totalfreedom.logging; + +import com.google.errorprone.annotations.Immutable; +import org.bukkit.Location; +import org.jetbrains.annotations.NotNull; + +import java.time.Instant; +import java.util.UUID; + +@Immutable +public interface Interaction +{ + @NotNull + static String format(@NotNull final Interaction interaction) + { + return new InteractionFormatter().formatInteraction(interaction); + } + + @NotNull + UUID getWhoClicked(); + + @NotNull + T getOriginalState(); + + @NotNull + T getNewState(); + + @NotNull + Instant getWhen(); + + @NotNull + Location getLocation(); +} diff --git a/Patchwork/src/main/java/me/totalfreedom/logging/InteractionFormatter.java b/Patchwork/src/main/java/me/totalfreedom/logging/InteractionFormatter.java new file mode 100644 index 0000000..c34bf1a --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/logging/InteractionFormatter.java @@ -0,0 +1,139 @@ +package me.totalfreedom.logging; + +import me.totalfreedom.sql.SQL; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.inventory.ItemStack; + +import java.time.Instant; + +public final class InteractionFormatter +{ + public String formatInteraction(final Interaction interaction) + { + final String location = formatLocation(interaction.getLocation()); + final String world = formatWorld(interaction.getLocation() + .getWorld()); + final String player = interaction.getWhoClicked() + .toString(); + final String block = formatBlock(interaction.getLocation() + .getBlock()); + final String when = formatTime(interaction.getWhen()); + + if (interaction instanceof ContainerInteraction container) + { + final StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Container ") + .append(block) + .append(" at location ") + .append(location) + .append(" in world ") + .append(world) + .append(" was opened by ") + .append(player) + .append(" at ") + .append(when) + .append("\nHere is a list of items changed:\n"); + + container.getOriginalState() + .stream() + .filter(item -> + { + final ItemStack newItem = container.getNewState() + .stream() + .filter(item2 -> item2.isSimilar(item)) + .findFirst() + .orElse(null); + return newItem == null || newItem.getAmount() != item.getAmount(); + }) + .forEach(item -> + { + final ItemStack newItem = container.getNewState() + .stream() + .filter(item2 -> item2.isSimilar(item)) + .findFirst() + .orElse(null); + stringBuilder.append("Item ") + .append(formatItemStack(item)) + .append(" was changed to ") + .append(formatItemStack(newItem)) + .append("\n"); + }); + + stringBuilder.append("."); + + return stringBuilder.toString(); + } else if (interaction instanceof BlockInteraction blockData) + { + final StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Block ") + .append(block) + .append(" at location ") + .append(location) + .append(" in world ") + .append(world) + .append(" was changed by ") + .append(player) + .append(" at ") + .append(when) + .append("\nBlock was changed from ") + .append(blockData.getOriginalState() + .getAsString()) + .append(" to ") + .append(blockData.getNewState() + .getAsString()) + .append("."); + + return stringBuilder.toString(); + } else + { + throw new IllegalArgumentException("Unknown interaction type: " + interaction.getClass() + .getName()); + } + } + + // Format: ,, + public String formatLocation(final Location location) + { + return String.format("%s,%s,%s", location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + + // Format: + public String formatWorld(final World world) + { + return world.getName(); + } + + // Format: + public String formatBlock(final Block block) + { + return block.getType() + .toString() + .toLowerCase(); + } + + public String formatTime(final Instant instant) + { + final String trimmed = instant.toString() + .replaceAll("[TZ]", " "); + final int dotIndex = trimmed.indexOf('.'); + + return (dotIndex != -1) + ? trimmed.substring(0, dotIndex) + : trimmed; + } + + // Format: , + public String formatItemStack(final ItemStack stack) + { + if (stack == null) + { + return String.format("%s,%s", "empty", "0"); + } + + return String.format("%s,%s", stack.getType() + .toString() + .toLowerCase(), stack.getAmount()); + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/security/perm/Group.java b/Patchwork/src/main/java/me/totalfreedom/security/Group.java similarity index 86% rename from Patchwork/src/main/java/me/totalfreedom/security/perm/Group.java rename to Patchwork/src/main/java/me/totalfreedom/security/Group.java index a0f1dcd..d09ba61 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/perm/Group.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/Group.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security.perm; +package me.totalfreedom.security; import net.kyori.adventure.text.Component; diff --git a/Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java b/Patchwork/src/main/java/me/totalfreedom/security/Node.java similarity index 89% rename from Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java rename to Patchwork/src/main/java/me/totalfreedom/security/Node.java index d661221..8af9348 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/perm/Node.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/Node.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security.perm; +package me.totalfreedom.security; import org.bukkit.permissions.Permission; diff --git a/Patchwork/src/main/java/me/totalfreedom/security/perm/NodeBuilder.java b/Patchwork/src/main/java/me/totalfreedom/security/NodeBuilder.java similarity index 88% rename from Patchwork/src/main/java/me/totalfreedom/security/perm/NodeBuilder.java rename to Patchwork/src/main/java/me/totalfreedom/security/NodeBuilder.java index 6769556..c0503ff 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/perm/NodeBuilder.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/NodeBuilder.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security.perm; +package me.totalfreedom.security; public interface NodeBuilder { diff --git a/Patchwork/src/main/java/me/totalfreedom/security/perm/NodeType.java b/Patchwork/src/main/java/me/totalfreedom/security/NodeType.java similarity index 70% rename from Patchwork/src/main/java/me/totalfreedom/security/perm/NodeType.java rename to Patchwork/src/main/java/me/totalfreedom/security/NodeType.java index 31c5b83..11293a9 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/perm/NodeType.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/NodeType.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security.perm; +package me.totalfreedom.security; public enum NodeType { diff --git a/Patchwork/src/main/java/me/totalfreedom/security/perm/PermissionHolder.java b/Patchwork/src/main/java/me/totalfreedom/security/PermissionHolder.java similarity index 87% rename from Patchwork/src/main/java/me/totalfreedom/security/perm/PermissionHolder.java rename to Patchwork/src/main/java/me/totalfreedom/security/PermissionHolder.java index f15ec15..05f7e7c 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/perm/PermissionHolder.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/PermissionHolder.java @@ -1,4 +1,4 @@ -package me.totalfreedom.security.perm; +package me.totalfreedom.security; import org.bukkit.permissions.Permissible; diff --git a/Patchwork/src/main/java/me/totalfreedom/security/ban/Ban.java b/Patchwork/src/main/java/me/totalfreedom/security/ban/Ban.java deleted file mode 100644 index 438b5f8..0000000 --- a/Patchwork/src/main/java/me/totalfreedom/security/ban/Ban.java +++ /dev/null @@ -1,78 +0,0 @@ -package me.totalfreedom.security.ban; - -import org.jetbrains.annotations.Nullable; - -import java.time.Instant; -import java.util.UUID; - -/** - * Represents a physical ban entry. This is used to store information about a ban, - * such as the player who was banned, the reason for why they were banned, the individual who issued the ban, - * when the ban expires, and when the ban was created. - *
- * Ban information is stored in the Database with the {@link BanID} as the PRIMARY KEY. - */ -public interface Ban -{ - /** - * Gets the ID of this ban. This is an object which represents a string prefixed with either a T or a P, - * and suffixed with a 6-10 digit numerical code. This is used to identify the ban in the database, and for - * easier ban referencing. - * - * @return The ID of this ban. - */ - BanID getBanID(); - - /** - * Gets the UUID of the player who was banned. This is formatted as a UUID - * which allows us to retrieve the particular player instance, if applicable, and also - * have a true identifier to check against user logins. - * - * @return The UUID of the player who was banned. - */ - UUID getOffenderID(); - - /** - * Gets the reason that the player was banned for. Typically, the default reason is "You are banned!". - * We've forced implementations to require a reason, as it's important to know why a player was banned. - * - * @return The reason that the player was banned for. - */ - String getReason(); - - /** - * Gets the username of the individual who issued the ban. This is not a reliable way to store data, but - * in our case, we should not need to interact with the ban issuer from the code. This is simply for - * reference purposes. - * - * @return The username of the individual who issued the ban. - */ - String getBanIssuer(); - - /** - * Gets the {@link Instant} which this ban was created. - * - * @return The ban's creation time. - */ - Instant getCreationTime(); - - /** - * Gets the {@link Instant} which this ban is due to expire, if applicable. - * This method is annotated as {@link Nullable}, as permanent bans do not have an expiry date. - * - * @return The ban's expiry time, or null if the ban is permanent. - */ - @Nullable - Instant getExpiry(); - - /** - * Checks if the ban has expired. This will return false if: - *
    - *
  • The {@link Instant} returned by {@link #getExpiry()} is null.
  • - *
  • The {@link Instant} returned by {@link #getExpiry()} is after the current time.
  • - *
- * - * @return True if the ban has expired, false otherwise. - */ - boolean isExpired(); -} diff --git a/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java b/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java deleted file mode 100644 index b6f004a..0000000 --- a/Patchwork/src/main/java/me/totalfreedom/security/ban/BanID.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.totalfreedom.security.ban; - -/** - * Represents an ID for a ban. These are formatted either as: - *

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

- * Where P marks a ban as permanent, and T marks a ban as temporary. - */ -public interface BanID -{ - /** - * This method returns the full Ban ID. - * - * @return The actual ID. - */ - String getID(); - - /** - * 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. - * - * @return The ban type denominator character for the Ban ID. - */ - char getIDPrefix(); - - /** - * Gets the numerical tag of this ban ID. - * This would be the numerical section of the full Ban ID. - * - * @return The numerical tag of this ban ID. - */ - int getNumericalTag(); -} diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java b/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java new file mode 100644 index 0000000..c8dacd2 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java @@ -0,0 +1,16 @@ +package me.totalfreedom.shop; + +import me.totalfreedom.economy.EconomicEntity; + +import java.time.Duration; + +public interface Reactable +{ + String getReactionMessage(); + + Duration getReactionDuration(); + + ReactionType getReactionType(); + + void onReact(final EconomicEntity entity); +} diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/ReactionType.java b/Patchwork/src/main/java/me/totalfreedom/shop/ReactionType.java new file mode 100644 index 0000000..b2b308d --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/shop/ReactionType.java @@ -0,0 +1,6 @@ +package me.totalfreedom.shop; + +public enum ReactionType +{ + COPYCAT, UNSCRAMBLE; +} diff --git a/Patchwork/src/main/java/me/totalfreedom/user/User.java b/Patchwork/src/main/java/me/totalfreedom/user/User.java index 20f58e6..f925492 100644 --- a/Patchwork/src/main/java/me/totalfreedom/user/User.java +++ b/Patchwork/src/main/java/me/totalfreedom/user/User.java @@ -2,7 +2,7 @@ package me.totalfreedom.user; import me.totalfreedom.economy.EconomicEntity; import me.totalfreedom.economy.EconomicEntityData; -import me.totalfreedom.security.perm.PermissionHolder; +import me.totalfreedom.security.PermissionHolder; import net.kyori.adventure.text.Component; public interface User extends PermissionHolder, EconomicEntity diff --git a/Patchwork/src/main/java/me/totalfreedom/user/UserData.java b/Patchwork/src/main/java/me/totalfreedom/user/UserData.java index e482750..2cfb8d1 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.economy.EconomicEntityData; -import me.totalfreedom.security.perm.Group; +import me.totalfreedom.security.Group; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,10 +27,6 @@ public interface UserData extends EconomicEntityData void resetPlaytime(); - boolean isFrozen(); - - void setFrozen(boolean frozen); - boolean canInteract(); void setInteractionState(boolean canInteract); From 1ea106d999553dd5bd4c3aec2e407e7f664550e5 Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Thu, 8 Jun 2023 10:02:20 -0500 Subject: [PATCH 09/14] Documentation, Add BouncyPads --- .../java/me/totalfreedom/datura/Datura.java | 4 +- .../datura/perms/FreedomUser.java | 2 +- .../datura/user/ServerEconomyHolder.java | 83 ++++++- .../java/me/totalfreedom/fossil/Fossil.java | 2 +- .../fossil/bouncypads/BouncyPad.java | 211 ++++++++++++++++++ .../fossil/bouncypads/PadHolder.java | 156 +++++++++++++ .../fossil/bouncypads/PadType.java | 32 +++ .../fossil/reactions/CopyCatReaction.java | 58 +++++ .../java/me/totalfreedom/api/Context.java | 87 ++++++++ .../me/totalfreedom/api/Interpolator.java | 14 ++ .../me/totalfreedom/api/Serializable.java | 15 +- .../audience/MutableAudienceForwarder.java | 138 +++++++++--- .../me/totalfreedom/base/CommonsBase.java | 47 +++- .../me/totalfreedom/base/Registration.java | 50 ++++- .../totalfreedom/command/BukkitDelegate.java | 52 +++-- .../totalfreedom/command/CommandHandler.java | 22 ++ .../me/totalfreedom/command/Commander.java | 84 ++++++- .../command/annotation/Completion.java | 14 ++ .../command/annotation/Completions.java | 9 + .../totalfreedom/command/annotation/Info.java | 26 +++ .../command/annotation/Permissive.java | 19 ++ .../command/annotation/Subcommand.java | 26 +++ .../me/totalfreedom/config/Configuration.java | 100 ++++++++- .../me/totalfreedom/data/ConfigRegistry.java | 20 ++ .../me/totalfreedom/data/EventRegistry.java | 24 ++ .../me/totalfreedom/data/GroupRegistry.java | 27 +++ .../me/totalfreedom/data/ModuleRegistry.java | 31 ++- .../me/totalfreedom/data/UserRegistry.java | 56 ++++- .../me/totalfreedom/display/AbstractMenu.java | 88 +++++++- .../totalfreedom/display/BossBarDisplay.java | 170 +++++++++++++- .../me/totalfreedom/display/BossBarTimer.java | 40 ++++ .../me/totalfreedom/display/ClickAction.java | 7 + .../me/totalfreedom/display/Displayable.java | 31 ++- .../totalfreedom/display/DisplayableView.java | 40 +++- .../me/totalfreedom/display/TitleDisplay.java | 111 ++++++++- .../service/ServiceSubscription.java | 20 +- .../service/SubscriptionProvider.java | 20 +- .../java/me/totalfreedom/service/Task.java | 83 ++++++- .../java/me/totalfreedom/shop/Reactable.java | 11 +- .../java/me/totalfreedom/shop/Reaction.java | 69 ++++++ .../me/totalfreedom/shop/ReactionTask.java | 50 +++++ .../me/totalfreedom/shop/ReactionType.java | 2 +- .../me/totalfreedom/utils/DurationTools.java | 28 +++ 43 files changed, 2069 insertions(+), 110 deletions(-) create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/BouncyPad.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadHolder.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadType.java create mode 100644 Fossil/src/main/java/me/totalfreedom/fossil/reactions/CopyCatReaction.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/shop/ReactionTask.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/utils/DurationTools.java diff --git a/Datura/src/main/java/me/totalfreedom/datura/Datura.java b/Datura/src/main/java/me/totalfreedom/datura/Datura.java index 5ef1440..da40da4 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/Datura.java +++ b/Datura/src/main/java/me/totalfreedom/datura/Datura.java @@ -27,11 +27,11 @@ public class Datura extends JavaPlugin CommonsBase.getInstance() .getRegistrations() - .getServiceRegistry() + .getServiceTaskRegistry() .registerService(SubscriptionProvider.syncService(this, locker)); CommonsBase.getInstance() .getRegistrations() - .getServiceRegistry() + .getServiceTaskRegistry() .registerService(SubscriptionProvider.syncService(this, cager)); Bukkit.getPluginManager() 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 cdd00f1..50a716b 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java @@ -45,7 +45,7 @@ public class FreedomUser implements User final Datura datura = CommonsBase.getInstance() .getRegistrations() .getModuleRegistry() - .getModule(Datura.class) + .getProvider(Datura.class) .getModule(); UserData data = SimpleUserData.fromSQL(datura.getSQL(), uuid.toString()); diff --git a/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java b/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java index 6db83ee..e9771f3 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java @@ -3,40 +3,112 @@ package me.totalfreedom.datura.user; import me.totalfreedom.economy.EconomicEntity; import me.totalfreedom.economy.EconomicEntityData; +/** + * Represents the server's economy holder. + *
+ *
+ * This is effectively a Bank object which is meant to represent the server itself, + * which can store a balance and perform transactions with other EconomicEntity objects. + *
+ *
+ * The server is initially given a maximum balance of {@link Long#MAX_VALUE}, though this can be changed + * using the constructor {@link #ServerEconomyHolder(String, long)}. The value that this + * bank object holds is persistent, which means that the total economic resources available + * are of limited supply. + *
+ *
+ * Please be aware, if the server's economy falls below 0, + * it will have drastic consequences. + */ public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData { - private long balance = Long.MAX_VALUE; + private final String name; + private long balance; + /** + * Constructs a new ServerEconomyHolder with the specified name and a balance of {@link Long#MAX_VALUE}. + * + * @param name The name of this server economy holder. + */ + public ServerEconomyHolder(final String name) + { + this.name = name; + this.balance = Long.MAX_VALUE; + } + + /** + * Constructs a new ServerEconomyHolder with the specified name and balance. + * + * @param name The name of this server economy holder. + * @param balance The balance of this server economy holder. + */ + public ServerEconomyHolder(final String name, final long balance) + { + this.name = name; + this.balance = balance; + } + + /** + * This method will return this object, as it is both the EconomicEntity and the EconomicEntityData. + * This is due to the fact that the server should only ever have one singular concrete representation + * of it's economic entity and the respective data. + * + * @return this object. + */ @Override public EconomicEntityData getEconomicData() { return this; } + /** + * @return The name of this server economy holder. + */ @Override public String getName() { - return "TotalFreedom-Bank"; + return name; } + /** + * This method will always return false, as the server should not ever be + * prevented from performing transactions. + * + * @return false + */ @Override public boolean areTransactionsFrozen() { return false; } + /** + * @return The server's current available balance. + */ @Override public long getBalance() { return balance; } + /** + * Sets the server's balance to the specified value. + * + * @param newBalance The new balance to set. + */ @Override public void setBalance(final long newBalance) { balance = newBalance; } + /** + * Adds the specified amount to the server's balance. + * This method mutates the balance and returns the new balance. + * + * @param amount The amount to add. + * @return The new balance. + */ @Override public long addToBalance(final long amount) { @@ -44,6 +116,13 @@ public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData return balance; } + /** + * Removes the specified amount from the server's balance. + * This method mutates the balance and returns the new balance. + * + * @param amount The amount to remove. + * @return The new balance. + */ @Override public long removeFromBalance(final long amount) { diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java b/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java index a638249..8d789f8 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java @@ -18,7 +18,7 @@ public class Fossil extends JavaPlugin registration.getModuleRegistry() .addModule(this); - registration.getServiceRegistry() + registration.getServiceTaskRegistry() .registerService( SubscriptionProvider.syncService(this, trailer)); } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/BouncyPad.java b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/BouncyPad.java new file mode 100644 index 0000000..cacd37a --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/BouncyPad.java @@ -0,0 +1,211 @@ +package me.totalfreedom.fossil.bouncypads; + +import com.google.errorprone.annotations.Immutable; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.SplittableRandom; + +/** + * Represents a bouncy pad. Has a velocity and a type. + */ +@Immutable +public class BouncyPad +{ + /** + * The velocity of the pad. + */ + private final double velocity; + /** + * The type of the pad. + */ + private final PadType padType; + + /** + * Creates a new bouncy pad. + * + * @param velocity The velocity of the pad. + * @param padType The type of the pad. + */ + public BouncyPad(final double velocity, final PadType padType) + { + this.velocity = velocity; + this.padType = padType; + } + + /** + * Creates a new bouncy pad with a type of {@link PadType#NORMAL}. + * + * @param velocity The velocity of the pad. + */ + public BouncyPad(final double velocity) + { + this(velocity, PadType.NORMAL); + } + + /** + * Creates a new bouncy pad with a velocity of 1.1 and a type of {@link PadType#NORMAL}. + */ + public BouncyPad() + { + this(1.0 + 0.1F); + } + + /** + * This method will bounce the player based on the type of the pad. + *

+ * The type of the pad, defined by {@link #padType}, will determine how the player is bounced. + *
+ * For type {@link PadType#NORMAL}, the player will be bounced if the face is {@link BlockFace#UP}. + *
+ * For type {@link PadType#SIDES}, the player will be bounced if the face is not {@link BlockFace#UP} or + * {@link BlockFace#DOWN}. + *
+ * For type {@link PadType#ALL}, the player will be bounced regardless of the face. + *
+ * For type {@link PadType#EXTREME}, the player will be bounced with a velocity based on the formula: + *
+ * (((173.31 + 0.5 * velocity) - (31.2 + 0.5 * Math.pow(velocity, 2.0)) + (0.5 * + * Math.pow(velocity, 3.0))) - 173.31) / (velocity * (velocity - 1)) + *
+ * For type {@link PadType#SPACE_CADET}, the player will be bounced with a velocity based on the formula: + *
+ * Math.round(Math.abs((accel * 100.0) + Math.pow(y, Math.floor(accel)) / + * Math.exp(accel))) + *
+ * where y = Math.abs(random.nextGaussian(12, 5) * 0.5 + 0.5) and accel = Math.sqrt(2 * 9.81 * y) + *
+ *
+ * NOTE: The velocity of the pad is added with the inverse velocity of the player. The inverse + * velocity of the player is acquired by multiplying the velocity of the player by -1. + * + * @param player The player to bounce. + * @param face The face of the block the player is bouncing on. + */ + public void bouncePad(final Player player, final BlockFace face) + { + switch (padType) + { + case NORMAL -> bounceNormal(player, face); + case SIDES -> bounceSides(player, face); + case ALL -> bounceAll(player, face); + case EXTREME -> bounceExtreme(player, face); + case SPACE_CADET -> bounceSpaceCadet(player, face); + } + } + + /** + * This method returns a vector based on the following: + *
+ * (BlockFace direction + Player velocity * -1) * velocity + *
+ *
+ * We retrieve a vector representing the direction in which this block face is facing. This is then added with the + * inverse velocity of the player, which is the direction and speed in which the player is moving multiplied by -1. + * This is then multiplied by the velocity of the pad. + * + * @param player The moving player + * @param face The face of the block the player is bouncing on. + * @return A vector representing the direction and speed in which the player should be bounced. + */ + private Vector getVector(final Player player, final BlockFace face) + { + return face.getDirection() + .add(player.getVelocity() + .multiply(-1)) + .multiply(velocity); + } + + /** + * This method will bounce the player if the face is {@link BlockFace#UP}. + * + * @param player The player to bounce. + * @param face The face of the block the player is bouncing on. + */ + private void bounceNormal(final Player player, final BlockFace face) + { + if (!face.equals(BlockFace.UP)) + return; + + player.setVelocity(getVector(player, face)); + } + + /** + * This method will bounce the player if the face is not {@link BlockFace#UP} or {@link BlockFace#DOWN}. + * + * @param player The player to bounce. + * @param face The face of the block the player is bouncing on. + */ + private void bounceSides(final Player player, final BlockFace face) + { + if (face == BlockFace.UP || face == BlockFace.DOWN) + return; + + player.setVelocity(getVector(player, face)); + } + + /** + * This method will bounce the player regardless of the face. + * + * @param player The player to bounce. + * @param face The face of the block the player is bouncing on. + */ + private void bounceAll(final Player player, final BlockFace face) + { + player.setVelocity(getVector(player, face)); + } + + /** + * This method will bounce the player with a velocity based on the formula: + *
+ * (((173.31 + 0.5 * velocity) - (31.2 + 0.5 * Math.pow(velocity, 2.0)) + (0.5 * + * Math.pow(velocity, 3.0))) - 173.31) / (velocity * (velocity - 1)) + *
+ *
+ * NOTE: The velocity of the pad is added with the inverse velocity of the player. The inverse + * velocity of the player is acquired by multiplying the velocity of the player by -1. + * + * @param player The player to bounce. + * @param face The face of the block the player is bouncing on. + */ + private void bounceExtreme(final Player player, final BlockFace face) + { + final double extremeVelocity = (((173.31 + 0.5 * velocity) - (31.2 + 0.5 * Math.pow(velocity, 2.0)) + (0.5 * Math.pow(velocity, 3.0))) - 173.31) / (velocity * (velocity - 1)); + player.setVelocity(face.getDirection() + .add(player.getVelocity() + .multiply(-1)) + .multiply(extremeVelocity * velocity)); + } + + /** + * This method will bounce the player with a velocity based on the formula: + *
+ * Math.round(Math.abs((accel * 100.0) + Math.pow(y, Math.floor(accel)) / + * Math.exp(accel))) + *
+ * where y = Math.abs(random.nextGaussian(12, 5) * 0.5 + 0.5) and + * accel = Math.sqrt(2 * 9.81 * y) + * + * @param player The player to bounce. + * @param face The face of the block the player is bouncing on. + */ + private void bounceSpaceCadet(final Player player, final BlockFace face) + { + final SplittableRandom random = new SplittableRandom(); + final double y = Math.abs(random.nextGaussian(12, 5) * 0.5 + 0.5); + final double accel = Math.sqrt(2 * 9.81 * y); + final double spaceVelocity = Math.round(Math.abs((accel * 100.0) + Math.pow(y, Math.floor(accel)) / Math.exp(accel))); + + final Vector accelVector = new Vector(0, y + accel, 0); + final Vector postVector = new Vector(0, spaceVelocity, 0); + + final Vector spaceVector = face.getDirection() + .add(player.getVelocity() + .multiply(-1)) + .multiply(accelVector.multiply(postVector)); + + player.setVelocity(spaceVector); + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadHolder.java b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadHolder.java new file mode 100644 index 0000000..829739d --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadHolder.java @@ -0,0 +1,156 @@ +package me.totalfreedom.fossil.bouncypads; + +import me.totalfreedom.base.CommonsBase; +import me.totalfreedom.fossil.Fossil; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Stream; + +/** + * Holds all the active pads for each player, and also manages player pad interaction. + */ +public class PadHolder implements Listener +{ + /** + * A map of all the currently active pads, stored by {@link Player} {@link UUID}. + */ + private final Map pads = new HashMap<>(); + + /** + * Creates a new pad holder. + */ + public PadHolder() + { + Bukkit.getPluginManager().registerEvents(this, CommonsBase + .getInstance() + .getRegistrations() + .getModuleRegistry() + .getProvider(Fossil.class) + .getModule()); + } + + /** + * Adds a pad for the given player. If the player already has a pad stored in the map, + * it will be overwritten with the new pad. + * + * @param player The player to add the pad for. + * @param pad The pad to add. + */ + public void addPad(final Player player, final BouncyPad pad) + { + this.pads.put(player.getUniqueId(), pad); + } + + /** + * Removes the pad for the given player, if the player has one. + * + * @param player The player to remove the pad for. + */ + public void removePad(final Player player) + { + this.pads.remove(player.getUniqueId()); + } + + /** + * Gets the pad for the given player, if the player has one. + * If the player has no active pad, this will return null. + * + * @param player The player to get the pad for. + * @return The pad for the given player. + */ + @Nullable + public BouncyPad getPad(final Player player) + { + return this.pads.get(player.getUniqueId()); + } + + /** + * Checks if there is a pad active for the given player. + * + * @param player The player to check. + * @return True if the player has a pad, false otherwise. + */ + public boolean hasPad(final Player player) + { + return this.pads.containsKey(player.getUniqueId()); + } + + /** + * Gets a map of all the currently active pads, stored by {@link Player} {@link UUID}. + * + * @return A map of all the currently active pads. + */ + public Map getPads() + { + return this.pads; + } + + /** + * Handles player pad interaction. This will check the relative block for each acceptible direction, and pass the + * resulting block face (if any) to the bounce pad. See {@link BouncyPad#bouncePad(Player, org.bukkit.block.BlockFace)} + * for how the resulting block face is processed. + * + * @param event The event which gets called when a player moves. + */ + @EventHandler + public void onPlayerMove(final PlayerMoveEvent event) + { + final Player player = event.getPlayer(); + if (!this.hasPad(player)) + { + return; + } + + final BouncyPad pad = this.getPad(player); + final Location location = player.getLocation(); + + final Block xNeg1 = getRelative(location, -1, 0, 0); + final Block xPos1 = getRelative(location, 1, 0, 0); + final Block zNeg1 = getRelative(location, 0, 0, -1); + final Block zPos1 = getRelative(location, 0, 0, 1); + final Block yNeg1 = getRelative(location, 0, -1, 0); + + Stream.of(xNeg1, xPos1, zNeg1, zPos1, yNeg1) + .filter(this::isWool) + .map(block -> block.getFace(location.getBlock())) + .findFirst() + .ifPresent(face -> pad.bouncePad(player, face)); + } + + /** + * Gets the relative block at the given location. + * + * @param location The location to get the relative block from. + * @param x The x mod. + * @param y The y mod. + * @param z The z mod. + * @return The relative block. + */ + private Block getRelative(final Location location, final int x, final int y, final int z) + { + return location.getBlock().getRelative(x, y, z); + } + + /** + * Checks if the given block is wool. + * + * @param block The block to check. + * @return True if the block is wool, false otherwise. + * @see Tag#WOOL + */ + private boolean isWool(final Block block) + { + return Tag.WOOL.isTagged(block.getType()); + } +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadType.java b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadType.java new file mode 100644 index 0000000..1cc0f66 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadType.java @@ -0,0 +1,32 @@ +package me.totalfreedom.fossil.bouncypads; + +import org.bukkit.block.BlockFace; + +/** + * Represents a specific type of bouncy pad. + */ +public enum PadType +{ + /** + * A normal pad, which will only bounce the player if the face is {@link BlockFace#UP}. + */ + NORMAL, + /** + * A pad which will bounce the player on {@link BlockFace#NORTH}, {@link BlockFace#SOUTH}, {@link BlockFace#EAST} + * or {@link BlockFace#WEST}. + */ + SIDES, + /** + * A pad which will bounce the player if the face is {@link BlockFace#UP}, {@link BlockFace#NORTH}, + * {@link BlockFace#EAST}, {@link BlockFace#SOUTH} or {@link BlockFace#WEST}. + */ + ALL, + /** + * A pad which will bounce the player with an extreme velocity + */ + EXTREME, + /** + * A pad which will send the player to space. + */ + SPACE_CADET; +} diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/reactions/CopyCatReaction.java b/Fossil/src/main/java/me/totalfreedom/fossil/reactions/CopyCatReaction.java new file mode 100644 index 0000000..983e5b4 --- /dev/null +++ b/Fossil/src/main/java/me/totalfreedom/fossil/reactions/CopyCatReaction.java @@ -0,0 +1,58 @@ +package me.totalfreedom.fossil.reactions; + +import me.totalfreedom.display.BossBarDisplay; +import me.totalfreedom.economy.EconomicEntity; +import me.totalfreedom.shop.Reaction; +import me.totalfreedom.shop.ReactionType; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.bossbar.BossBar; + +import java.util.SplittableRandom; +import java.util.function.Consumer; + +/** + * Represents a single chat reaction that can be performed by a player. + */ +public final class CopyCatReaction extends Reaction +{ + private final long reward; + + public CopyCatReaction(final long reward) + { + super(ReactionType.COPYCAT); + this.reward = reward; + } + + @Override + public long getReward() + { + return reward; + } + + @Override + public void onReact(final Consumer entity) + { + entity.accept(null); + } + + @Override + public void display(final Audience audience) + { + final BossBar bossBar = BossBarDisplay.builder().setName(getRandomCharacterString()) + .setProgress(0.0F) + .build(); + } + + public String getRandomCharacterString() { + final SplittableRandom random = new SplittableRandom(); + final StringBuilder sb = new StringBuilder(10); + + final String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + for (int i = 0; i < 10; i++) { + sb.append(chars.charAt(random.nextInt(chars.length()))); + } + + return sb.toString(); + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/api/Context.java b/Patchwork/src/main/java/me/totalfreedom/api/Context.java index e4e7731..321cca6 100644 --- a/Patchwork/src/main/java/me/totalfreedom/api/Context.java +++ b/Patchwork/src/main/java/me/totalfreedom/api/Context.java @@ -1,5 +1,6 @@ package me.totalfreedom.api; +import me.totalfreedom.provider.ContextProvider; import net.kyori.adventure.text.Component; import org.bukkit.Location; import org.bukkit.World; @@ -13,16 +14,40 @@ import org.jetbrains.annotations.Nullable; import java.util.function.Function; +/** + * Represents an object context. This class is a simple generic type wrapper that can be used to ensure data types. This + * class is also used to provide a simple way to map data types. + * + * @param The type of the context. + * @see ContextProvider + */ @FunctionalInterface public interface Context { + /** + * Maps the context to another context. + * + * @param mapper The mapper function. + * @param The type of the mapped context. + * @return The mapped context. + */ default Context map(@NotNull final Function mapper) { return () -> mapper.apply(get()); } + /** + * Gets the context. + * + * @return The context. + */ T get(); + /** + * Gets the context as a string. + * + * @return The context as a string. + */ default @Nullable String asString() { if (get() instanceof String string) @@ -34,6 +59,11 @@ public interface Context } } + /** + * Gets the context as a boolean. + * + * @return The context as a boolean. + */ default @Nullable Boolean asBoolean() { if (get() instanceof Boolean bool) @@ -45,6 +75,9 @@ public interface Context } } + /** + * @return The context as a {@link Double}. + */ default @Nullable Double asDouble() { if (get() instanceof Double doub) @@ -56,6 +89,9 @@ public interface Context } } + /** + * @return The context as a {@link Integer}. + */ default @Nullable Integer asInt() { if (get() instanceof Integer integer) @@ -67,6 +103,9 @@ public interface Context } } + /** + * @return The context as a {@link Byte}. + */ default @Nullable Long asLong() { if (get() instanceof Long longg) @@ -78,6 +117,9 @@ public interface Context } } + /** + * @return The context as a {@link Float}. + */ default @Nullable Float asFloat() { if (get() instanceof Float floatt) @@ -89,6 +131,9 @@ public interface Context } } + /** + * @return The context as a {@link Player}. + */ default @Nullable Player asPlayer() { if (get() instanceof Player player) @@ -100,6 +145,9 @@ public interface Context } } + /** + * @return The context as a {@link CommandSender}. + */ default @Nullable CommandSender asCommandSender() { if (get() instanceof CommandSender commandSender) @@ -111,11 +159,19 @@ public interface Context } } + /** + * This is the same as calling {@link #get()} and then calling {@link Object#toString()} on the result. + * + * @return The context as a {@link String} literal. + */ default @NotNull String literal() { return get().toString(); } + /** + * @return The context as a {@link World}. + */ default @Nullable World asWorld() { if (get() instanceof World world) @@ -127,6 +183,9 @@ public interface Context } } + /** + * @return The context as a {@link Location}. + */ default @Nullable Location asLocation() { if (get() instanceof Location location) @@ -138,6 +197,9 @@ public interface Context } } + /** + * @return The context as a {@link LivingEntity}. + */ default @Nullable LivingEntity asLivingEntity() { if (get() instanceof LivingEntity livingEntity) @@ -149,6 +211,9 @@ public interface Context } } + /** + * @return The context as a {@link Component}. + */ default @Nullable Component asComponent() { if (get() instanceof Component component) @@ -160,6 +225,9 @@ public interface Context } } + /** + * @return The context as a {@link Projectile}. + */ default @Nullable Projectile asProjectile() { if (get() instanceof Projectile projectile) @@ -171,6 +239,9 @@ public interface Context } } + /** + * @return The context as an {@link Action}. + */ default @Nullable Action asAction() { if (get() instanceof Action action) @@ -182,6 +253,22 @@ public interface Context } } + /** + * Gets the context as a custom class. This will cast the object to the class if it is an instance of it. + *
+ * Typically, Context objects are useful when used to collect unknown data and then cast it to a known type. + *
+ * In the case where we know what the data should be but the compiler or the runtime does not, the object is wrapped + * in a Context which then exposes multiple methods to get the data as one of the known types. + *

+ * For example, if we have a Context<Object> and we already know that the wrapped object should be of type X, + * we can use X.class on this method to retrieve the actual object. That is, to say, if there is not + * already a predefined method to get the object as the type we want. + * + * @param clazz + * @param + * @return + */ default @Nullable U asCustom(Class clazz) { if (clazz.isInstance(get())) diff --git a/Patchwork/src/main/java/me/totalfreedom/api/Interpolator.java b/Patchwork/src/main/java/me/totalfreedom/api/Interpolator.java index 7e71edc..0a6c598 100644 --- a/Patchwork/src/main/java/me/totalfreedom/api/Interpolator.java +++ b/Patchwork/src/main/java/me/totalfreedom/api/Interpolator.java @@ -1,7 +1,21 @@ package me.totalfreedom.api; +/** + * Interpolates a range of values and returns the results in a {@link Double} array. + *
+ * This is a functional interface, to allow for lambda expressions, but also for anonymous custom interpolation + * implementations. + */ @FunctionalInterface public interface Interpolator { + /** + * Interpolates a range of values and returns the results in a {@link Double} array. + * + * @param from The starting value. + * @param to The ending value. + * @param max The number of values to interpolate. + * @return The interpolated values. + */ double[] interpolate(final double from, final double to, final int max); } diff --git a/Patchwork/src/main/java/me/totalfreedom/api/Serializable.java b/Patchwork/src/main/java/me/totalfreedom/api/Serializable.java index 499841b..41ab562 100644 --- a/Patchwork/src/main/java/me/totalfreedom/api/Serializable.java +++ b/Patchwork/src/main/java/me/totalfreedom/api/Serializable.java @@ -1,5 +1,12 @@ package me.totalfreedom.api; +/** + * This interface represents a Serializable object. + * Objects which require custom serialization and cannot simply override or call + * the default {@link Object#toString()} method should implement this interface. + * + * @param The type of object to serialize + */ public interface Serializable { /** @@ -11,5 +18,11 @@ public interface Serializable */ String serialize(T object); - T deserialize(Context... contexts); + /** + * Deserialize an object from a Serialized string.. + * @param serializedObject The serialized object + * @return The deserialized object + */ + + T deserialize(String serializedObject); } diff --git a/Patchwork/src/main/java/me/totalfreedom/audience/MutableAudienceForwarder.java b/Patchwork/src/main/java/me/totalfreedom/audience/MutableAudienceForwarder.java index 4048c49..f725d73 100644 --- a/Patchwork/src/main/java/me/totalfreedom/audience/MutableAudienceForwarder.java +++ b/Patchwork/src/main/java/me/totalfreedom/audience/MutableAudienceForwarder.java @@ -19,16 +19,25 @@ 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. */ // TODO: Work on thread-safety (or thread-safe alternative) public class MutableAudienceForwarder implements Audience { + /** + * The audiences that this forwards to. + */ private final Set audiences = new HashSet<>(); + /** + * Creates a new {@link MutableAudienceForwarder} with the given audiences. + * + * @param audiences The audiences to forward to. + * @return The new {@link MutableAudienceForwarder}. + */ public static MutableAudienceForwarder from(final Audience... audiences) { final MutableAudienceForwarder audienceForwarder = new MutableAudienceForwarder(); @@ -41,6 +50,11 @@ public class MutableAudienceForwarder implements Audience return audienceForwarder; } + /** + * Adds an audience to this forwarder. + * + * @param audience The audience to add. + */ public void addAudience(final Audience audience) { if (audiences.contains(audience) || audience == this /* Protect against honest self-referential calls */) @@ -51,12 +65,23 @@ public class MutableAudienceForwarder implements Audience audiences.add(audience); } + /** + * Removes an audience from this forwarder. + * + * @param audience The audience to remove. + * @return Whether the audience was removed. + */ public boolean removeAudience(final Audience audience) { return audiences.remove(audience); } - + /** + * Filters the audiences in the stream by the given predicate. + * + * @param filter a filter that determines if an audience should be included + * @return The first Audience found that matches the filter. + */ @Override public @NotNull Audience filterAudience(@NotNull final Predicate filter) { @@ -66,52 +91,103 @@ public class MutableAudienceForwarder implements Audience .orElseThrow(); } + /** + * Applies a consumer to each audience in the stream. + * + * @param action the action to apply. + */ @Override public void forEachAudience(@NotNull final Consumer action) { audiences.forEach(action); } + /** + * Sends a {@link ComponentLike} to every audience within the stream. + * + * @param message The message to send. + * @see Audience#sendMessage(ComponentLike) + * @see #forEachAudience(Consumer) + */ @Override public void sendMessage(@NotNull final ComponentLike message) { - audiences.forEach(a -> a.sendMessage(message)); + forEachAudience(a -> a.sendMessage(message)); } + /** + * Sends a {@link Component} to every audience within the stream. + * + * @param message The message to send + * @see Audience#sendMessage(Component) + * @see #forEachAudience(Consumer) + */ @Override public void sendMessage(@NotNull final Component message) { - audiences.forEach(a -> a.sendMessage(message)); + forEachAudience(a -> a.sendMessage(message)); } + /** + * Sends a {@link SignedMessage} to every audience within the stream. + * + * @param message the component content of the message + * @param boundChatType the bound chat type of the message + * @see Audience#sendMessage(Component, ChatType.Bound) + * @see #forEachAudience(Consumer) + */ @Override public void sendMessage(@NotNull final Component message, final ChatType.@NotNull Bound boundChatType) { - audiences.forEach(a -> a.sendMessage(message, boundChatType)); + forEachAudience(a -> a.sendMessage(message, boundChatType)); } + /** + * Sends a {@link SignedMessage} to every audience within the stream. + * + * @param message the component content of the message + * @param boundChatType the bound chat type of the message + * @see Audience#sendMessage(ComponentLike, ChatType.Bound) + * @see #forEachAudience(Consumer) + */ @Override public void sendMessage(@NotNull final ComponentLike message, final ChatType.@NotNull Bound boundChatType) { - audiences.forEach(a -> a.sendMessage(message, boundChatType)); + forEachAudience(a -> a.sendMessage(message, boundChatType)); } + /** + * Sends a {@link SignedMessage} to every audience within the stream. + * + * @param signedMessage the signed message data to send + * @param boundChatType the bound chat type of the message + */ @Override public void sendMessage(@NotNull final SignedMessage signedMessage, final ChatType.@NotNull Bound boundChatType) { - audiences.forEach(a -> a.sendMessage(signedMessage, boundChatType)); + forEachAudience(a -> a.sendMessage(signedMessage, boundChatType)); } + /** + * Deletes a signed message from the audiences chat. + * + * @param signedMessage the message to delete + */ @Override public void deleteMessage(@NotNull final SignedMessage signedMessage) { - audiences.forEach(a -> a.deleteMessage(signedMessage)); + forEachAudience(a -> a.deleteMessage(signedMessage)); } + /** + * Deletes a signed message from the audiences chat using the provided chat signature. + * + * @param signature the signature associated with the message to delete. + */ @Override public void deleteMessage(final SignedMessage.@NotNull Signature signature) { - audiences.forEach(a -> a.deleteMessage(signature)); + forEachAudience(a -> a.deleteMessage(signature)); } // The methods below here will (probably) never be used, however it's good to keep them for completeness' sake. @@ -119,127 +195,127 @@ public class MutableAudienceForwarder implements Audience @Override public void sendActionBar(@NotNull final ComponentLike message) { - audiences.forEach(a -> a.sendActionBar(message)); + forEachAudience(a -> a.sendActionBar(message)); } @Override public void sendActionBar(@NotNull final Component message) { - audiences.forEach(a -> a.sendActionBar(message)); + forEachAudience(a -> a.sendActionBar(message)); } @Override public void sendPlayerListHeader(@NotNull final ComponentLike header) { - audiences.forEach(a -> a.sendPlayerListHeader(header)); + forEachAudience(a -> a.sendPlayerListHeader(header)); } @Override public void sendPlayerListHeader(@NotNull final Component header) { - audiences.forEach(a -> a.sendPlayerListHeader(header)); + forEachAudience(a -> a.sendPlayerListHeader(header)); } @Override public void sendPlayerListFooter(@NotNull final ComponentLike footer) { - audiences.forEach(a -> a.sendPlayerListFooter(footer)); + forEachAudience(a -> a.sendPlayerListFooter(footer)); } @Override public void sendPlayerListFooter(@NotNull final Component footer) { - audiences.forEach(a -> a.sendPlayerListFooter(footer)); + forEachAudience(a -> a.sendPlayerListFooter(footer)); } @Override public void sendPlayerListHeaderAndFooter(@NotNull final ComponentLike header, @NotNull final ComponentLike footer) { - audiences.forEach(a -> a.sendPlayerListHeaderAndFooter(header, footer)); + forEachAudience(a -> a.sendPlayerListHeaderAndFooter(header, footer)); } @Override public void sendPlayerListHeaderAndFooter(@NotNull final Component header, @NotNull final Component footer) { - audiences.forEach(a -> a.sendPlayerListHeaderAndFooter(header, footer)); + forEachAudience(a -> a.sendPlayerListHeaderAndFooter(header, footer)); } @Override public void showTitle(@NotNull final Title title) { - audiences.forEach(a -> a.showTitle(title)); + forEachAudience(a -> a.showTitle(title)); } @Override public void sendTitlePart(@NotNull final TitlePart part, @NotNull final T value) { - audiences.forEach(a -> a.sendTitlePart(part, value)); + forEachAudience(a -> a.sendTitlePart(part, value)); } @Override public void clearTitle() { - audiences.forEach(Audience::clearTitle); + forEachAudience(Audience::clearTitle); } @Override public void resetTitle() { - audiences.forEach(Audience::resetTitle); + forEachAudience(Audience::resetTitle); } @Override public void showBossBar(@NotNull final BossBar bar) { - audiences.forEach(a -> a.showBossBar(bar)); + forEachAudience(a -> a.showBossBar(bar)); } @Override public void hideBossBar(@NotNull final BossBar bar) { - audiences.forEach(a -> a.hideBossBar(bar)); + forEachAudience(a -> a.hideBossBar(bar)); } @Override public void playSound(@NotNull final Sound sound) { - audiences.forEach(a -> a.playSound(sound)); + forEachAudience(a -> a.playSound(sound)); } @Override public void playSound(@NotNull final Sound sound, final double x, final double y, final double z) { - audiences.forEach(a -> a.playSound(sound, x, y, z)); + forEachAudience(a -> a.playSound(sound, x, y, z)); } @Override public void playSound(@NotNull final Sound sound, final Sound.@NotNull Emitter emitter) { - audiences.forEach(a -> a.playSound(sound, emitter)); + forEachAudience(a -> a.playSound(sound, emitter)); } @Override public void stopSound(@NotNull final Sound sound) { - audiences.forEach(a -> a.stopSound(sound)); + forEachAudience(a -> a.stopSound(sound)); } @Override public void stopSound(@NotNull final SoundStop stop) { - audiences.forEach(a -> a.stopSound(stop)); + forEachAudience(a -> a.stopSound(stop)); } @Override public void openBook(final Book.@NotNull Builder book) { - audiences.forEach(a -> a.openBook(book)); + forEachAudience(a -> a.openBook(book)); } @Override public void openBook(@NotNull final Book book) { - audiences.forEach(a -> a.openBook(book)); + forEachAudience(a -> a.openBook(book)); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java index b75d402..911086e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java @@ -6,12 +6,30 @@ import me.totalfreedom.service.SubscriptionProvider; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; +/** + * The base class for Patchwork. + */ public class CommonsBase extends JavaPlugin { + /** + * The {@link EventBus} for this plugin. + */ private final EventBus eventBus = new EventBus(this); + /** + * The {@link Registration} object for this plugin. + */ private final Registration registration = new Registration(); + /** + * The {@link FreedomExecutor} for this plugin. + */ private final FreedomExecutor executor = new FreedomExecutor(); + /** + * Provides this plugin instance through a safe static method. + * This is effectively the same thing as using {@link JavaPlugin#getPlugin(Class)} + * + * @return the plugin instance + */ public static CommonsBase getInstance() { return JavaPlugin.getPlugin(CommonsBase.class); @@ -22,34 +40,51 @@ public class CommonsBase extends JavaPlugin { Bukkit.getScheduler() .runTaskLater(this, () -> getRegistrations() - .getServiceRegistry() - .stopAllServices(), 1L); + .getServiceTaskRegistry() + .stopAllServices(), 1L); - getRegistrations().getServiceRegistry() + getRegistrations().getServiceTaskRegistry() .unregisterService(EventBus.class); } @Override public void onEnable() { - getRegistrations().getServiceRegistry() + getRegistrations().getServiceTaskRegistry() .registerService(SubscriptionProvider.asyncService(this, eventBus)); getExecutor().getSync() .execute(() -> getRegistrations() - .getServiceRegistry() - .startAllServices()); + .getServiceTaskRegistry() + .startAllServices()); } + /** + * Gets the {@link FreedomExecutor} for this plugin. + * + * @return the {@link FreedomExecutor} + */ public FreedomExecutor getExecutor() { return executor; } + /** + * Get's the Registration object for this plugin. This object contains every registry class for the various features + * provided by this plugin. + * + * @return the Registration object + */ public Registration getRegistrations() { return registration; } + /** + * Gets the {@link EventBus} for this plugin. The EventBus is used to register and listen to custom events provided + * by Freedom Network Suite. + * + * @return the {@link EventBus} + */ 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 e23609a..1f5cf6c 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/Registration.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/Registration.java @@ -7,16 +7,44 @@ import me.totalfreedom.data.ModuleRegistry; import me.totalfreedom.data.ServiceTaskRegistry; import me.totalfreedom.data.UserRegistry; +/** + * This class is a holder for each registry in the data package. + *
+ * Registries such as {@link ModuleRegistry} and {@link ServiceTaskRegistry} + * can be found as final objects in this class. These registries should only ever be accessed through + * the single Registration object in CommonsBase using {@link CommonsBase#getRegistrations()} + */ public class Registration { + /** + * The {@link EventRegistry} + */ private final EventRegistry eventRegistry; + /** + * The {@link UserRegistry} + */ private final UserRegistry userRegistry; + /** + * The {@link ServiceTaskRegistry} + */ private final ServiceTaskRegistry serviceTaskRegistry; + /** + * The {@link ModuleRegistry} + */ private final ModuleRegistry moduleRegistry; + /** + * The {@link GroupRegistry} + */ private final GroupRegistry groupRegistry; + /** + * The {@link ConfigRegistry} + */ private final ConfigRegistry configRegistry; - public Registration() + /** + * Constructs a new Registration object and initializes all registries. + */ + Registration() { this.eventRegistry = new EventRegistry(); this.userRegistry = new UserRegistry(); @@ -26,31 +54,49 @@ public class Registration this.configRegistry = new ConfigRegistry(); } + /** + * @return The {@link ModuleRegistry} + */ public ModuleRegistry getModuleRegistry() { return moduleRegistry; } + /** + * @return The {@link EventRegistry} + */ public EventRegistry getEventRegistry() { return eventRegistry; } + /** + * @return The {@link UserRegistry} + */ public UserRegistry getUserRegistry() { return userRegistry; } - public ServiceTaskRegistry getServiceRegistry() + /** + * @return The {@link ServiceTaskRegistry} + */ + public ServiceTaskRegistry getServiceTaskRegistry() { return serviceTaskRegistry; } + /** + * @return The {@link GroupRegistry} + */ public GroupRegistry getGroupRegistry() { return groupRegistry; } + /** + * @return The {@link ConfigRegistry} + */ 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 index a888edb..b6d6276 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java @@ -22,7 +22,23 @@ import java.util.Arrays; import java.util.List; import java.util.Set; -public class BukkitDelegate extends Command implements PluginIdentifiableCommand +/** + * This class is acts as a delegate between our custom command implementation and the Bukkit API. + *
+ * This class is not meant to be used directly, and is only public to allow for the Bukkit API to access it. + * As a result, this file will remain undocumented. + * + *
+ * This class is not thread-safe. + *
+ * This class is not meant to be extended. + *
+ * This class is not meant to be instantiated. + *
+ * This class is not meant to be used outside Patchwork. + *
+ */ +public final class BukkitDelegate extends Command implements PluginIdentifiableCommand { private final JavaPlugin plugin; private final Commander command; @@ -50,8 +66,8 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand @Override public boolean execute(@NotNull final CommandSender sender, - @NotNull final String commandLabel, - @NotNull final String[] args) + @NotNull final String commandLabel, + @NotNull final String[] args) { if (sender instanceof ConsoleCommandSender && noConsole) { @@ -87,8 +103,7 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand { command.getBaseMethod() .invoke(command, sender); - } - catch (Exception ex) + } catch (Exception ex) { FreedomLogger.getLogger("Patchwork") .error(ex); @@ -101,8 +116,8 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand } private void processSubCommands(final @NotNull String @NotNull [] args, - final CommandSender sender, final ContextProvider provider, - final Subcommand node) + final CommandSender sender, final ContextProvider provider, + final Subcommand node) { final Class[] argTypes = node.args(); if (argTypes.length != args.length) @@ -126,8 +141,7 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand command.getSubcommands() .get(node) .invoke(command, sender, objects); - } - catch (Exception ex) + } catch (Exception ex) { FreedomLogger.getLogger("Patchwork") .error(ex); @@ -159,16 +173,16 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand .map(World::getName) .toList()); case "%number%" -> results.addAll(List.of( - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9")); + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9")); case "%location%" -> results.add("world,x,y,z"); default -> results.add(p); } diff --git a/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java b/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java index c2714bf..34c754d 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java @@ -1,17 +1,39 @@ package me.totalfreedom.command; import org.bukkit.Bukkit; +import org.bukkit.command.CommandMap; import org.bukkit.plugin.java.JavaPlugin; +/** + * Handles the registration of commands. + * The plugin which initializes this class should be the plugin that is registering the commands. + */ public class CommandHandler { + /** + * The plugin that this command handler is registered to. + *
+ * This should be the plugin instance which is trying to register the commands. + */ private final JavaPlugin plugin; + /** + * Creates a new command handler. + * + * @param plugin The plugin that this command handler is registered to. + */ public CommandHandler(final JavaPlugin plugin) { this.plugin = plugin; } + /** + * Registers a command. This method will automatically delegate the command information to the Bukkit API and + * register with the {@link CommandMap}. + * + * @param command The command to register. + * @param The type of the command. + */ public void registerCommand(final T command) { final BukkitDelegate delegate = new BukkitDelegate(command); diff --git a/Patchwork/src/main/java/me/totalfreedom/command/Commander.java b/Patchwork/src/main/java/me/totalfreedom/command/Commander.java index 62f6d56..2830a84 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/Commander.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/Commander.java @@ -17,15 +17,60 @@ import java.util.Map; import java.util.Set; import java.util.stream.Stream; +/** + * This is the base command class which should be extended when creating a new command. Commands must be annotated with + * the {@link Info} and {@link Permissive} annotations in order to be properly registered with the + * {@link CommandHandler}. + *

+ * One single method can be annotated with the {@link Base} annotation to specify that method should be called when the + * command is executed without any arguments. + *
+ * You are allowed to have as many methods as you want which are annotated with the {@link Subcommand} annotation. These + * methods will be called when the command is executed with the specified subcommand. + *
+ * You are also allowed to use multiple {@link Completion} annotations per method to define multiple tab completions for + * a single subcommand. This would be useful in the case where you would like to include specific completion cases, but + * also support basic String completion cases. + *
+ * When creating {@link Completion} annotations, you only need to register arguments a single time per class. For more + * information, see {@link Subcommand}. + */ public abstract class Commander { + /** + * The plugin which owns this command. + */ private final JavaPlugin plugin; + /** + * The {@link Info} annotation for this command. + */ private final Info info; + /** + * The {@link Permissive} annotation for this command. + */ private final Permissive perms; + /** + * A map of all subcommands and their related methods for this command. + */ private final Map subcommands; + /** + * A set of all {@link Completion} annotations for this command. + */ private final Set completions; + /** + * The method which should be called when the command is executed without any arguments. + */ private final Method baseMethod; + /** + * Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the + * command. + *

+ * This constructor will automatically register all subcommands and completions for this command. It will also + * automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations. + * + * @param plugin The plugin which contains this command. + */ protected Commander(final @NotNull JavaPlugin plugin) { this.info = this.getClass() @@ -44,7 +89,7 @@ public abstract class Commander .filter(m -> m.isAnnotationPresent(Base.class)) .findFirst() .orElseThrow(() -> new RuntimeException( - "Base annotation present but no method found.")); + "Base annotation present but no method found.")); this.baseMethod = method; } else @@ -55,14 +100,17 @@ public abstract class Commander registerAnnotations(); } + /** + * Registers all subcommands and completions for this command. + */ private void registerAnnotations() { Stream.of(this.getClass() .getDeclaredMethods()) .filter(method -> method.isAnnotationPresent(Subcommand.class)) .forEach(method -> this.subcommands.put( - method.getDeclaredAnnotation(Subcommand.class), - method)); + method.getDeclaredAnnotation(Subcommand.class), + method)); List.of(this.getClass() .getDeclaredAnnotationsByType(Completion.class)) @@ -70,36 +118,66 @@ public abstract class Commander .forEach(completions::add); } + /** + * Gets the method which should be called when the command is executed without any arguments. + *
+ * This method will return null if the command does not have a base method. + * + * @return The base method for this command, or null if the command does not have a base method. + */ @Nullable public Method getBaseMethod() { return baseMethod; } + /** + * Gets the {@link Info} annotation for this command. + *
+ * This method will never return null as this annotation is required for the command to be registered. + * + * @return The {@link Info} annotation for this command. + */ @NotNull Info getInfo() { return this.info; } + /** + * Gets the {@link Permissive} annotation for this command. + *
+ * This method will never return null as this annotation is required for the command to be registered. + * + * @return The {@link Permissive} annotation for this command. + */ @NotNull Permissive getPerms() { return this.perms; } + /** + * @return The plugin which owns this command. + */ @NotNull public JavaPlugin getPlugin() { return this.plugin; } + /** + * @return A map of all subcommands and their related methods for this command. + */ @NotNull Map getSubcommands() { return this.subcommands; } + /** + * @return A set of all {@link Completion} annotations for this command. + */ @Nullable Set getCompletions() { 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 253fc86..d32efa4 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completion.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completion.java @@ -6,12 +6,26 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * Represents a tab completion for a command. + *

+ * This will register at class level, and does not retain method information. As a result, you only need to register the + * arguments a single time, and it will always be used in tab completions. + */ @Target(ElementType.METHOD) @Repeatable(Completions.class) @Retention(RetentionPolicy.RUNTIME) public @interface Completion { + /** + * An array of possible arguments for this particular index, represented by {@link #index()}. + * + * @return An array of possible arguments for tab completion. + */ String[] args(); + /** + * @return The index in which these arguments should be shown. + */ int index(); } diff --git a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completions.java b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completions.java index 632156d..694804e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completions.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Completions.java @@ -5,9 +5,18 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * A marker interface which represents a holder for multiple {@link Completion} annotations. + *
+ * This interface is NOT intended for implementation and should + * NOT be used. + */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Completions { + /** + * @return The {@link Completion} annotations. + */ Completion[] value(); } diff --git a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Info.java b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Info.java index 478a5ad..fd90d82 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Info.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Info.java @@ -3,14 +3,40 @@ package me.totalfreedom.command.annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +/** + * This interface holds the information for each command. This annotation defines the command's name, description, + * usage, and aliases. Commands must have this annotation present to be registered with the handler. + */ @Retention(RetentionPolicy.RUNTIME) public @interface Info { + /** + * Technically, this is the only required value you must supply yourself. + * However, it is HIGHLY recommended you supply the other optional values as well, + * for better customization of your command. + * + * @return The command's name. + */ String name(); + /** + * By default, this is set to "This is the default command description." + * + * @return The command's description. + */ String description() default "This is the default command description."; + /** + * By default, this is set to "/<command>" + * + * @return The command's usage. + */ String usage() default "/"; + /** + * By default, this returns an empty array. + * + * @return The command's aliases. + */ String[] aliases() default {}; } diff --git a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Permissive.java b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Permissive.java index 470569d..90c5739 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Permissive.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Permissive.java @@ -3,12 +3,31 @@ package me.totalfreedom.command.annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +/** + * This annotation holds the permission information for each command. This annotation defines the command's permission, + * whether it is only for players, and the message to send if the sender does not have permission to use the command. + *

+ * Classes MUST have this annotation present to be registered with the handler. + */ @Retention(RetentionPolicy.RUNTIME) public @interface Permissive { + /** + * @return The command's permission. + */ String perm(); + /** + * By default, this is set to false. + * + * @return True if the command is only for players, false otherwise. + */ boolean onlyPlayers() default false; + /** + * By default, this is set to "You do not have permission to use this command." + * + * @return The message to send if the sender does not have permission to use the command. + */ String noPerms() default "You do not have permission to use this command."; } 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 3010844..9a3b8c7 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Subcommand.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Subcommand.java @@ -1,15 +1,41 @@ package me.totalfreedom.command.annotation; +import me.totalfreedom.command.CommandHandler; +import me.totalfreedom.provider.ContextProvider; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * This annotation should be used to mark methods as subcommand methods. + * Subcommand methods can have custom arguments (current supported arguments can be found in the {@link ContextProvider}), + * and can also have a custom permission. These subcommands can also be annotated with {@link Completions} to provide + * tab completions for the subcommand. The subcommand method must be public, and must be in a class that is registered + * with the {@link CommandHandler}. + *
+ * Tab completions with the {@link Completions} annotation are only supported for subcommands. When registering + * completions, you only need to define the completion arguments a single time. If there are other methods which + * function as optional additional arguments for the subcommand, the previously registered arguments will still be + * present when the user does their tab completion. + *
+ * For example, if you have a subcommand method with the arguments {@code (Player, String)}, and another method which + * has the arguments {@code (Player, String, String)}, the tab completions for the second method will still have the + * {@code Player} and {@code String} arguments registered from the first method. You will only need to provide a + * {@link Completion} for the additional 3rd argument. + */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Subcommand { + /** + * @return The permission to use when executing this subcommand. + */ String permission(); + /** + * @return The arguments, as classes, to use when registering this subcommand. + */ Class[] args() default {}; } diff --git a/Patchwork/src/main/java/me/totalfreedom/config/Configuration.java b/Patchwork/src/main/java/me/totalfreedom/config/Configuration.java index 6b551c1..728ead2 100644 --- a/Patchwork/src/main/java/me/totalfreedom/config/Configuration.java +++ b/Patchwork/src/main/java/me/totalfreedom/config/Configuration.java @@ -1,36 +1,132 @@ package me.totalfreedom.config; +import me.totalfreedom.api.Context; +import me.totalfreedom.provider.ContextProvider; + import java.io.File; import java.io.IOException; import java.util.List; +/** + * Represents a configuration file of any type. + */ public interface Configuration { + /** + * Saves the configuration to the file. + * + * @throws IOException If the operation cannot be completed. + */ void save() throws IOException; + /** + * Loads the configuration from the file. + * + * @throws IOException If the operation cannot be completed. + */ void load() throws IOException; + /** + * @return The name of the file. + */ String getFileName(); + /** + * @return The actual Configuration {@link File}. + */ File getConfigurationFile(); + /** + * Gets a String object from the associated path. + * + * @param path The path to get the String from. + * @return The String object. + */ String getString(String path); + /** + * Gets a Boolean object from the associated path. + * + * @param path The path to get the Boolean from. + * @return The Boolean object. + */ Boolean getBoolean(String path); + /** + * Gets a List object from the associated path. This method will use {@link Context}s and the + * {@link ContextProvider} to get the object types in the list. If the objects cannot be inferred, the method will + * return a list of generic {@link Object}s. + * + * @param path The path to get the List from. + * @param The type of the objects in the list. + * @return The List object. + */ List getList(String path); + /** + * Gets a List object from the associated path. The List that is returned will be the String values which are stored + * within the configuration file at the given path. + * + * @param path The path to get the List from. + * @return The List object. + */ List getStringList(String path); + /** + * Gets an Integer from the associated path. + * + * @param path The path to get the Integer from. + * @return The Integer object. + */ Integer getInt(String path); + /** + * Gets a Long from the associated path. + * + * @param path The path to get the Long from. + * @return The Long object. + */ Long getLong(String path); + /** + * Gets a Double from the associated path. + * + * @param path The path to get the Double from. + * @return The Double object. + */ Double getDouble(String path); + /** + * Sets the value at the given path to the given value. + * + * @param path The path to set the value at. + * @param value The value to set. + * @param The type of the value. + */ void set(String path, T value); - T get(String path, Class type); + /** + * Gets the value at the given path as the given type. + *

+ * This method will use {@link Context}s and the {@link ContextProvider} to get the object type. If the object type + * cannot be inferred, the method will return a generic {@link Object}. + * + * @param path The path to get the value from. + * @param The type of the value. + * @return The value at the given path. + */ + T get(String path); - T getOrDefault(String path, Class type, T fallback); + /** + * Gets the value at the given path as the given type. + *

+ * This method will use {@link Context}s and the {@link ContextProvider} to get the object type. If the object type + * cannot be inferred, the method will return the given fallback value. + * + * @param path The path to get the value from. + * @param fallback The fallback value to return if the value at the given path is null. + * @param The type of the value. + * @return The value at the given path. + */ + T getOrDefault(String path, T fallback); } \ No newline at end of file diff --git a/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java index 2c54b02..8f6b9e9 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java @@ -5,20 +5,40 @@ import me.totalfreedom.config.Configuration; import java.util.HashMap; import java.util.Map; +/** + * A registry for all the configurations. + */ public class ConfigRegistry { + /** + * A map of all the configurations. + */ private final Map configurationList = new HashMap<>(); + /** + * Registers a configuration. + * @param name The name of the configuration. + * @param configuration The configuration. + */ public void register(final String name, final Configuration configuration) { configurationList.put(name, configuration); } + /** + * Unregisters a configuration. + * @param name The name of the configuration. + */ public void unregister(final String name) { configurationList.remove(name); } + /** + * Gets a configuration. + * @param name The name of the configuration. + * @return The configuration. + */ public Configuration getConfiguration(final String name) { return configurationList.get(name); diff --git a/Patchwork/src/main/java/me/totalfreedom/data/EventRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/EventRegistry.java index b98d6cb..99f7271 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/EventRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/EventRegistry.java @@ -6,25 +6,49 @@ import me.totalfreedom.provider.EventProvider; import java.util.ArrayList; import java.util.List; +/** + * A registry for {@link FEvent}s. + */ public class EventRegistry { + /** + * The list of events. + */ private final List events; + /** + * Creates a new event registry. + */ public EventRegistry() { this.events = new ArrayList<>(); } + /** + * Registers an event. + * @param event The event to register. + */ public void register(final FEvent event) { this.events.add(event); } + /** + * Unregisters an event. + * @param event The event to unregister. + */ public void unregister(final FEvent event) { this.events.remove(event); } + /** + * Gets an {@link EventProvider} for the specified event class which contains the actual {@link FEvent} instance. + * + * @param clazz The event class. + * @return The event provider. + * @param The event type. + */ public EventProvider getEvent(final Class clazz) { for (final FEvent event : this.events) diff --git a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java index 12e6c57..96ae921 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java @@ -6,25 +6,49 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import java.util.ArrayList; import java.util.List; +/** + * A registry for {@link Group}s. + */ public class GroupRegistry { + /** + * The list of groups. + */ private final List groups; + /** + * Creates a new group registry. + */ public GroupRegistry() { this.groups = new ArrayList<>(); } + /** + * Registers a group. + * @param group The group to register. + * @return {@code true} if the group was registered, {@code false} otherwise. + */ public boolean registerGroup(final Group group) { return groups.add(group); } + /** + * Unregisters a group. + * @param group The group to unregister. + * @return {@code true} if the group was unregistered, {@code false} otherwise. + */ public boolean unregisterGroup(final Group group) { return groups.remove(group); } + /** + * Gets a group by name. + * @param name The name of the group. + * @return The group, or {@code null} if no group was found. + */ public Group getGroup(final String name) { final PlainTextComponentSerializer s = PlainTextComponentSerializer.plainText(); @@ -39,6 +63,9 @@ public class GroupRegistry return null; } + /** + * @return The list of groups. + */ 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 34f024a..cdc26c0 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/ModuleRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/ModuleRegistry.java @@ -6,15 +6,29 @@ import org.bukkit.plugin.java.JavaPlugin; import java.util.ArrayList; import java.util.List; +/** + * A registry for modules. + */ public class ModuleRegistry { + /** + * The list of modules. + */ private final List plugins; + /** + * Creates a new module registry. + */ public ModuleRegistry() { this.plugins = new ArrayList<>(); } + /** + * Adds a module to the registry. + * + * @param plugin The module to add. + */ public void addModule(final JavaPlugin plugin) { if (this.plugins.contains(plugin)) @@ -24,19 +38,30 @@ public class ModuleRegistry this.plugins.add(plugin); } + /** + * Removes a module from the registry. + * + * @param plugin The module to remove. + */ public void removeModule(final JavaPlugin plugin) { this.plugins.remove(plugin); } - @SuppressWarnings("unchecked") - public ModuleProvider getModule(final Class clazz) + /** + * Gets a module from the registry wrapped in a {@link ModuleProvider}. + * + * @param clazz The class of the module. + * @param The type of the module. + * @return The module. + */ + public ModuleProvider getProvider(final Class clazz) { for (final JavaPlugin plugin : plugins) { if (clazz.isInstance(plugin)) { - return () -> (T) plugin; + return () -> clazz.cast(plugin); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java index b5f47e4..184e140 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java @@ -7,39 +7,91 @@ import org.bukkit.entity.Player; import java.util.HashMap; import java.util.Map; +/** + * A registry for {@link UserData} objects. + */ public class UserRegistry { + /** + * A map of {@link User} objects to {@link UserData} objects. + */ private final Map userDataMap; + /** + * Creates a new {@link UserRegistry}. + */ public UserRegistry() { this.userDataMap = new HashMap<>(); } + /** + * Gets the {@link UserData} object for the given {@link User}. + * + * @param user The {@link User} to get the {@link UserData} for. + * @return The {@link UserData} object for the given {@link User}. + */ public UserData getUserData(final User user) { return userDataMap.get(user); } - public UserData fromPlayer(final Player player) { + /** + * Gets the {@link UserData} object for the given {@link Player}. + */ + public UserData fromPlayer(final Player player) + { return userDataMap.entrySet() .stream() - .filter(entry -> entry.getKey().getUniqueId().equals(player.getUniqueId())) + .filter(entry -> entry.getKey() + .getUniqueId() + .equals(player.getUniqueId())) .findFirst() .map(Map.Entry::getValue) .orElse(null); } + /** + * Gets the {@link User} object for the given {@link Player}. + * + * @param player The {@link Player} to get the {@link User} for. + * @return The {@link User} object for the given {@link Player}. + */ + public User getUser(final Player player) + { + return userDataMap.entrySet() + .stream() + .filter(entry -> entry.getKey() + .getUniqueId() + .equals(player.getUniqueId())) + .findFirst() + .map(Map.Entry::getKey) + .orElse(null); + } + + /** + * Registers the given {@link User} and {@link UserData} objects. + * @param user The {@link User} to register. + * @param userData The {@link UserData} to register. + */ public void registerUserData(final User user, final UserData userData) { userDataMap.put(user, userData); } + /** + * Unregisters the given {@link User} and {@link UserData} objects. + * @param user The {@link User} to unregister. + */ public void unregisterUserData(final User user) { userDataMap.remove(user); } + /** + * Gets the map of {@link User} objects to {@link UserData} objects. + * @return The map of {@link User} objects to {@link UserData} objects. + */ public Map getUserDataMap() { return userDataMap; diff --git a/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java b/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java index 697f7eb..9baa4df 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/AbstractMenu.java @@ -15,14 +15,34 @@ import java.util.List; import java.util.Map; import java.util.UUID; +/** + * Represents a menu that can be opened by a player. + */ public abstract class AbstractMenu { + /** + * A map of all menus by their UUID. + */ private static final Map invByUUID = new HashMap<>(); + /** + * A map of all open menus by the player's UUID. + */ private static final Map openInvs = new HashMap<>(); private final Map actionMap; + /** + * The displayable that represents this menu. + */ private final Displayable displayable; + /** + * The UUID of the displayable that represents this menu. + */ private final UUID displayableUUID; + /** + * Creates a new menu with the specified size. + * + * @param size The size of the menu. + */ protected AbstractMenu(final int size) { actionMap = new HashMap<>(); @@ -32,26 +52,48 @@ public abstract class AbstractMenu invByUUID.put(getDisplayableUUID(), this); } - public UUID getDisplayableUUID() - { - return displayableUUID; - } - + /** + * @return A map of all menus by their UUID. + */ public static Map getInvByUUID() { return invByUUID; } + /** + * @return A map of all open menus by the player's UUID. + */ public static Map getOpenInvs() { return openInvs; } + /** + * @return The displayable UUID of this menu. + */ + public UUID getDisplayableUUID() + { + return displayableUUID; + } + + /** + * Sets the item at the specified slot. + * + * @param slot The slot to set the item at. + * @param stack The item to set. + */ public void setItem(final int slot, final @NotNull ItemStack stack) { setItem(slot, stack, null); } + /** + * Sets the item at the specified slot. + * + * @param slot The slot to set the item at. + * @param stack The item to set. + * @param action The action to perform when the item is clicked. + */ public void setItem(final int slot, final @NotNull ItemStack stack, final @Nullable ClickAction action) { getDisplayable().setItem(slot, stack); @@ -61,17 +103,28 @@ public abstract class AbstractMenu } } + /** + * @return The displayable that represents this menu. + */ public Displayable getDisplayable() { return displayable; } + /** + * Opens this menu for the specified player. + * + * @param player The player to open the menu for. + */ public void open(final @NotNull Player player) { player.openInventory(getDisplayable()); openInvs.put(player.getUniqueId(), getDisplayableUUID()); } + /** + * Deletes this menu. + */ public void delete() { Bukkit.getOnlinePlayers() @@ -87,24 +140,47 @@ public abstract class AbstractMenu invByUUID.remove(getDisplayableUUID()); } + /** + * Closes this menu for the specified player. + * + * @param player The player to close the menu for. + */ public void close(final @NotNull Player player) { player.closeInventory(); openInvs.remove(player.getUniqueId()); } + /** + * @return A map of all actions by their slot. + */ public Map getActions() { return actionMap; } + /** + * Creates a new item with the specified material and name. + * + * @param material The material of the item. + * @param name The name of the item. + * @return The created item. + */ public ItemStack newItem(final @NotNull Material material, final @NotNull Component name) { return this.newItem(material, name, new Component[0]); } + /** + * Creates a new item with the specified material, name, and lore. + * + * @param material The material of the item. + * @param name The name of the item. + * @param lore The lore of the item. + * @return The created item. + */ public ItemStack newItem(final @NotNull Material material, final @NotNull Component name, - final @NotNull Component... lore) + final @NotNull Component... lore) { final ItemStack item = new ItemStack(material, 1); final ItemMeta meta = item.getItemMeta(); diff --git a/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java b/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java index 3c59ccd..6ef8948 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java @@ -11,65 +11,126 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +/** + * This class is a wrapper for {@link BossBar} objects. It provides some handy methods for changing the boss bar's + * properties, displaying the bar to {@link Audience}s, and a {@link BossBarBuilder} to easily create new boss bars. + */ public class BossBarDisplay { private BossBar bossBar; + /** + * Creates a new {@link BossBarDisplay} object. + * + * @param bossBar The {@link BossBar} to wrap. + */ public BossBarDisplay(final BossBar bossBar) { this.bossBar = bossBar; } + /** + * @return A new {@link BossBarBuilder} object. + */ public static BossBarBuilder builder() { return new BossBarBuilder(); } + /** + * Changes the boss bar's color. + * + * @param color The new color. + */ public void changeColor(final BossBar.Color color) { this.bossBar.color(color); } + /** + * Changes the boss bar's color. + * + * @param overlay The new overlay. + */ public void changeOverlay(final BossBar.Overlay overlay) { this.bossBar.overlay(overlay); } + /** + * Changes the boss bar's name using a {@link Component}. + * + * @param name The new name. + */ public void changeName(final Component name) { this.bossBar.name(name); } + /** + * Changes the boss bar's name with a String and a {@link TextColor}. + * + * @param name The new name. + * @param color The name color. + */ public void changeName(final String name, final TextColor color) { this.bossBar.name(Component.text(name, color)); } + /** + * Changes the boss bar's name with a String. + * + * @param name The new name. + */ public void changeName(final String name) { this.bossBar.name(Component.text(name)); } + /** + * Shows this Boss Bar to the specified {@link Audience}. + * + * @param audience The {@link Audience} to show the Boss Bar to. + */ public void showTo(final Audience audience) { audience.showBossBar(getBossBar()); } + /** + * @return The {@link BossBar} object that this class wraps. + */ public BossBar getBossBar() { return this.bossBar; } + /** + * Sets the {@link BossBar} object that this class wraps. + * + * @param bossBar The new {@link BossBar} object. + */ public void setBossBar(final BossBar bossBar) { this.bossBar = bossBar; } + /** + * Hides this Boss Bar from the specified {@link Audience}. + * + * @param audience The {@link Audience} to hide the Boss Bar from. + */ public void hideFrom(final Audience audience) { audience.hideBossBar(getBossBar()); } + /** + * Increments the Bar's progress by the specified amount. This must be a range from 0 to 100. + * + * @param progress The new progress. + */ public void incrementProgress(final @Range(from = 0, to = 100) float progress) { final float currentProgress = this.bossBar.progress(); @@ -79,6 +140,11 @@ public class BossBarDisplay else this.bossBar.progress(newProgress); } + /** + * Decrements the Bar's progress by the specified amount. This must be a range from 0 to 100. + * + * @param progress The new progress. + */ public void decrementProgress(final @Range(from = 0, to = 100) float progress) { final float currentProgress = this.bossBar.progress(); @@ -88,40 +154,80 @@ public class BossBarDisplay else this.bossBar.progress(newProgress); } + /** + * Sets the Bar's progress to the maximum amount (full bar). + */ public void maximumProgress() { this.bossBar.progress(1.0F); } + /** + * Sets the Bar's progress to half of the maximum amount (half bar). + */ public void halfProgress() { this.bossBar.progress(0.5F); } + /** + * Sets the Bar's progress to the minimum amount (empty bar). + */ public void minimumProgress() { this.bossBar.progress(0.0F); } + /** + * Shows this Boss Bar to the specified {@link ForwardingAudience}. + * + * @param forwardingAudience The {@link ForwardingAudience} to show the Boss Bar to. + */ public void showForwarded(final ForwardingAudience forwardingAudience) { forwardingAudience.showBossBar(getBossBar()); } + /** + * Hides this Boss Bar from the specified {@link ForwardingAudience}. + * + * @param forwardingAudience The {@link ForwardingAudience} to hide the Boss Bar from. + */ public void hideForwarded(final ForwardingAudience forwardingAudience) { forwardingAudience.hideBossBar(getBossBar()); } - private static final class BossBarBuilder + /** + * A Builder class for {@link BossBar} objects. + */ + public static final class BossBarBuilder { + /** + * The flags that this Boss Bar will have. + */ private final Set flags = new HashSet<>(); + /** + * The Boss Bar's name. + */ private Component name; + /** + * The Boss Bar's color. + */ private BossBar.Color color; + /** + * The Boss Bar's overlay. + */ private BossBar.Overlay overlay; + /** + * The Boss Bar's progress. + */ @Range(from = 0, to = 1) private float progress; + /** + * Initializes this Builder object. + */ public BossBarBuilder() { this.name = Component.empty(); @@ -130,72 +236,134 @@ public class BossBarDisplay this.progress = 0.0F; } + /** + * Sets the name of the boss bar. + * + * @param name The name of the boss bar. + * @return The builder. + */ public BossBarBuilder setName(final Component name) { this.name = name; return this; } + /** + * Sets the name of the boss bar using a String and a {@link TextColor}. + * + * @param name The name of the boss bar. + * @param color The color of the boss bar. + * @return The builder. + */ public BossBarBuilder setName(final String name, final TextColor color) { this.name = Component.text(name, color); return this; } + /** + * Sets the name of the boss bar using a String. + * + * @param name The name of the boss bar. + * @return The builder. + */ public BossBarBuilder setName(final String name) { this.name = Component.text(name); return this; } + /** + * Adds a flag to the boss bar. + * @param flag The flag to add. + * @return The builder. + */ public BossBarBuilder addFlag(final BossBar.Flag flag) { this.flags.add(flag); return this; } + /** + * Adds multiple flags to the boss bar. + * @param flags The flags to add. + * @return The builder. + */ public BossBarBuilder addFlags(final BossBar.Flag... flags) { this.flags.addAll(List.of(flags)); return this; } + /** + * Removes a flag from the boss bar. + * @param flag The flag to remove. + * @return The builder. + */ public BossBarBuilder removeFlag(final BossBar.Flag flag) { this.flags.remove(flag); return this; } + /** + * Removes multiple flags from the boss bar. + * @param flags The flags to remove. + * @return The builder. + */ public BossBarBuilder removeFlags(final BossBar.Flag... flags) { this.flags.removeAll(List.of(flags)); return this; } + /** + * Clears all flags from the boss bar. + * @return The builder. + */ public BossBarBuilder clearFlags() { this.flags.clear(); return this; } + /** + * Sets the color of the boss bar. + * @param color The color of the boss bar. + * @return The builder. + */ public BossBarBuilder setColor(final BossBar.Color color) { this.color = color; return this; } + /** + * Sets the overlay of the boss bar. + * @param overlay The overlay of the boss bar. + * @return The builder. + */ public BossBarBuilder setOverlay(final BossBar.Overlay overlay) { this.overlay = overlay; return this; } + /** + * Sets the progress of the boss bar. This must satisfy {@code 0 <= progress <= 100}. + * @param progress The progress of the boss bar. + * @return The builder. + */ public BossBarBuilder setProgress(final @Range(from = 0, to = 100) float progress) { this.progress = progress / 100.0F; return this; } + /** + * Builds the boss bar. + * @return The {@link BossBar}. + */ public BossBar build() { return BossBar.bossBar(this.name, this.progress, this.color, this.overlay, this.flags); diff --git a/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java b/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java new file mode 100644 index 0000000..91cf858 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java @@ -0,0 +1,40 @@ +package me.totalfreedom.display; + +import me.totalfreedom.service.Task; +import net.kyori.adventure.audience.Audience; +import org.bukkit.Bukkit; + +import java.time.Duration; + +public class BossBarTimer extends Task +{ + private final BossBarDisplay bossBarDisplay; + private final Duration duration; + private double seconds = 0; + + public BossBarTimer(final BossBarDisplay bossBarDisplay, final Duration duration) + { + super("BossBarTimer", -1L, 20L); + this.bossBarDisplay = bossBarDisplay; + this.duration = duration; + bossBarDisplay.minimumProgress(); + bossBarDisplay.showTo(Bukkit.getServer()); + } + + @Override + public void run() + { + if (this.isCancelled()) return; + + if (seconds >= duration.getSeconds()) + { + bossBarDisplay.hideFrom(Bukkit.getServer()); + this.cancel(); + return; + } + + final float percentage = (float) (seconds / duration.getSeconds()) * 100L; + bossBarDisplay.incrementProgress(percentage); + seconds++; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java b/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java index 2d6d21f..a7816c7 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java @@ -2,8 +2,15 @@ package me.totalfreedom.display; import org.bukkit.entity.Player; +/** + * Represents an action to be performed when a player clicks on an inventory slot in the respective {@link AbstractMenu}. + */ @FunctionalInterface public interface ClickAction { + /** + * Called when a player clicks on an inventory slot in the respective {@link AbstractMenu}. + * @param player The player who clicked. + */ 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 c550877..56a5fff 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/Displayable.java @@ -15,12 +15,29 @@ import java.util.HashMap; import java.util.List; import java.util.ListIterator; +/** + * A class that represents an inventory that can be displayed to players. This class also represents the inventory + * holder which contains the inventory. + */ public final class Displayable implements Inventory, InventoryHolder { + /** + * The size of the inventory. This is always a multiple of 9. + */ private final int size; + /** + * The contents of the inventory. + */ private ItemStack[] contents; + /** + * Creates a new Displayable inventory with the given size. You are free to supply any size you want, but it will + * always be rounded up to the next multiple of 9. The maximum size allowed is 54. Any number higher than that will + * be rounded down to 54. + * + * @param size The size of the inventory. + */ protected Displayable(final int size) { if (size < 1 || size > 54) @@ -31,8 +48,8 @@ public final class Displayable implements Inventory, InventoryHolder // 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); + ? size + : size + (9 - size % 9); this.contents = new ItemStack[size]; } @@ -82,7 +99,7 @@ public final class Displayable implements Inventory, InventoryHolder @Override public @NotNull HashMap addItem(final @NotNull ItemStack... items) - throws IllegalArgumentException + throws IllegalArgumentException { final HashMap remainingItems = new HashMap<>(); @@ -121,7 +138,7 @@ public final class Displayable implements Inventory, InventoryHolder @Override public @NotNull HashMap removeItem(final @NotNull ItemStack... items) - throws IllegalArgumentException + throws IllegalArgumentException { final HashMap removedItems = new HashMap<>(); @@ -154,7 +171,7 @@ public final class Displayable implements Inventory, InventoryHolder if (remainingAmount < item.getAmount()) { removedItems.put(removedItems.size(), - new ItemStack(item.getType(), item.getAmount() - remainingAmount)); + new ItemStack(item.getType(), item.getAmount() - remainingAmount)); } } @@ -163,7 +180,7 @@ public final class Displayable implements Inventory, InventoryHolder @Override public @NotNull HashMap removeItemAnySlot(final @NotNull ItemStack... items) - throws IllegalArgumentException + throws IllegalArgumentException { return removeItem(items); } @@ -294,7 +311,7 @@ public final class Displayable implements Inventory, InventoryHolder @Override public @NotNull HashMap all(final @NotNull Material material) - throws IllegalArgumentException + throws IllegalArgumentException { final HashMap matchingItems = new HashMap<>(); for (int i = 0; i < size; i++) diff --git a/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java b/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java index 9a5eb2a..2a923b1 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java @@ -8,14 +8,42 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.jetbrains.annotations.NotNull; +/** + * A view of a {@link Displayable} inventory. + *

+ * This class can be used to display two separate {@link Displayable} objects to the Player. + */ public class DisplayableView extends InventoryView { + /** + * The upper inventory involved in this transaction. + */ private final Displayable top; + /** + * The lower inventory involved in this transaction. + */ private final Displayable bottom; + /** + * The player viewing the inventories involved in this transaction. + */ private final Player player; + /** + * The type of inventory this transaction is for. + */ private final InventoryType type; + /** + * The title of the main inventory involved in this transaction. The main inventory should always be the top + * inventory. + */ private String title; + /** + * Creates a new DisplayableView. + * + * @param player The player viewing the inventories involved in this transaction. + * @param top The upper inventory involved in this transaction. + * @param bottom The lower inventory involved in this transaction. + */ public DisplayableView(final Player player, final Displayable top, final Displayable bottom) { this.player = player; @@ -55,15 +83,15 @@ public class DisplayableView extends InventoryView return title; } - @Override - public @NotNull String getOriginalTitle() - { - return FreedomAdventure.toPlainText(type.defaultTitle()); - } - @Override public void setTitle(final @NotNull String title) { this.title = title; } + + @Override + public @NotNull String getOriginalTitle() + { + return FreedomAdventure.toPlainText(type.defaultTitle()); + } } diff --git a/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java b/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java index 1a7a4e4..a5110bd 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java @@ -8,50 +8,108 @@ import net.kyori.adventure.title.Title; import java.time.Duration; +/** + * A wrapper class for {@link Title}s that allows for easy display to an {@link Audience}. + */ public class TitleDisplay { + /** + * The {@link Title} to display. + */ private Title title; + /** + * Creates a new {@link TitleDisplay} with the given {@link Title}. + * @param title The {@link Title} to display. + */ public TitleDisplay(final Title title) { this.title = title; } + /** + * @return A new {@link TitleBuilder} which can be used to create new {@link Title}s. + */ public static TitleBuilder builder() { return new TitleBuilder(); } + /** + * Displays the {@link Title} to the given {@link Audience}. + * @param audience The {@link Audience} to display the {@link Title} to. + */ public void displayTo(final Audience audience) { audience.clearTitle(); audience.showTitle(getTitle()); } + /** + * @return The {@link Title} to display. + */ public Title getTitle() { return this.title; } + /** + * Sets the {@link Title} to display. + * @param title The {@link Title} to display. + */ public void setTitle(final Title title) { this.title = title; } + /** + * Displays the {@link Title} to the given {@link ForwardingAudience}. + * @param forwardingAudience The {@link ForwardingAudience} to display the {@link Title} to. + */ public void displayForwarded(final ForwardingAudience forwardingAudience) { forwardingAudience.clearTitle(); forwardingAudience.showTitle(getTitle()); } - private static final class TitleBuilder + /** + * A builder class for {@link Title}s. + */ + public static final class TitleBuilder { + /** + * The main title of the {@link Title}. + */ private Component mainTitle; + /** + * The subtitle of the {@link Title}. + */ private Component subTitle; + /** + * How long the Title should fade in for. + */ private Duration fadeIn; + /** + * How long the Title should fade out for. + */ private Duration fadeOut; + /** + * How long the Title should be displayed for. + */ private Duration displayDuration; + /** + * Creates a new {@link TitleBuilder} with default values. + * The default values are: + *

    + *
  • Empty main title
  • + *
  • Empty subtitle
  • + *
  • Default fade in time
  • + *
  • Default fade out time
  • + *
  • Default display duration
  • + *
+ * @see Title#DEFAULT_TIMES + */ public TitleBuilder() { this.mainTitle = Component.empty(); @@ -61,60 +119,111 @@ public class TitleDisplay this.displayDuration = Title.DEFAULT_TIMES.stay(); } + /** + * Sets the main title of the {@link Title}. + * @param title The main title of the {@link Title}. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setMainTitle(final String title) { this.mainTitle = Component.text(title); return this; } + /** + * Sets the main title of the {@link Title}. + * @param title The main title of the {@link Title}. + * @param titleColor The color of the main title. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setMainTitle(final String title, final TextColor titleColor) { this.mainTitle = Component.text(title, titleColor); return this; } + /** + * Sets the main title of the {@link Title}. + * @param mainTitle The main title of the {@link Title}. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setMainTitle(final Component mainTitle) { this.mainTitle = mainTitle; return this; } + /** + * Sets the subtitle of the {@link Title}. + * @param title The subtitle of the {@link Title}. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setSubTitle(final String title) { this.subTitle = Component.text(title); return this; } + /** + * Sets the subtitle of the {@link Title}. + * @param title The subtitle of the {@link Title}. + * @param titleColor The color of the subtitle. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setSubTitle(final String title, final TextColor titleColor) { this.subTitle = Component.text(title, titleColor); return this; } + /** + * Sets the subtitle of the {@link Title}. + * @param subTitle The subtitle of the {@link Title}. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setSubTitle(final Component subTitle) { this.subTitle = subTitle; return this; } + /** + * Sets the fade in time of the {@link Title}. + * @param duration The fade in time of the {@link Title}. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setFadeIn(final Duration duration) { this.fadeIn = duration; return this; } + /** + * Sets the fade out time of the {@link Title}. + * @param duration The fade out time of the {@link Title}. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setFadeOut(final Duration duration) { this.fadeOut = duration; return this; } + /** + * Sets the display duration of the {@link Title}. + * @param duration The display duration of the {@link Title}. + * @return The {@link TitleBuilder} instance. + */ public TitleBuilder setDisplayDuration(final Duration duration) { this.displayDuration = duration; return this; } + /** + * Builds the {@link Title} with the given parameters. + * @return The built {@link Title}. + */ public Title build() { return Title.title( diff --git a/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java index f6c4a83..25bcb8e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java @@ -16,7 +16,23 @@ public final class ServiceSubscription private boolean isActive = false; + ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service) + { + this(plugin, service, 1L, false); + } + ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final boolean async) + { + this(plugin, service, 1L, async); + } + + ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final long interval) + { + this(plugin, service, interval, false); + } + + ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, + final long interval, final boolean async) { this.service = service; this.async = async; @@ -28,7 +44,7 @@ public final class ServiceSubscription this.executor = r -> { final BukkitTask task = Bukkit.getScheduler() - .runTaskTimerAsynchronously(plugin, r, 0, 1); + .runTaskTimerAsynchronously(plugin, r, 0, interval); tempId[0] = task.getTaskId(); }; } else @@ -36,7 +52,7 @@ public final class ServiceSubscription this.executor = r -> { final BukkitTask task = Bukkit.getScheduler() - .runTaskTimer(plugin, r, 0, 1); + .runTaskTimer(plugin, r, 0, interval); tempId[0] = task.getTaskId(); }; } diff --git a/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java b/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java index a1478c0..cd2e846 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java @@ -16,7 +16,16 @@ public final class SubscriptionProvider public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin, @NotNull final S service) { - return new ServiceSubscription<>(plugin, service, false); + return new ServiceSubscription<>(plugin, service); + } + + @NotNull + @Contract(value = "_,_,_ -> new", pure = false) + public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin, + final long interval, + @NotNull final S service) + { + return new ServiceSubscription<>(plugin, service, interval); } @NotNull @@ -35,6 +44,15 @@ public final class SubscriptionProvider return new TaskSubscription<>(plugin, task, false); } + @NotNull + @Contract(value = "_,_,_ -> new", pure = false) + public static final ServiceSubscription asyncService(@NotNull final JavaPlugin plugin, + final long interval, + @NotNull final S service) + { + return new ServiceSubscription<>(plugin, service, interval, true); + } + @NotNull @Contract(value = "_, _ -> new", pure = false) public static final TaskSubscription runAsyncTask(@NotNull final JavaPlugin plugin, diff --git a/Patchwork/src/main/java/me/totalfreedom/service/Task.java b/Patchwork/src/main/java/me/totalfreedom/service/Task.java index b072b26..88049e1 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/Task.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/Task.java @@ -1,20 +1,85 @@ package me.totalfreedom.service; -public interface Task extends Runnable +import me.totalfreedom.utils.DurationTools; +import org.bukkit.scheduler.BukkitRunnable; + +import java.time.Duration; + +public abstract class Task extends BukkitRunnable { - boolean isRunning(); + private final String name; + private long delay; + private long interval; - String getName(); + protected Task(final String name) + { + this(name, -1L, -1L); + } - boolean isRepeating(); + protected Task(final String name, final long delay, final long interval) + { + this.name = name; + this.delay = delay; + this.interval = interval; + } - void setRepeating(long interval); + protected Task(final String name, final long delay) + { + this(name, delay, -1L); + } - boolean isDelayed(); + protected Task(final String name, final Duration delay) + { + this(name, DurationTools.getTickedSeconds(delay), -1L); + } - void setDelayed(long delay); + protected Task(final String name, final Duration delay, final Duration interval) + { + this(name, DurationTools.getTickedSeconds(delay), DurationTools.getTickedSeconds(interval)); + } - long getInterval(); + protected Task(final String name, final long delay, final Duration interval) + { + this(name, delay, DurationTools.getTickedSeconds(interval)); + } - long getDelay(); + public boolean isRunning() + { + return !isCancelled(); + } + + public String getName() + { + return name; + } + + public boolean isRepeating() + { + return interval != -1L; + } + + public void setRepeating(final long interval) + { + this.interval = interval; + } + + public boolean isDelayed() + { + return this.delay != -1; + } + + public void setDelayed(final long delay) + { + this.delay = delay; + } + + public long getInterval() + { + return interval; + } + + public long getDelay() + { + return delay; + } } diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java b/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java index c8dacd2..6a00d84 100644 --- a/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java +++ b/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java @@ -1,16 +1,25 @@ package me.totalfreedom.shop; +import me.totalfreedom.display.BossBarDisplay; import me.totalfreedom.economy.EconomicEntity; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import org.bukkit.event.Listener; import java.time.Duration; +import java.util.function.Consumer; public interface Reactable { - String getReactionMessage(); + Component getReactionMessage(); Duration getReactionDuration(); ReactionType getReactionType(); + long getReward(); + + void display(final Audience audience); + void onReact(final EconomicEntity entity); } diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java b/Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java new file mode 100644 index 0000000..6124f8b --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java @@ -0,0 +1,69 @@ +package me.totalfreedom.shop; + +import me.totalfreedom.display.BossBarDisplay; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; + +import java.time.Duration; + +/** + * Represents a chat reaction that can be performed by a player. + */ +public abstract class Reaction implements Reactable +{ + private final Duration reactionDuration; + private final ReactionType reactionType; + private final long reward; + private Component reactionMessage = Component.empty(); + + protected Reaction(final ReactionType type) + { + this(50L, type); + } + + protected Reaction(final long reward, final ReactionType type) + { + this(30L, reward, type); + } + + protected Reaction(final long seconds, final long reward, final ReactionType reactionType) + { + this(Duration.ofSeconds(seconds), reward, reactionType); + } + + protected Reaction(final Duration duration, final long reward, final ReactionType reactionType) + { + this.reward = reward; + this.reactionDuration = duration; + this.reactionType = reactionType; + } + + @Override + public Component getReactionMessage() + { + return reactionMessage; + } + + @Override + public Duration getReactionDuration() + { + return reactionDuration; + } + + @Override + public ReactionType getReactionType() + { + return reactionType; + } + + @Override + public BossBarDisplay getBossBarDisplay() + { + + } + + public void setReactionMessage(final Component message) + { + this.reactionMessage = message; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/ReactionTask.java b/Patchwork/src/main/java/me/totalfreedom/shop/ReactionTask.java new file mode 100644 index 0000000..4af9233 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/shop/ReactionTask.java @@ -0,0 +1,50 @@ +package me.totalfreedom.shop; + +import io.papermc.paper.event.player.AsyncChatEvent; +import me.totalfreedom.base.CommonsBase; +import me.totalfreedom.display.BossBarDisplay; +import me.totalfreedom.display.BossBarTimer; +import me.totalfreedom.economy.EconomicEntity; +import me.totalfreedom.service.Task; +import net.kyori.adventure.bossbar.BossBar; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class ReactionTask extends Task implements Listener { + private final Reaction reaction; + private final BossBarDisplay bossBarDisplay; + + public ReactionTask(final String name, final Reaction reaction) { + super(name, -1L, -1); + this.reaction = reaction; + final BossBar bossBar = BossBarDisplay.builder() + .setName(reaction.getReactionMessage()) + .setColor(BossBar.Color.GREEN) + .setProgress(0.0F) + .build(); + + this.bossBarDisplay = new BossBarDisplay(bossBar); + } + + @Override + public void run() { + if (isCancelled()) { + } + + final BossBarTimer timer = new BossBarTimer(bossBarDisplay, reaction.getReactionDuration()); + timer.runTaskTimer(CommonsBase.getInstance(), 0L, timer.getInterval()); + } + + @EventHandler + public void onPlayerChat(final AsyncChatEvent event) { + if (event.message() + .equals(reaction.getReactionMessage())) { + final EconomicEntity entity = CommonsBase.getInstance() + .getRegistrations() + .getUserRegistry() + .getUser(event.getPlayer()); + + reaction.onReact(entity); + } + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/ReactionType.java b/Patchwork/src/main/java/me/totalfreedom/shop/ReactionType.java index b2b308d..e36a3da 100644 --- a/Patchwork/src/main/java/me/totalfreedom/shop/ReactionType.java +++ b/Patchwork/src/main/java/me/totalfreedom/shop/ReactionType.java @@ -2,5 +2,5 @@ package me.totalfreedom.shop; public enum ReactionType { - COPYCAT, UNSCRAMBLE; + COPYCAT, UNSCRAMBLE, MATH; } diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/DurationTools.java b/Patchwork/src/main/java/me/totalfreedom/utils/DurationTools.java new file mode 100644 index 0000000..1f833bc --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/utils/DurationTools.java @@ -0,0 +1,28 @@ +package me.totalfreedom.utils; + +import java.time.Duration; + +public final class DurationTools +{ + // One tick is 1/20th of a second which is about 50ms. + public static final Duration TICK = Duration.ofMillis(50L); + // One second is 20 ticks. + public static final Duration SECOND = TICK.multipliedBy(20L); + // One minute is 60 seconds. + public static final Duration MINUTE = SECOND.multipliedBy(60L); + + private DurationTools() + { + throw new AssertionError(); + } + + public static final long getTickedSeconds(final Duration duration) + { + return duration.toMillis() / 50L; + } + + public static final Duration getTickedSeconds(final long seconds) + { + return SECOND.multipliedBy(seconds); + } +} From 09c511ef3413e0ea0ea8c0bd91304a274c5a9f7f Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Fri, 9 Jun 2023 13:23:06 -0500 Subject: [PATCH 10/14] Additional documentation --- .../me/totalfreedom/display/BossBarTimer.java | 1 - .../java/me/totalfreedom/security/Group.java | 23 +++++ .../totalfreedom/service/FreedomExecutor.java | 79 ++++++++++++++- .../java/me/totalfreedom/service/Service.java | 29 ++++++ .../service/ServiceSubscription.java | 95 +++++++++++++++++- .../service/SubscriptionProvider.java | 92 +++++++++++++++--- .../java/me/totalfreedom/service/Task.java | 97 ++++++++++++++++--- .../service/TaskSubscription.java | 87 +++++++++++++++-- .../java/me/totalfreedom/shop/Reactable.java | 3 - .../java/me/totalfreedom/shop/Reaction.java | 11 +-- 10 files changed, 469 insertions(+), 48 deletions(-) diff --git a/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java b/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java index 91cf858..dfa3eb1 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/BossBarTimer.java @@ -1,7 +1,6 @@ package me.totalfreedom.display; import me.totalfreedom.service.Task; -import net.kyori.adventure.audience.Audience; import org.bukkit.Bukkit; import java.time.Duration; diff --git a/Patchwork/src/main/java/me/totalfreedom/security/Group.java b/Patchwork/src/main/java/me/totalfreedom/security/Group.java index d09ba61..41b2825 100644 --- a/Patchwork/src/main/java/me/totalfreedom/security/Group.java +++ b/Patchwork/src/main/java/me/totalfreedom/security/Group.java @@ -2,17 +2,40 @@ package me.totalfreedom.security; import net.kyori.adventure.text.Component; +/** + * Represents a permissible group which holds a set of permissions that can then be applied to a User / Player. + */ public interface Group extends PermissionHolder { + /** + * @return The name of the group. + */ Component getName(); + /** + * @return The prefix of the group. + */ Component getPrefix(); + /** + * @return The abbreviation of the group. + */ Component getAbbreviation(); + /** + * @return The weight of the group. + */ int getWeight(); + /** + * If more than one group is marked as default, the first retrieved default group will be used. + * + * @return Whether this is the default group. + */ boolean isDefault(); + /** + * @return Whether the group is hidden. + */ boolean isHidden(); } diff --git a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java index dcaff95..5724f09 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java @@ -4,13 +4,28 @@ import me.totalfreedom.base.CommonsBase; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +/** + * This is a holder class for {@link Executor} objects that are used to delegate runnable tasks to the Bukkit Scheduler. + * This class is here for both convenience purposes, and also for the sake of providing easy access to executors for + * {@link CompletableFuture} invocations. + */ public class FreedomExecutor { + /** + * An executor which runs tasks synchronously. + */ private final Executor syncExecutor; + /** + * An executor which runs tasks asynchronously. + */ private final Executor asyncExecutor; + /** + * Creates a new {@link FreedomExecutor} instance. + */ public FreedomExecutor() { syncExecutor = r -> Bukkit.getScheduler() @@ -19,47 +34,107 @@ public class FreedomExecutor .runTaskAsynchronously(CommonsBase.getInstance(), r); } + /** + * Creates a new {@link Executor} that is capable of executing a runnable one singular time, synchronously. + * + * @param plugin The plugin to run the task for. + * @return A new {@link Executor} instance. + */ public Executor singleExecutor(final JavaPlugin plugin) { return r -> Bukkit.getScheduler() .runTask(plugin, r); } + /** + * Creates a new {@link Executor} that is capable of executing a runnable one singular time, synchronously. This + * Executor will wait for the supplied delay before executing the runnable. + * + * @param plugin The plugin to run the task for. + * @param delay The delay to wait before executing the runnable. + * @return A new {@link Executor} instance. + */ public Executor delayedExecutor(final JavaPlugin plugin, final long delay) { return r -> Bukkit.getScheduler() .runTaskLater(plugin, r, delay); } - public Executor periodicExecutor(final JavaPlugin plugin, final long delay, final long period) + /** + * Creates a new {@link Executor} tthat is capable of executing a runnable on a periodic basis, synchronously. This + * executor can also be supplied a delay to indicate it should wait the specified amount of time before executing + * the runnable for the first time. + * + * @param plugin The plugin to run the task for. + * @param initialDelay The delay to wait before executing the runnable for the first time. + * @param period The period to wait between each execution of the runnable. + * @return A new {@link Executor} instance. + */ + public Executor periodicExecutor(final JavaPlugin plugin, final long initialDelay, final long period) { return r -> Bukkit.getScheduler() - .runTaskTimer(plugin, r, delay, period); + .runTaskTimer(plugin, r, initialDelay, period); } + /** + * Creates a new {@link Executor} that is capable of executing a runnable one singular time, asynchronously. + * + * @param plugin The plugin to run the task for. + * @return A new {@link Executor} instance. + */ public Executor asynchronousSingleExecutor(final JavaPlugin plugin) { return r -> Bukkit.getScheduler() .runTaskAsynchronously(plugin, r); } + /** + * Creates a new {@link Executor} that is capable of executing a runnable one singular time, asynchronously. This + * Executor will wait for the supplied delay before executing the runnable. + * + * @param plugin The plugin to run the task for. + * @param delay The delay to wait before executing the runnable. + * @return A new {@link Executor} instance. + */ public Executor asynchronousDelayedExecutor(final JavaPlugin plugin, final long delay) { return r -> Bukkit.getScheduler() .runTaskLaterAsynchronously(plugin, r, delay); } + /** + * Creates a new {@link Executor} tthat is capable of executing a runnable on a periodic basis, asynchronously. This + * executor can also be supplied a delay to indicate it should wait the specified amount of time before executing + * the runnable for the first time. + * + * @param plugin The plugin to run the task for. + * @param delay The delay to wait before executing the runnable for the first time. + * @param period The period to wait between each execution of the runnable. + * @return A new {@link Executor} instance. + */ public Executor asynchronousPeriodicExecutor(final JavaPlugin plugin, final long delay, final long period) { return r -> Bukkit.getScheduler() .runTaskTimerAsynchronously(plugin, r, delay, period); } + /** + * Gets the synchronous executor instance. This is a convenience for {@link CompletableFuture} invocations, + * when defining a custom executor for the {@link CompletableFuture}. + * + * @return The synchronous executor instance. + */ public Executor getSync() { return syncExecutor; } + /** + * Gets the asynchronous executor instance. This is a convenience for {@link CompletableFuture} invocations, + * when defining a custom executor for the {@link CompletableFuture}. + * + * @return The asynchronous executor instance. + */ 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 592eb9c..927fb36 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/Service.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/Service.java @@ -1,16 +1,45 @@ package me.totalfreedom.service; +/** + * Represents a ticking service. Services may be asynchronous or synchronous, however there are some restrictions: + *
    + *
  • Sync services may not have a complexity greater than 5.
  • + *
  • Async services may not interact with the Bukkit API in any form.
  • + *
+ */ public abstract class Service { + /** + * The name of the service. + */ private final String name; + /** + * Creates a new service with the given name. + * + * @param name The name of the service. + */ protected Service(final String name) { this.name = name; } + /** + * This method is called every single tick, or at least, every tick interval described by the holding + * {@link ServiceSubscription}. Since this runs every single tick, the body of this method should not have a + * complexity higher than 5. This includes Cyclomatic, Cognitive, and NPath complexities. If the service is + * asynchronous, there is a bit more flexibility with the complexity rating, extending to no more than 10. However, + * it's generally good practice to keep the complexity of ticking services as low as possible to avoid extensive + * resource consumption. + * + * @see ServiceSubscription + * @see SubscriptionProvider + */ public abstract void tick(); + /** + * @return The name of the service. + */ public String getName() { return name; diff --git a/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java index 25bcb8e..dd8b543 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/ServiceSubscription.java @@ -7,32 +7,105 @@ import org.jetbrains.annotations.NotNull; import java.util.concurrent.Executor; +/** + * Represents a subscription to a {@link Service}. + *

+ * Subscriptions contain some information about the service itself and it's presence on the scheduler. For example, + * {@link #getServiceId()} will return the ID of the task which was returned by the scheduler. Subscriptions also manage + * the state of the service, using {@link #isActive()} to determine if the service is currently running. + *
+ *
+ * The subscription itself provides type inference to safely store the actual service instance. This is useful for when + * we need to access the service itself, without calling to the service directly. + * + * @param The type of service this subscription is for. + */ public final class ServiceSubscription { + /** + * The service this subscription is for. + */ private final T service; + /** + * Whether this is an asynchronous service. + */ private final boolean async; + /** + * The executor used to schedule the service. + */ private final Executor executor; + /** + * The ID of the service from the associated {@link BukkitTask} which was returned by the Scheduler. + */ private final int serviceId; + /** + * Whether the service is currently running. + */ private boolean isActive = false; + /** + * Creates a new subscription for the given service. By default, this method will mark this service as a synchronous + * service. This will also initialize the default interval to a single tick. + *
+ * If you are trying to create an asynchronous service, use + * {@link #ServiceSubscription(JavaPlugin, Service, boolean)} instead. + *
+ * If you would like to define a custom interval, use either {@link #ServiceSubscription(JavaPlugin, Service, long)} + * or {@link #ServiceSubscription(JavaPlugin, Service, long, boolean)} (for asynchronous services). + * + * @param plugin The plugin which owns the service. + * @param service The service to subscribe to. + */ ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service) { this(plugin, service, 1L, false); } + /** + * Creates a new subscription for the given service. This will initialize the default interval to a single tick. + *
+ * If you would like to define a custom interval, use either {@link #ServiceSubscription(JavaPlugin, Service, long)} + * or {@link #ServiceSubscription(JavaPlugin, Service, long, boolean)} (for asynchronous services). + * + * @param plugin The plugin which owns the service. + * @param service The service to subscribe to. + * @param async Whether the service should be scheduled asynchronously. + */ ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final boolean async) { this(plugin, service, 1L, async); } + /** + * Creates a new subscription for the given service. By default, this will mark the service as synchronous. When + * defining a custom interval, the interval should be less than 20L (the number of ticks in a second). For anything + * that requires an interval greater than 1 second, use a {@link Task} instead. + *
+ * If you are trying to create an asynchronous service, use + * {@link #ServiceSubscription(JavaPlugin, Service, long, boolean)} instead. + * + * @param plugin The plugin which owns the service. + * @param service The service to subscribe to. + * @param interval The interval at which the service should be scheduled. + */ ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final long interval) { this(plugin, service, interval, false); } + /** + * Creates a new subscription for the given service. When defining a custom interval, the interval should be less + * than 20L (the number of ticks in a second). For anything that requires an interval greater than 1 second, use a + * {@link Task} instead. + * + * @param plugin The plugin which owns the service. + * @param service The service to subscribe to. + * @param interval The interval at which the service should be scheduled. + * @param async Whether the service should be scheduled asynchronously. + */ ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, - final long interval, final boolean async) + final long interval, final boolean async) { this.service = service; this.async = async; @@ -60,12 +133,18 @@ public final class ServiceSubscription this.serviceId = tempId[0]; } + /** + * Starts the service. + */ public void start() { this.isActive = true; this.executor.execute(service::tick); } + /** + * Stops the service. + */ public void stop() { this.isActive = false; @@ -73,22 +152,36 @@ public final class ServiceSubscription .cancelTask(this.getServiceId()); } + /** + * Returns the ID of the service from the associated {@link BukkitTask} which was returned by the Scheduler. + * + * @return The ID of the service. + */ public int getServiceId() { return serviceId; } + /** + * @return The service this subscription is for. + */ @NotNull public T getService() { return service; } + /** + * @return Whether this is an asynchronous service. + */ public boolean isAsync() { return async; } + /** + * @return Whether the service is currently running. + */ public boolean isActive() { return isActive; diff --git a/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java b/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java index cd2e846..3a3c8ab 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/SubscriptionProvider.java @@ -4,59 +4,121 @@ import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +/** + * Provides static methods for creating {@link ServiceSubscription} and {@link TaskSubscription} objects. + */ public final class SubscriptionProvider { + /** + * Prevents instantiation of this class. + */ private SubscriptionProvider() { throw new AssertionError(); } + /** + * Creates a new {@link ServiceSubscription} object that will run the given {@link Service} object on the main + * thread a single time. + * + * @param plugin The plugin that owns the service. + * @param service The service to run. + * @param Type inference to maintain the service type. + * @return The new {@link ServiceSubscription} object. + */ @NotNull @Contract(value = "_, _ -> new", pure = false) public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin, - @NotNull final S service) + @NotNull final S service) { return new ServiceSubscription<>(plugin, service); } + /** + * Creates a new {@link ServiceSubscription} object that will run the given {@link Service} object on the main + * thread at the given interval. + * + * @param plugin The plugin that owns the service. + * @param interval The interval to run the service at. + * @param service The service to run. + * @param Type inference to maintain the service type. + * @return The new {@link ServiceSubscription} object. + */ @NotNull @Contract(value = "_,_,_ -> new", pure = false) public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin, - final long interval, - @NotNull final S service) + final long interval, + @NotNull final S service) { return new ServiceSubscription<>(plugin, service, interval); } + /** + * Creates a new {@link ServiceSubscription} object that will run the given {@link Service} object on the default + * tick interval, which is a single tick. This method will create an asynchronous service. + * + * @param plugin The plugin that owns the service. + * @param service The service to run. + * @param Type inference to maintain the service type. + * @return The new {@link ServiceSubscription} object. + */ @NotNull @Contract(value = "_, _ -> new", pure = false) public static final ServiceSubscription asyncService(@NotNull final JavaPlugin plugin, - @NotNull final S service) + @NotNull final S service) { return new ServiceSubscription<>(plugin, service, true); } - @NotNull - @Contract(value = "_, _ -> new", pure = false) - public static final TaskSubscription runSyncTask(@NotNull final JavaPlugin plugin, - @NotNull final T task) - { - return new TaskSubscription<>(plugin, task, false); - } - + /** + * Creates a new {@link ServiceSubscription} object that will run the given {@link Service} object on the given + * interval. This method will create an asynchronous service. + * + * @param plugin The plugin that owns the service. + * @param interval The interval to run the service at. + * @param service The service to run. + * @param Type inference to maintain the service type. + * @return The new {@link ServiceSubscription} object. + */ @NotNull @Contract(value = "_,_,_ -> new", pure = false) public static final ServiceSubscription asyncService(@NotNull final JavaPlugin plugin, - final long interval, - @NotNull final S service) + final long interval, + @NotNull final S service) { return new ServiceSubscription<>(plugin, service, interval, true); } + /** + * Creates a new {@link TaskSubscription} object that will run the given {@link Task} object synchronously on the + * main thread. + * + * @param plugin The plugin that owns the task. + * @param task The task to run. + * @param Type inference to maintain the task type. + * @return The new {@link TaskSubscription} object. + */ + @NotNull + @Contract(value = "_, _ -> new", pure = false) + public static final TaskSubscription runSyncTask(@NotNull final JavaPlugin plugin, + @NotNull final T task) + { + return new TaskSubscription<>(plugin, task, false); + } + + /** + * Creates a new {@link TaskSubscription} object that will run the given {@link Task} object asynchronously on the + * main thread. + * + * @param plugin The plugin that owns the task. + * @param task The task to run. + * @param Type inference to maintain the task type. + * @return The new {@link TaskSubscription} object. + */ @NotNull @Contract(value = "_, _ -> new", pure = false) public static final TaskSubscription runAsyncTask(@NotNull final JavaPlugin plugin, - @NotNull final T task) + @NotNull final T task) { return new TaskSubscription<>(plugin, task, true); } diff --git a/Patchwork/src/main/java/me/totalfreedom/service/Task.java b/Patchwork/src/main/java/me/totalfreedom/service/Task.java index 88049e1..cea71a6 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/Task.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/Task.java @@ -5,17 +5,45 @@ import org.bukkit.scheduler.BukkitRunnable; import java.time.Duration; +/** + * Represents a task that can be run asynchronously or synchronously. + */ public abstract class Task extends BukkitRunnable { + /** + * The name of the task. + */ private final String name; - private long delay; - private long interval; + /** + * The delay of the task. + */ + private final long delay; + /** + * The interval of the task. + */ + private final long interval; + /** + * Creates a new task with the given name. This will initialize a task with no initail delay and no interval. + * + * @param name The name of the task. + */ protected Task(final String name) { this(name, -1L, -1L); } + /** + * Creates a new task with the given name, delay, and interval. + *
+ * It's important to note that the delay and interval are in ticks. One tick is equal to 1/20th of a second, which + * means there are 20 ticks are in one second. If your interval is intended to be anything less than 20 ticks, you + * should use a {@link Service} instead. + * + * @param name The name of the task. + * @param delay The delay of the task. + * @param interval The interval of the task. + */ protected Task(final String name, final long delay, final long interval) { this.name = name; @@ -23,61 +51,102 @@ public abstract class Task extends BukkitRunnable this.interval = interval; } + /** + * Creates a new task with the given name and delay. This will intialize a single execute task with an + * initial delay before execution. + * + * @param name The name of the task. + * @param delay How long the task should wait before executing. + */ protected Task(final String name, final long delay) { this(name, delay, -1L); } + /** + * Creates a new task with the given name and delay. + * This is the same as longs, except that here, we naturally support durations which are automatically converted to + * ticks for you. This means that using {@link Duration#ofSeconds(long)} will work as expected. + * + * @param name The name of the task. + * @param delay How long the task should wait before executing. + */ protected Task(final String name, final Duration delay) { this(name, DurationTools.getTickedSeconds(delay), -1L); } + /** + * Creates a new task with the given name, delay, and interval. + * This is the same as longs, except that here, we naturally support durations which are automatically converted to + * ticks for you. This means that using {@link Duration#ofSeconds(long)} will work as expected. + * + * @param name The name of the task. + * @param delay How long the task should wait before executing. + * @param interval How long the task should wait between executions. + */ protected Task(final String name, final Duration delay, final Duration interval) { this(name, DurationTools.getTickedSeconds(delay), DurationTools.getTickedSeconds(interval)); } + /** + * Creates a new task with the given name, delay, and interval. + * This method is a convenience method to use a {@link Duration} for the interval, while also being able to + * specify the delay as -1L so the task does not have an initial delay before execution. + * + * @param name The name of the task. + * @param delay The delay of the task. + * @param interval The interval of the task. + */ protected Task(final String name, final long delay, final Duration interval) { this(name, delay, DurationTools.getTickedSeconds(interval)); } + /** + * @return True if the task is running, false otherwise. + */ public boolean isRunning() { return !isCancelled(); } + /** + * @return The name of the task. + */ public String getName() { return name; } + /** + * @return True if the task is repeating, false otherwise. + */ public boolean isRepeating() { - return interval != -1L; - } - - public void setRepeating(final long interval) - { - this.interval = interval; + return this.interval > 0L; } + /** + * @return True if the task is delayed, false otherwise. + */ public boolean isDelayed() { - return this.delay != -1; - } - - public void setDelayed(final long delay) - { - this.delay = delay; + return this.delay > 0L; } + /** + * @return The interval between each task execution. + */ public long getInterval() { return interval; } + /** + * @return The initial delay before the first execution of this task. + */ public long getDelay() { return delay; diff --git a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java index e8e4b8e..5d2b5e2 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java @@ -3,39 +3,82 @@ package me.totalfreedom.service; import me.totalfreedom.utils.Pair; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; import java.util.concurrent.Executor; +/** + * Represents a subscription to a task. Task subscriptions offer a nice wrapper for managing tasks, which are + * inevitably just bukkit runnables with a bit more lenience in terms of instantiation modification and execution. + * It also offers a more intuitive way to manage our tasks; rather than having to keep track of task ids for each + * {@link BukkitTask} object that gets returned by the {@link BukkitScheduler}. + * + * @param The type of task. + */ public final class TaskSubscription { + /** + * The task that is being subscribed to. + */ private final T task; + /** + * The task id of the task. + */ private final int taskId; + /** + * True if the task is async, false otherwise. + */ private final boolean async; + /** + * The executor that will execute the task. + */ private final Executor executor; + /** + * True if the task is active, false otherwise. By default, this is set to false, and will be marked as true when + * the task is started. + */ private boolean isActive = false; + /** + * Creates a new task subscription. + * + * @param plugin The plugin which owns the task. + * @param task The task that is being subscribed to. + * @param async True if the task is async, false otherwise. + */ TaskSubscription(final JavaPlugin plugin, final T task, final boolean async) { this.task = task; this.async = async; final long delay = (task.isDelayed() - ? task.getDelay() - : 0); + ? task.getDelay() + : 0); final long period = (task.isRepeating() - ? task.getInterval() - : 0); + ? task.getInterval() + : 0); final Pair integerExecutorPair = async - ? getAsync(plugin, delay, period) - : getSync(plugin, delay, period); + ? getAsync(plugin, delay, period) + : getSync(plugin, delay, period); this.executor = integerExecutorPair.value(); this.taskId = integerExecutorPair.key(); } + /** + * Gets the executor and task id for an async task, wrapped in a {@link Pair}<{@link Integer}, + * {@link Executor}>. + *
+ * This will return a Pair where {@link Pair#value()} is an asynchronous executor. + * + * @param plugin The plugin which owns the task. + * @param delay The delay of the task. + * @param period The period of the task. + * @return The executor and task id for an asynchronous task. + */ private Pair getAsync(final JavaPlugin plugin, final long delay, final long period) { final Executor executor1; @@ -69,6 +112,17 @@ public final class TaskSubscription return new Pair<>(tempId[0], executor1); } + /** + * Gets the executor and task id for a sync task, wrapped in a {@link Pair}<{@link Integer}, + * {@link Executor}>. + *
+ * This will return a Pair where {@link Pair#value()} is a synchronous executor. + * + * @param plugin The plugin which owns the task. + * @param delay The delay of the task. + * @param period The period of the task. + * @return The executor and task id for a synchronous task. + */ private Pair getSync(final JavaPlugin plugin, final long delay, final long period) { final Executor executor1; @@ -103,12 +157,18 @@ public final class TaskSubscription return new Pair<>(tempId[0], executor1); } + /** + * Starts the task. + */ public void start() { this.isActive = true; executor.execute(task); } + /** + * Stops the task. + */ public void stop() { this.isActive = false; @@ -116,26 +176,41 @@ public final class TaskSubscription .cancelTask(this.getTaskId()); } + /** + * @return The task id of the task. + */ public int getTaskId() { return taskId; } + /** + * @return The task that is being subscribed to. + */ public T getTask() { return task; } + /** + * @return True if the task is async, false otherwise. + */ public boolean isAsync() { return async; } + /** + * @return The executor that will execute the task. + */ public Executor getExecutor() { return executor; } + /** + * @return True if the task is active, false otherwise. + */ public boolean isActive() { return isActive; diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java b/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java index 6a00d84..86ddec4 100644 --- a/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java +++ b/Patchwork/src/main/java/me/totalfreedom/shop/Reactable.java @@ -1,13 +1,10 @@ package me.totalfreedom.shop; -import me.totalfreedom.display.BossBarDisplay; import me.totalfreedom.economy.EconomicEntity; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; -import org.bukkit.event.Listener; import java.time.Duration; -import java.util.function.Consumer; public interface Reactable { diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java b/Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java index 6124f8b..0b96cc7 100644 --- a/Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java +++ b/Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java @@ -1,7 +1,6 @@ package me.totalfreedom.shop; import me.totalfreedom.display.BossBarDisplay; -import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.text.Component; import java.time.Duration; @@ -44,6 +43,11 @@ public abstract class Reaction implements Reactable return reactionMessage; } + public void setReactionMessage(final Component message) + { + this.reactionMessage = message; + } + @Override public Duration getReactionDuration() { @@ -61,9 +65,4 @@ public abstract class Reaction implements Reactable { } - - public void setReactionMessage(final Component message) - { - this.reactionMessage = message; - } } From f459842eaffec39961617a42e1724ba33a2c0368 Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Fri, 9 Jun 2023 14:15:53 -0500 Subject: [PATCH 11/14] Some more updates --- .../totalfreedom/datura/punishment/Cager.java | 20 +-- .../me/totalfreedom/datura/sql/MySQL.java | 2 +- .../datura/user/SimpleUserData.java | 2 +- .../totalfreedom/fossil/cmd/CakeCommand.java | 2 +- .../economy/SimpleTransactionLogger.java | 2 +- .../totalfreedom/command/BukkitDelegate.java | 2 +- .../totalfreedom/display/DisplayableView.java | 2 +- .../me/totalfreedom/particle/NoteWrapper.java | 157 ++++++++++++++++++ .../me/totalfreedom/particle/TrailType.java | 21 +++ .../service/TaskSubscription.java | 2 +- .../utils/{Shaper.java => ShapeUtils.java} | 4 +- .../utils/{ => container}/Identity.java | 2 +- .../utils/{ => container}/Pair.java | 2 +- .../totalfreedom/utils/container/Tuple.java | 30 ++++ .../utils/container/UnaryTuple.java | 30 ++++ .../utils/{ => kyori}/FreedomAdventure.java | 2 +- .../utils/{ => kyori}/FreedomMiniMessage.java | 2 +- .../utils/{ => kyori}/KyoriConstants.java | 2 +- .../utils/{ => logging}/FreedomLogger.java | 3 +- 19 files changed, 264 insertions(+), 25 deletions(-) create mode 100644 Patchwork/src/main/java/me/totalfreedom/particle/NoteWrapper.java rename Patchwork/src/main/java/me/totalfreedom/utils/{Shaper.java => ShapeUtils.java} (90%) rename Patchwork/src/main/java/me/totalfreedom/utils/{ => container}/Identity.java (89%) rename Patchwork/src/main/java/me/totalfreedom/utils/{ => container}/Pair.java (52%) create mode 100644 Patchwork/src/main/java/me/totalfreedom/utils/container/Tuple.java create mode 100644 Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTuple.java rename Patchwork/src/main/java/me/totalfreedom/utils/{ => kyori}/FreedomAdventure.java (97%) rename Patchwork/src/main/java/me/totalfreedom/utils/{ => kyori}/FreedomMiniMessage.java (99%) rename Patchwork/src/main/java/me/totalfreedom/utils/{ => kyori}/KyoriConstants.java (98%) rename Patchwork/src/main/java/me/totalfreedom/utils/{ => logging}/FreedomLogger.java (98%) 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 5c767e8..ffe12f8 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java +++ b/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java @@ -2,7 +2,7 @@ package me.totalfreedom.datura.punishment; import me.totalfreedom.base.CommonsBase; import me.totalfreedom.service.Service; -import me.totalfreedom.utils.Shaper; +import me.totalfreedom.utils.ShapeUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -53,25 +53,25 @@ public class Cager extends Service /** * 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 + * We use the {@link ShapeUtils} class to generate the cube, which allows us to define * custom shapes using {@link DoubleUnaryOperator}s. * * @param location The location to center the cube around. * @param material The material to use for the cube. * @return The center location of the cube (the passed location). - * @see Shaper + * @see ShapeUtils * @see DoubleUnaryOperator */ public Location createCage(final Location location, final Material material) { - final Shaper shaper = new Shaper(location.getWorld(), 0.0, 4.0); + final ShapeUtils shapeUtils = new ShapeUtils(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)); + cubed.addAll(shapeUtils.generate(5, t -> t, t -> 4.0, t -> t)); + cubed.addAll(shapeUtils.generate(5, t -> t, t -> 0.0, t -> t)); + cubed.addAll(shapeUtils.generate(5, t -> 0.0, t -> t, t -> t)); + cubed.addAll(shapeUtils.generate(5, t -> 4.0, t -> t, t -> t)); + cubed.addAll(shapeUtils.generate(5, t -> t, t -> t, t -> 0.0)); + cubed.addAll(shapeUtils.generate(5, t -> t, t -> t, t -> 4.0)); for (final Location l : cubed) { 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 5827a8e..9097fb3 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java +++ b/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java @@ -2,7 +2,7 @@ package me.totalfreedom.datura.sql; import me.totalfreedom.base.CommonsBase; import me.totalfreedom.sql.SQL; -import me.totalfreedom.utils.Identity; +import me.totalfreedom.utils.container.Identity; import java.sql.Connection; import java.sql.DriverManager; 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 65df6a1..1b6f9ef 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java @@ -7,7 +7,7 @@ import me.totalfreedom.security.Group; import me.totalfreedom.sql.SQL; import me.totalfreedom.user.User; import me.totalfreedom.user.UserData; -import me.totalfreedom.utils.FreedomLogger; +import me.totalfreedom.utils.logging.FreedomLogger; import org.apache.commons.lang3.exception.ExceptionUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java b/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java index 6c7c364..304cc4c 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java @@ -25,7 +25,7 @@ import me.totalfreedom.command.Commander; import me.totalfreedom.command.annotation.Base; import me.totalfreedom.command.annotation.Info; import me.totalfreedom.command.annotation.Permissive; -import me.totalfreedom.utils.FreedomMiniMessage; +import me.totalfreedom.utils.kyori.FreedomMiniMessage; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.command.CommandSender; 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 7ebb9cc..80ba2d2 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionLogger.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionLogger.java @@ -5,7 +5,7 @@ import me.totalfreedom.economy.CompletedTransaction; import me.totalfreedom.economy.EconomicEntity; import me.totalfreedom.economy.TransactionLogger; import me.totalfreedom.economy.TransactionResult; -import me.totalfreedom.utils.FreedomLogger; +import me.totalfreedom.utils.logging.FreedomLogger; import net.kyori.adventure.text.Component; public class SimpleTransactionLogger implements TransactionLogger diff --git a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java index b6d6276..99c7464 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java @@ -4,7 +4,7 @@ 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 me.totalfreedom.utils.logging.FreedomLogger; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.World; diff --git a/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java b/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java index 2a923b1..26c5138 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/DisplayableView.java @@ -1,6 +1,6 @@ package me.totalfreedom.display; -import me.totalfreedom.utils.FreedomAdventure; +import me.totalfreedom.utils.kyori.FreedomAdventure; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; diff --git a/Patchwork/src/main/java/me/totalfreedom/particle/NoteWrapper.java b/Patchwork/src/main/java/me/totalfreedom/particle/NoteWrapper.java new file mode 100644 index 0000000..ef656ce --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/particle/NoteWrapper.java @@ -0,0 +1,157 @@ +package me.totalfreedom.particle; + +import org.bukkit.Particle; +import org.bukkit.World; + +import java.math.RoundingMode; +import java.text.DecimalFormat; + +/** + * A utility class for the 24 different note colors available in Minecraft. Each note is represented as a double value + * between 0 and 1. Furthermore, each note is a multiple of 1/24 within that range of 0 to 1. + *

+ * For example, the note G is represented as 1/24, or 0.042. The note C is represented as 6/24, or 0.25. + *

+ * When spawning particles, the count must be set to 0 and the extra value set between 0 and 1. The extra value is the + * size of the note particle. To add a color, use one of the provided methods in this class for the xOffset value in + * {@link World#spawnParticle(Particle, double, double, double, int, double, double, double, double)}. The xOffset value + * is the note color, with the yOffset and zOffset values set to 0. + */ +public final class NoteWrapper +{ + public static final double CYAN_NOTE_F_SHARP_LOW = 0; + public static final double CYAN_NOTE_F_SHARP_HIGH = 1; + + private static final DecimalFormat FORMAT; + + static + { + FORMAT = new DecimalFormat("#.###"); + FORMAT.setRoundingMode(RoundingMode.HALF_UP); + } + + private NoteWrapper() + { + throw new AssertionError(); + } + + private static double round(final double value) + { + return Double.parseDouble(FORMAT.format(value)); + } + + public static double cyanNoteG() + { + return round(1 / 24D); + } + + public static double grayNoteGSharp() + { + return round(2 / 24D); + } + + public static double grayNoteA() + { + return round(3 / 24D); + } + + public static double grayNoteASharp() + { + return round(4 / 24D); + } + + public static double magentaNoteB() + { + return round(5 / 24D); + } + + public static double redNoteC() + { + return round(6 / 24D); + } + + public static double yellowNoteCSharp() + { + return round(7 / 24D); + } + + public static double yellowNoteD() + { + return round(8 / 24D); + } + + public static double yellowNoteDSharpLow() + { + return round(9 / 24D); + } + + public static double grayNoteE() + { + return round(10 / 24D); + } + + public static double grayNoteF() + { + return round(11 / 24D); + } + + public static double grayNoteFSharp() + { + return round(12 / 24D); + } + + public static double lightBlueNoteG() + { + return round(13 / 24D); + } + + public static double blueNoteGSharp() + { + return round(14 / 24D); + } + + public static double purpleNoteA() + { + return round(15 / 24D); + } + + public static double purpleNoteASharp() + { + return round(16 / 24D); + } + + public static double purpleNoteB() + { + return round(17 / 24D); + } + + public static double grayNoteC() + { + return round(18 / 24D); + } + + public static double grayNoteCSharp() + { + return round(19 / 24D); + } + + public static double grayNoteD() + { + return round(20 / 24D); + } + + public static double yellowNoteDSharpHigh() + { + return round(21 / 24D); + } + + public static double greenNoteE() + { + return round(22 / 24D); + } + + public static double lightBlueNoteF() + { + return round(23 / 24D); + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/particle/TrailType.java b/Patchwork/src/main/java/me/totalfreedom/particle/TrailType.java index e37fae4..c0a5001 100644 --- a/Patchwork/src/main/java/me/totalfreedom/particle/TrailType.java +++ b/Patchwork/src/main/java/me/totalfreedom/particle/TrailType.java @@ -1,13 +1,34 @@ package me.totalfreedom.particle; +import org.bukkit.Note; import org.bukkit.Particle; public enum TrailType { + /** + * Default trail type. Uses {@link Particle#REDSTONE}. This trail is colorable. Use {@link Particle.DustOptions} to + * set the particle properties. + */ DEFAULT(Particle.REDSTONE), + /** + * A trail that uses {@link Particle#HEART}. This is not modifiable and will always have the same size shape and + * color. + */ HEART(Particle.HEART), + /** + * A trail that uses {@link Particle#FLAME}. This is not modifiable and will always have the same size shape and + * color. + */ FLAME(Particle.FLAME), + /** + * A trail that uses {@link Particle#REDSTONE}. This particle however is rainbow-colored by default and cannot have + * additional options set. + */ RAINBOW(Particle.REDSTONE), + /** + * A trail that uses {@link Particle#NOTE}. This is colorable, however you are limited to the 24 different note + * colors available in Minecraft. + */ MUSIC(Particle.NOTE), SNOW(Particle.SNOWBALL), SPELL(Particle.SPELL_MOB), diff --git a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java index 5d2b5e2..f7b7c0b 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java @@ -1,6 +1,6 @@ package me.totalfreedom.service; -import me.totalfreedom.utils.Pair; +import me.totalfreedom.utils.container.Pair; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitScheduler; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/Shaper.java b/Patchwork/src/main/java/me/totalfreedom/utils/ShapeUtils.java similarity index 90% rename from Patchwork/src/main/java/me/totalfreedom/utils/Shaper.java rename to Patchwork/src/main/java/me/totalfreedom/utils/ShapeUtils.java index 7f3dfdc..5a142a0 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/Shaper.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/ShapeUtils.java @@ -7,13 +7,13 @@ import java.util.LinkedList; import java.util.List; import java.util.function.DoubleUnaryOperator; -public class Shaper +public class ShapeUtils { private final double start; private final double end; private final World world; - public Shaper(final World world, final double start, final double end) + public ShapeUtils(final World world, final double start, final double end) { this.start = start; this.end = end; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/Identity.java b/Patchwork/src/main/java/me/totalfreedom/utils/container/Identity.java similarity index 89% rename from Patchwork/src/main/java/me/totalfreedom/utils/Identity.java rename to Patchwork/src/main/java/me/totalfreedom/utils/container/Identity.java index d186093..0770962 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/Identity.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/container/Identity.java @@ -1,4 +1,4 @@ -package me.totalfreedom.utils; +package me.totalfreedom.utils.container; import java.util.UUID; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/Pair.java b/Patchwork/src/main/java/me/totalfreedom/utils/container/Pair.java similarity index 52% rename from Patchwork/src/main/java/me/totalfreedom/utils/Pair.java rename to Patchwork/src/main/java/me/totalfreedom/utils/container/Pair.java index 9ab5e2f..0cf4e76 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/Pair.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/container/Pair.java @@ -1,4 +1,4 @@ -package me.totalfreedom.utils; +package me.totalfreedom.utils.container; public record Pair(K key, V value) { diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/container/Tuple.java b/Patchwork/src/main/java/me/totalfreedom/utils/container/Tuple.java new file mode 100644 index 0000000..794637d --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/utils/container/Tuple.java @@ -0,0 +1,30 @@ +package me.totalfreedom.utils.container; + +public final class Tuple +{ + private final A a; + private final B b; + private final C c; + + public Tuple(final A a, final B b, final C c) + { + this.a = a; + this.b = b; + this.c = c; + } + + public A getPrimary() + { + return a; + } + + public B getSecondary() + { + return b; + } + + public C getTertiary() + { + return c; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTuple.java b/Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTuple.java new file mode 100644 index 0000000..85bdee3 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTuple.java @@ -0,0 +1,30 @@ +package me.totalfreedom.utils.container; + +public class UnaryTuple +{ + private final T primary; + private final T secondary; + private final T tertiary; + + public UnaryTuple(final T primary, final T secondary, final T tertiary) + { + this.primary = primary; + this.secondary = secondary; + this.tertiary = tertiary; + } + + public T getPrimary() + { + return primary; + } + + public T getSecondary() + { + return secondary; + } + + public T getTertiary() + { + return tertiary; + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomAdventure.java b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomAdventure.java similarity index 97% rename from Patchwork/src/main/java/me/totalfreedom/utils/FreedomAdventure.java rename to Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomAdventure.java index 727869f..f24cbc7 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomAdventure.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomAdventure.java @@ -1,4 +1,4 @@ -package me.totalfreedom.utils; +package me.totalfreedom.utils.kyori; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomMiniMessage.java b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomMiniMessage.java similarity index 99% rename from Patchwork/src/main/java/me/totalfreedom/utils/FreedomMiniMessage.java rename to Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomMiniMessage.java index a3c1e34..e39552c 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomMiniMessage.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomMiniMessage.java @@ -19,7 +19,7 @@ * THE SOFTWARE. */ -package me.totalfreedom.utils; +package me.totalfreedom.utils.kyori; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextDecoration; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/KyoriConstants.java b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/KyoriConstants.java similarity index 98% rename from Patchwork/src/main/java/me/totalfreedom/utils/KyoriConstants.java rename to Patchwork/src/main/java/me/totalfreedom/utils/kyori/KyoriConstants.java index 46bb8d8..5ba62d5 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/KyoriConstants.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/KyoriConstants.java @@ -1,4 +1,4 @@ -package me.totalfreedom.utils; +package me.totalfreedom.utils.kyori; import me.totalfreedom.base.CommonsBase; import net.kyori.adventure.chat.ChatType; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java b/Patchwork/src/main/java/me/totalfreedom/utils/logging/FreedomLogger.java similarity index 98% rename from Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java rename to Patchwork/src/main/java/me/totalfreedom/utils/logging/FreedomLogger.java index 9fd27ad..2a093c4 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/FreedomLogger.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/logging/FreedomLogger.java @@ -1,5 +1,6 @@ -package me.totalfreedom.utils; +package me.totalfreedom.utils.logging; +import me.totalfreedom.utils.kyori.FreedomAdventure; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.chat.ChatType; import net.kyori.adventure.chat.SignedMessage; From bacf6e881843b22fe2ee82b8ca2498738ac1ef78 Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Fri, 9 Jun 2023 21:11:36 -0500 Subject: [PATCH 12/14] Beans --- .../totalfreedom/datura/cmd/CageCommand.java | 4 +- .../datura/cmd/LockerCommand.java | 2 +- .../datura/perms/DefaultNodes.java | 48 ++--- .../datura/perms/FreedomGroup.java | 63 +++--- .../datura/perms/FreedomUser.java | 10 +- .../datura/perms/PermissionNode.java | 10 +- .../totalfreedom/datura/punishment/Cager.java | 10 +- .../datura/punishment/Locker.java | 6 +- .../me/totalfreedom/datura/sql/MySQL.java | 183 +++++++++--------- .../datura/user/ServerEconomyHolder.java | 30 ++- .../datura/user/SimpleUserData.java | 103 +++++----- .../java/me/totalfreedom/fossil/Fossil.java | 2 +- .../fossil/bouncypads/PadHolder.java | 36 ++-- .../fossil/bouncypads/PadType.java | 4 +- .../totalfreedom/fossil/cmd/CakeCommand.java | 4 +- .../economy/SimpleTransactionResult.java | 10 +- .../fossil/reactions/CopyCatReaction.java | 13 +- .../fossil/trail/types/FlameTrail.java | 2 +- .../me/totalfreedom/api/Serializable.java | 9 +- .../me/totalfreedom/base/CommonsBase.java | 4 +- .../me/totalfreedom/base/Registration.java | 6 +- .../totalfreedom/command/BukkitDelegate.java | 4 +- .../totalfreedom/command/CommandHandler.java | 4 +- .../totalfreedom/command/annotation/Base.java | 4 +- .../totalfreedom/command/annotation/Info.java | 5 +- .../command/annotation/Subcommand.java | 9 +- .../me/totalfreedom/data/ConfigRegistry.java | 5 +- .../me/totalfreedom/data/EventRegistry.java | 4 +- .../me/totalfreedom/data/GroupRegistry.java | 3 + .../data/ServiceTaskRegistry.java | 51 +++-- .../me/totalfreedom/data/UserRegistry.java | 5 +- .../totalfreedom/display/BossBarDisplay.java | 9 + .../me/totalfreedom/display/ClickAction.java | 4 +- .../me/totalfreedom/display/TitleDisplay.java | 28 ++- .../totalfreedom/economy/EconomicEntity.java | 3 +- .../economy/EconomicEntityData.java | 13 +- .../economy/MutableTransaction.java | 3 +- .../logging/InteractionFormatter.java | 5 +- .../totalfreedom/particle/NoteColorUtil.java | 50 +++++ .../me/totalfreedom/particle/NoteWrapper.java | 157 --------------- .../java/me/totalfreedom/particle/Trail.java | 19 +- .../me/totalfreedom/particle/TrailType.java | 1 - .../provider/ContextProvider.java | 46 ++--- .../totalfreedom/service/FreedomExecutor.java | 8 +- .../java/me/totalfreedom/service/Task.java | 40 ++-- .../service/TaskSubscription.java | 8 +- .../me/totalfreedom/shop/ReactionTask.java | 32 +-- .../me/totalfreedom/sql/SQLProperties.java | 20 +- .../me/totalfreedom/utils/DurationTools.java | 2 +- .../utils/InterpolationUtils.java | 20 +- .../me/totalfreedom/utils/ShapeUtils.java | 2 +- .../utils/container/{Tuple.java => Trio.java} | 4 +- .../{UnaryTuple.java => UnaryTrio.java} | 4 +- .../utils/kyori/FreedomAdventure.java | 2 +- .../utils/kyori/FreedomMiniMessage.java | 21 +- .../utils/kyori/KyoriConstants.java | 24 ++- .../utils/logging/FreedomLogger.java | 51 +++-- README.md | 4 +- 58 files changed, 565 insertions(+), 668 deletions(-) create mode 100644 Patchwork/src/main/java/me/totalfreedom/particle/NoteColorUtil.java delete mode 100644 Patchwork/src/main/java/me/totalfreedom/particle/NoteWrapper.java rename Patchwork/src/main/java/me/totalfreedom/utils/container/{Tuple.java => Trio.java} (81%) rename Patchwork/src/main/java/me/totalfreedom/utils/container/{UnaryTuple.java => UnaryTrio.java} (81%) diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java index e8ad5c1..38b2050 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/CageCommand.java @@ -34,7 +34,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @Info(name = "cage", description = "Cage a player.", - usage = "/cage [material]") + usage = "/cage [material]") @Permissive(perm = "datura.cage") public class CageCommand extends Commander { @@ -68,7 +68,7 @@ public class CageCommand extends Commander @Completion(args = {"[material]"}, index = 2) @Subcommand(permission = "datura.cage.custom", args = {Player.class, String.class, Material.class}) public void cagePlayer(final CommandSender sender, final Player player, final String string, - final Material material) + final Material material) { switch (string.toLowerCase()) { diff --git a/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java b/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java index f346e83..38f9f2c 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java +++ b/Datura/src/main/java/me/totalfreedom/datura/cmd/LockerCommand.java @@ -11,7 +11,7 @@ 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"}) + usage = "/locker ", aliases = {"lock", "lockup"}) @Permissive(perm = "datura.locker") public final class LockerCommand extends Commander { 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 5119871..6357cdc 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/DefaultNodes.java @@ -6,33 +6,33 @@ import me.totalfreedom.security.NodeType; public class DefaultNodes { public static final Node OP = new PermissionNodeBuilder() - .key("freedom.master_key") - .value(true) - .type(NodeType.PERMISSION) - .negated(false) - .wildcard(true) - .build(); + .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(); + .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(); + .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(); + .key("freedom.none") + .value(true) + .type(NodeType.PERMISSION) + .negated(false) + .wildcard(false) + .build(); private DefaultNodes() { diff --git a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomGroup.java index 6e9a6d6..a2ccc5d 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; @@ -121,11 +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(); } @@ -146,30 +146,29 @@ 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(); } /** - * Adds a permission to the relative PermissionAttachment for this group. - * This method is not thread-safe and should not be called asynchronously. + * Adds a permission to the relative PermissionAttachment for this group. This method is not thread-safe and should + * not be called asynchronously. *

* This method is only here for compatibility with the Bukkit API. * - * @param plugin The plugin responsible for this attachment. May not be null - * or disabled. + * @param plugin The plugin responsible for this attachment. May not be null or disabled. * @param name Name of the permission to attach * @param value Value of the permission * @return This group's PermissionAttachment. */ @Override public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, - final boolean value) + final boolean value) { attachment.setPermission(name, value); return attachment; @@ -183,7 +182,7 @@ public class FreedomGroup implements Group @Override public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, - final boolean value, final int ticks) + final boolean value, final int ticks) { attachment.setPermission(name, value); return attachment; @@ -211,23 +210,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 50a716b..3f1510f 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/FreedomUser.java @@ -23,9 +23,9 @@ import java.util.Set; import java.util.UUID; /** - * The superinterface User extends PermissionHolder, - * which is an extension of {@link org.bukkit.permissions.Permissible}. - * This means that our permission data can be interchanged with other permission plugins. + * The superinterface User extends PermissionHolder, which is an extension of + * {@link org.bukkit.permissions.Permissible}. This means that our permission data can be interchanged with other + * permission plugins. */ public class FreedomUser implements User { @@ -139,7 +139,7 @@ public class FreedomUser implements User @Override public @NotNull PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, - final boolean value) + final boolean value) { final Player player = Bukkit.getPlayer(uuid); if (player != null) @@ -164,7 +164,7 @@ public class FreedomUser implements User @Override public @Nullable PermissionAttachment addAttachment(@NotNull final Plugin plugin, @NotNull final String name, - final boolean value, final int ticks) + 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 2a88f40..48870b9 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java +++ b/Datura/src/main/java/me/totalfreedom/datura/perms/PermissionNode.java @@ -16,9 +16,9 @@ record PermissionNode(String key, public Permission bukkit() { return new Permission(key(), - value() - ? PermissionDefault.TRUE - : PermissionDefault.FALSE); + value() + ? PermissionDefault.TRUE + : PermissionDefault.FALSE); } @Override @@ -26,8 +26,8 @@ record PermissionNode(String key, { return node.key() .equalsIgnoreCase(key()) - && node.value() == value() - && node.type() == type(); + && node.value() == value() + && node.type() == type(); } @Override 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 ffe12f8..52920aa 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java +++ b/Datura/src/main/java/me/totalfreedom/datura/punishment/Cager.java @@ -51,10 +51,9 @@ public class Cager extends Service } /** - * This method generates a cube centered around the passed location, - * made of the provided material. This method returns the passed location object. - * We use the {@link ShapeUtils} class to generate the cube, which allows us to define - * custom shapes using {@link DoubleUnaryOperator}s. + * This method generates a cube centered around the passed location, made of the provided material. This method + * returns the passed location object. We use the {@link ShapeUtils} class to generate the cube, which allows us to + * define custom shapes using {@link DoubleUnaryOperator}s. * * @param location The location to center the cube around. * @param material The material to use for the cube. @@ -108,8 +107,7 @@ public class Cager extends Service } /** - * This method will check to make sure each caged player remains within their cage. - * We use + * This method will check to make sure each caged player remains within their cage. We use *

* {@link Location#distanceSquared(Location)} * {@link Math#pow(double, double)} *

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 4aa2eca..9e1e027 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/punishment/Locker.java +++ b/Datura/src/main/java/me/totalfreedom/datura/punishment/Locker.java @@ -81,9 +81,9 @@ public class Locker extends Service 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) + 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/MySQL.java b/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java index 9097fb3..9446e08 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java +++ b/Datura/src/main/java/me/totalfreedom/datura/sql/MySQL.java @@ -29,8 +29,7 @@ public class MySQL implements SQL } /** - * Adds credentials to the MySQL URL. - * If the URL already contains credentials, they will be overwritten. + * Adds credentials to the MySQL URL. If the URL already contains credentials, they will be overwritten. * * @param username The username to add * @param password The password to add @@ -61,25 +60,24 @@ public class MySQL implements SQL public CompletableFuture prepareStatement(final String query, final Object... args) { return getConnection() - .thenApplyAsync(connection -> - { - try - { - final PreparedStatement statement = connection.prepareStatement(query); - for (int i = 0; i < args.length; i++) - { - statement.setObject(i + 1, args[i]); - } - return statement; - } - catch (SQLException ex) - { - throw new CompletionException("Failed to prepare statement: " - + query + "\n", ex); - } - }, CommonsBase.getInstance() - .getExecutor() - .getAsync()); + .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() @@ -89,11 +87,10 @@ public class MySQL implements SQL try { return DriverManager.getConnection(url.toString()); - } - catch (SQLException ex) + } catch (SQLException ex) { throw new CompletionException("Failed to connect to the database: " - + url.toString() + "\n", ex); + + url.toString() + "\n", ex); } }, CommonsBase.getInstance() .getExecutor() @@ -104,61 +101,58 @@ public class MySQL implements SQL 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 @@ -181,46 +175,45 @@ public class MySQL implements SQL } public CompletableFuture getColumn(final String table, final String column, final String key, - final Identity identity, final Class type) + 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()); + .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) + 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()); + .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()); + .thenApplyAsync(result -> result > 0, CommonsBase.getInstance() + .getExecutor() + .getAsync()); } public CompletableFuture insertRow(final String table, final Object... values) diff --git a/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java b/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java index e9771f3..768ac91 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/ServerEconomyHolder.java @@ -7,18 +7,16 @@ import me.totalfreedom.economy.EconomicEntityData; * Represents the server's economy holder. *
*
- * This is effectively a Bank object which is meant to represent the server itself, - * which can store a balance and perform transactions with other EconomicEntity objects. + * This is effectively a Bank object which is meant to represent the server itself, which can store a balance and + * perform transactions with other EconomicEntity objects. *
*
- * The server is initially given a maximum balance of {@link Long#MAX_VALUE}, though this can be changed - * using the constructor {@link #ServerEconomyHolder(String, long)}. The value that this - * bank object holds is persistent, which means that the total economic resources available - * are of limited supply. + * The server is initially given a maximum balance of {@link Long#MAX_VALUE}, though this can be changed using the + * constructor {@link #ServerEconomyHolder(String, long)}. The value that this bank object holds is persistent, which + * means that the total economic resources available are of limited supply. *
*
- * Please be aware, if the server's economy falls below 0, - * it will have drastic consequences. + * Please be aware, if the server's economy falls below 0, it will have drastic consequences. */ public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData { @@ -49,9 +47,9 @@ public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData } /** - * This method will return this object, as it is both the EconomicEntity and the EconomicEntityData. - * This is due to the fact that the server should only ever have one singular concrete representation - * of it's economic entity and the respective data. + * This method will return this object, as it is both the EconomicEntity and the EconomicEntityData. This is due to + * the fact that the server should only ever have one singular concrete representation of it's economic entity and + * the respective data. * * @return this object. */ @@ -71,8 +69,7 @@ public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData } /** - * This method will always return false, as the server should not ever be - * prevented from performing transactions. + * This method will always return false, as the server should not ever be prevented from performing transactions. * * @return false */ @@ -103,8 +100,7 @@ public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData } /** - * Adds the specified amount to the server's balance. - * This method mutates the balance and returns the new balance. + * Adds the specified amount to the server's balance. This method mutates the balance and returns the new balance. * * @param amount The amount to add. * @return The new balance. @@ -117,8 +113,8 @@ public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData } /** - * Removes the specified amount from the server's balance. - * This method mutates the balance and returns the new balance. + * Removes the specified amount from the server's balance. This method mutates the balance and returns the new + * balance. * * @param amount The amount to remove. * @return The new balance. 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 1b6f9ef..014876c 100644 --- a/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java +++ b/Datura/src/main/java/me/totalfreedom/datura/user/SimpleUserData.java @@ -42,14 +42,14 @@ public class SimpleUserData implements UserData } private SimpleUserData( - final UUID uuid, - final String username, - final User user, - final Group group, - final long playtime, - final boolean canInteract, - final long balance, - final boolean transactionsFrozen) + final UUID uuid, + final String username, + final User user, + final Group group, + final long playtime, + final boolean canInteract, + final long balance, + final boolean transactionsFrozen) { this.uuid = uuid; this.username = username; @@ -66,57 +66,56 @@ public class SimpleUserData implements UserData return sql.executeQuery("SELECT * FROM users WHERE UUID = ?", uuid) .thenApplyAsync(result -> { - try - { - if (result.next()) - { - final String g = result.getString("group"); + 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 canInteract = result.getBoolean("canInteract"); - final long balance = result.getLong("balance"); - final boolean transactionsFrozen = result.getBoolean("transactionsFrozen"); - - return new SimpleUserData(u, username, user, group, playtime, - canInteract, balance, transactionsFrozen); - } - } - catch (SQLException ex) - { - final String sb = "An error occurred while trying to retrieve user data for" + - " UUID " + - uuid + - " from the database." + - "\nCaused by: " + - ExceptionUtils.getRootCauseMessage(ex) + - "\nStack trace: " + - ExceptionUtils.getStackTrace(ex); + final long playtime = result.getLong("playtime"); + final boolean canInteract = result.getBoolean("canInteract"); + final long balance = result.getLong("balance"); + final boolean transactionsFrozen = result.getBoolean("transactionsFrozen"); - FreedomLogger.getLogger("Datura") - .error(sb); - } + return new SimpleUserData(u, username, user, group, playtime, + canInteract, balance, transactionsFrozen); + } + } catch (SQLException ex) + { + final String sb = "An error occurred while trying to retrieve user data for" + + " UUID " + + uuid + + " from the database." + + "\nCaused by: " + + ExceptionUtils.getRootCauseMessage(ex) + + "\nStack trace: " + + ExceptionUtils.getStackTrace(ex); - 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()) + 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(); } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java b/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java index 8d789f8..18dc7fb 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/Fossil.java @@ -20,6 +20,6 @@ public class Fossil extends JavaPlugin registration.getServiceTaskRegistry() .registerService( - SubscriptionProvider.syncService(this, trailer)); + SubscriptionProvider.syncService(this, trailer)); } } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadHolder.java b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadHolder.java index 829739d..cd4842e 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadHolder.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadHolder.java @@ -32,17 +32,18 @@ public class PadHolder implements Listener */ public PadHolder() { - Bukkit.getPluginManager().registerEvents(this, CommonsBase - .getInstance() - .getRegistrations() - .getModuleRegistry() - .getProvider(Fossil.class) - .getModule()); + Bukkit.getPluginManager() + .registerEvents(this, CommonsBase + .getInstance() + .getRegistrations() + .getModuleRegistry() + .getProvider(Fossil.class) + .getModule()); } /** - * Adds a pad for the given player. If the player already has a pad stored in the map, - * it will be overwritten with the new pad. + * Adds a pad for the given player. If the player already has a pad stored in the map, it will be overwritten with + * the new pad. * * @param player The player to add the pad for. * @param pad The pad to add. @@ -63,8 +64,8 @@ public class PadHolder implements Listener } /** - * Gets the pad for the given player, if the player has one. - * If the player has no active pad, this will return null. + * Gets the pad for the given player, if the player has one. If the player has no active pad, this will return + * null. * * @param player The player to get the pad for. * @return The pad for the given player. @@ -98,8 +99,8 @@ public class PadHolder implements Listener /** * Handles player pad interaction. This will check the relative block for each acceptible direction, and pass the - * resulting block face (if any) to the bounce pad. See {@link BouncyPad#bouncePad(Player, org.bukkit.block.BlockFace)} - * for how the resulting block face is processed. + * resulting block face (if any) to the bounce pad. See + * {@link BouncyPad#bouncePad(Player, org.bukkit.block.BlockFace)} for how the resulting block face is processed. * * @param event The event which gets called when a player moves. */ @@ -122,10 +123,10 @@ public class PadHolder implements Listener final Block yNeg1 = getRelative(location, 0, -1, 0); Stream.of(xNeg1, xPos1, zNeg1, zPos1, yNeg1) - .filter(this::isWool) - .map(block -> block.getFace(location.getBlock())) - .findFirst() - .ifPresent(face -> pad.bouncePad(player, face)); + .filter(this::isWool) + .map(block -> block.getFace(location.getBlock())) + .findFirst() + .ifPresent(face -> pad.bouncePad(player, face)); } /** @@ -139,7 +140,8 @@ public class PadHolder implements Listener */ private Block getRelative(final Location location, final int x, final int y, final int z) { - return location.getBlock().getRelative(x, y, z); + return location.getBlock() + .getRelative(x, y, z); } /** diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadType.java b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadType.java index 1cc0f66..2c58591 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadType.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/bouncypads/PadType.java @@ -12,8 +12,8 @@ public enum PadType */ NORMAL, /** - * A pad which will bounce the player on {@link BlockFace#NORTH}, {@link BlockFace#SOUTH}, {@link BlockFace#EAST} - * or {@link BlockFace#WEST}. + * A pad which will bounce the player on {@link BlockFace#NORTH}, {@link BlockFace#SOUTH}, {@link BlockFace#EAST} or + * {@link BlockFace#WEST}. */ SIDES, /** diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java b/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java index 304cc4c..7a5c7b0 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/cmd/CakeCommand.java @@ -47,8 +47,8 @@ public class CakeCommand extends Commander public void broadcastCake(final CommandSender sender) { Bukkit.broadcast(FreedomMiniMessage.deserialize(true, - "But there's no sense crying over every mistake. You just keep on trying till you run out of " + - "cake.")); + "But there's no sense crying over every mistake. You just keep on trying till you run out of " + + "cake.")); final ItemStack stack = new ItemStack(Material.CAKE, 1); final ItemMeta meta = stack.getItemMeta(); 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 eeb629c..e0ee389 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionResult.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/economy/SimpleTransactionResult.java @@ -8,11 +8,11 @@ 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); + false); public static final TransactionResult AMOUNT_TOO_SMALL = new SimpleTransactionResult( - "Transaction balance too small.", false); + "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); + "The source has an insufficient balance to carry out this transaction.", false); private final String message; private final Component component; private final boolean successful; @@ -20,8 +20,8 @@ public class SimpleTransactionResult implements TransactionResult public SimpleTransactionResult(final String message, final boolean successful) { this(message, Component.text(message, successful - ? NamedTextColor.GREEN - : NamedTextColor.RED), 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/reactions/CopyCatReaction.java b/Fossil/src/main/java/me/totalfreedom/fossil/reactions/CopyCatReaction.java index 983e5b4..52460e8 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/reactions/CopyCatReaction.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/reactions/CopyCatReaction.java @@ -38,18 +38,21 @@ public final class CopyCatReaction extends Reaction @Override public void display(final Audience audience) { - final BossBar bossBar = BossBarDisplay.builder().setName(getRandomCharacterString()) - .setProgress(0.0F) - .build(); + final BossBar bossBar = BossBarDisplay.builder() + .setName(getRandomCharacterString()) + .setProgress(0.0F) + .build(); } - public String getRandomCharacterString() { + public String getRandomCharacterString() + { final SplittableRandom random = new SplittableRandom(); final StringBuilder sb = new StringBuilder(10); final String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) + { sb.append(chars.charAt(random.nextInt(chars.length()))); } diff --git a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java index d8e7ba9..2fe823e 100644 --- a/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java +++ b/Fossil/src/main/java/me/totalfreedom/fossil/trail/types/FlameTrail.java @@ -24,6 +24,6 @@ public final class FlameTrail extends SimpleTrail final Vector direction = location.getDirection(); location.getWorld() .spawnParticle(getTrailType().getType(), location, 0, direction.getX(), direction.getY(), - direction.getZ(), 0.1); + direction.getZ(), 0.1); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/api/Serializable.java b/Patchwork/src/main/java/me/totalfreedom/api/Serializable.java index 41ab562..3dc62a6 100644 --- a/Patchwork/src/main/java/me/totalfreedom/api/Serializable.java +++ b/Patchwork/src/main/java/me/totalfreedom/api/Serializable.java @@ -1,17 +1,15 @@ package me.totalfreedom.api; /** - * This interface represents a Serializable object. - * Objects which require custom serialization and cannot simply override or call - * the default {@link Object#toString()} method should implement this interface. + * This interface represents a Serializable object. Objects which require custom serialization and cannot simply + * override or call the default {@link Object#toString()} method should implement this interface. * * @param The type of object to serialize */ public interface Serializable { /** - * Serialize an object to a string. - * Ideally, this should serialize to an SQL query for easy data transfer. + * Serialize an object to a string. Ideally, this should serialize to an SQL query for easy data transfer. * * @param object The object to serialize * @return The serialized object @@ -20,6 +18,7 @@ public interface Serializable /** * Deserialize an object from a Serialized string.. + * * @param serializedObject The serialized object * @return The deserialized object */ diff --git a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java index 911086e..69bade0 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/CommonsBase.java @@ -25,8 +25,8 @@ public class CommonsBase extends JavaPlugin private final FreedomExecutor executor = new FreedomExecutor(); /** - * Provides this plugin instance through a safe static method. - * This is effectively the same thing as using {@link JavaPlugin#getPlugin(Class)} + * Provides this plugin instance through a safe static method. This is effectively the same thing as using + * {@link JavaPlugin#getPlugin(Class)} * * @return the plugin instance */ diff --git a/Patchwork/src/main/java/me/totalfreedom/base/Registration.java b/Patchwork/src/main/java/me/totalfreedom/base/Registration.java index 1f5cf6c..e697fe9 100644 --- a/Patchwork/src/main/java/me/totalfreedom/base/Registration.java +++ b/Patchwork/src/main/java/me/totalfreedom/base/Registration.java @@ -10,9 +10,9 @@ import me.totalfreedom.data.UserRegistry; /** * This class is a holder for each registry in the data package. *
- * Registries such as {@link ModuleRegistry} and {@link ServiceTaskRegistry} - * can be found as final objects in this class. These registries should only ever be accessed through - * the single Registration object in CommonsBase using {@link CommonsBase#getRegistrations()} + * Registries such as {@link ModuleRegistry} and {@link ServiceTaskRegistry} can be found as final objects in this + * class. These registries should only ever be accessed through the single Registration object in CommonsBase using + * {@link CommonsBase#getRegistrations()} */ public class Registration { diff --git a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java index 99c7464..0a740d6 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/BukkitDelegate.java @@ -25,8 +25,8 @@ import java.util.Set; /** * This class is acts as a delegate between our custom command implementation and the Bukkit API. *
- * This class is not meant to be used directly, and is only public to allow for the Bukkit API to access it. - * As a result, this file will remain undocumented. + * This class is not meant to be used directly, and is only public to allow for the Bukkit API to access it. As a + * result, this file will remain undocumented. * *
* This class is not thread-safe. diff --git a/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java b/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java index 34c754d..cfcdd90 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/CommandHandler.java @@ -5,8 +5,8 @@ import org.bukkit.command.CommandMap; import org.bukkit.plugin.java.JavaPlugin; /** - * Handles the registration of commands. - * The plugin which initializes this class should be the plugin that is registering the commands. + * Handles the registration of commands. The plugin which initializes this class should be the plugin that is + * registering the commands. */ public class CommandHandler { diff --git a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Base.java b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Base.java index cd76252..c230186 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Base.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Base.java @@ -4,8 +4,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * This annotation is used to mark a method as the command's default method. - * This is the method that will be run to execute the command when a user inputs /{command} + * This annotation is used to mark a method as the command's default method. This is the method that will be run to + * execute the command when a user inputs /{command} */ @Retention(RetentionPolicy.RUNTIME) public @interface Base diff --git a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Info.java b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Info.java index fd90d82..5ab0bbc 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Info.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Info.java @@ -11,9 +11,8 @@ import java.lang.annotation.RetentionPolicy; public @interface Info { /** - * Technically, this is the only required value you must supply yourself. - * However, it is HIGHLY recommended you supply the other optional values as well, - * for better customization of your command. + * Technically, this is the only required value you must supply yourself. However, it is HIGHLY recommended you + * supply the other optional values as well, for better customization of your command. * * @return The command's name. */ 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 9a3b8c7..b203761 100644 --- a/Patchwork/src/main/java/me/totalfreedom/command/annotation/Subcommand.java +++ b/Patchwork/src/main/java/me/totalfreedom/command/annotation/Subcommand.java @@ -9,11 +9,10 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * This annotation should be used to mark methods as subcommand methods. - * Subcommand methods can have custom arguments (current supported arguments can be found in the {@link ContextProvider}), - * and can also have a custom permission. These subcommands can also be annotated with {@link Completions} to provide - * tab completions for the subcommand. The subcommand method must be public, and must be in a class that is registered - * with the {@link CommandHandler}. + * This annotation should be used to mark methods as subcommand methods. Subcommand methods can have custom arguments + * (current supported arguments can be found in the {@link ContextProvider}), and can also have a custom permission. + * These subcommands can also be annotated with {@link Completions} to provide tab completions for the subcommand. The + * subcommand method must be public, and must be in a class that is registered with the {@link CommandHandler}. *
* Tab completions with the {@link Completions} annotation are only supported for subcommands. When registering * completions, you only need to define the completion arguments a single time. If there are other methods which diff --git a/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java index 8f6b9e9..7db90f2 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/ConfigRegistry.java @@ -17,7 +17,8 @@ public class ConfigRegistry /** * Registers a configuration. - * @param name The name of the configuration. + * + * @param name The name of the configuration. * @param configuration The configuration. */ public void register(final String name, final Configuration configuration) @@ -27,6 +28,7 @@ public class ConfigRegistry /** * Unregisters a configuration. + * * @param name The name of the configuration. */ public void unregister(final String name) @@ -36,6 +38,7 @@ public class ConfigRegistry /** * Gets a configuration. + * * @param name The name of the configuration. * @return The configuration. */ diff --git a/Patchwork/src/main/java/me/totalfreedom/data/EventRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/EventRegistry.java index 99f7271..c5fb292 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/EventRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/EventRegistry.java @@ -26,6 +26,7 @@ public class EventRegistry /** * Registers an event. + * * @param event The event to register. */ public void register(final FEvent event) @@ -35,6 +36,7 @@ public class EventRegistry /** * Unregisters an event. + * * @param event The event to unregister. */ public void unregister(final FEvent event) @@ -46,8 +48,8 @@ public class EventRegistry * Gets an {@link EventProvider} for the specified event class which contains the actual {@link FEvent} instance. * * @param clazz The event class. + * @param The event type. * @return The event provider. - * @param The event type. */ public EventProvider getEvent(final Class clazz) { diff --git a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java index 96ae921..aec9b76 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/GroupRegistry.java @@ -26,6 +26,7 @@ public class GroupRegistry /** * Registers a group. + * * @param group The group to register. * @return {@code true} if the group was registered, {@code false} otherwise. */ @@ -36,6 +37,7 @@ public class GroupRegistry /** * Unregisters a group. + * * @param group The group to unregister. * @return {@code true} if the group was unregistered, {@code false} otherwise. */ @@ -46,6 +48,7 @@ public class GroupRegistry /** * Gets a group by name. + * * @param name The name of the group. * @return The group, or {@code null} if no group was found. */ diff --git a/Patchwork/src/main/java/me/totalfreedom/data/ServiceTaskRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/ServiceTaskRegistry.java index 4a1b191..2cf3e8d 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/ServiceTaskRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/ServiceTaskRegistry.java @@ -21,9 +21,8 @@ import java.util.List; *
*
* Tasks are runnable tasks which execute at the provided times in the {@link Task} and - * {@link TaskSubscription} classes. These define whether the Task is repeating, delayed, or just a one-time task. - * Tasks are registered using {@link #registerTask(TaskSubscription)} and can be started using - * {@link #startTask(Class)}. + * {@link TaskSubscription} classes. These define whether the Task is repeating, delayed, or just a one-time task. Tasks + * are registered using {@link #registerTask(TaskSubscription)} and can be started using {@link #startTask(Class)}. *
*
* ServiceSubscriptions and TaskSubscriptions can both be easily obtained using the @@ -59,16 +58,14 @@ public class ServiceTaskRegistry /** * Starts all services registered with the registry. *
- * This method should be avoided, due to the fact that modules may have registered their services - * after this method - * has already been called. In this case, it is preferred to start - * each service using {@link #startService(Class)}. + * This method should be avoided, due to the fact that modules may have registered their services after + * this method has already been called. In this case, it is preferred to start each service using + * {@link #startService(Class)}. *
* However, Patchwork calls this method when the server is starting up, as Patchwork is the central - * resource - * manager for registered tasks and services. Patchwork will call this method on the first server tick, so unless - * you are registering services AND starting them POST WORLD, you do not need to worry about starting - * your services. + * resource manager for registered tasks and services. Patchwork will call this method on the first server tick, so + * unless you are registering services AND starting them POST WORLD, you do not need to worry about + * starting your services. */ public void startAllServices() { @@ -82,16 +79,13 @@ public class ServiceTaskRegistry * Starts all tasks registered with the registry. *
* This method should be avoided, due to the fact that modules may have registered their tasks after - * this method - * has already been called. In this case, it is preferred to start - * each task - * using {@link #startTask(Class)}. + * this method has already been called. In this case, it is preferred to start each task using + * {@link #startTask(Class)}. *
* However, Patchwork calls this method when the server is starting up, as Patchwork is the central - * resource - * manager for registered tasks and services. Patchwork will call this method on the first server tick, so unless - * you are registering tasks AND starting them POST WORLD, you do not need to worry about starting - * your tasks. + * resource manager for registered tasks and services. Patchwork will call this method on the first server tick, so + * unless you are registering tasks AND starting them POST WORLD, you do not need to worry about + * starting your tasks. */ public void startAllTasks() { @@ -105,13 +99,13 @@ public class ServiceTaskRegistry * Stops all services registered with the registry. *
* This method should be avoided, due to the fact that modules should be handling their own - * registrations. - * It is preferred to use {@link #stopService(Class)} for each service you would like to stop. + * registrations. It is preferred to use {@link #stopService(Class)} for each service you would like to + * stop. *
* However, Patchwork calls this method when the server is shutting down, or when Patchwork is being - * disabled, as Patchwork is the central resource manager for registered tasks and services. - * Unless you are modifying service states while the server is running, you do not need to worry about - * disabling or unregistering your services. + * disabled, as Patchwork is the central resource manager for registered tasks and services. Unless you are + * modifying service states while the server is running, you do not need to worry about disabling or + * unregistering your services. */ public void stopAllServices() { @@ -125,13 +119,12 @@ public class ServiceTaskRegistry * Stops all tasks registered with the registry. *
* This method should be avoided, due to the fact that modules should be handling their own - * registrations. - * It is preferred to use {@link #stopTask(Class)} for each task you would like to stop. + * registrations. It is preferred to use {@link #stopTask(Class)} for each task you would like to stop. *
* However, Patchwork calls this method when the server is shutting down, or when Patchwork is being - * disabled, as Patchwork is the central resource manager for registered tasks and services. - * Unless you are modifying task states while the server is running, you do not need to worry about - * disabling or unregistering your tasks. + * disabled, as Patchwork is the central resource manager for registered tasks and services. Unless you are + * modifying task states while the server is running, you do not need to worry about disabling or + * unregistering your tasks. */ public void stopAllTasks() { diff --git a/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java b/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java index 184e140..64bf824 100644 --- a/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java +++ b/Patchwork/src/main/java/me/totalfreedom/data/UserRegistry.java @@ -71,7 +71,8 @@ public class UserRegistry /** * Registers the given {@link User} and {@link UserData} objects. - * @param user The {@link User} to register. + * + * @param user The {@link User} to register. * @param userData The {@link UserData} to register. */ public void registerUserData(final User user, final UserData userData) @@ -81,6 +82,7 @@ public class UserRegistry /** * Unregisters the given {@link User} and {@link UserData} objects. + * * @param user The {@link User} to unregister. */ public void unregisterUserData(final User user) @@ -90,6 +92,7 @@ public class UserRegistry /** * Gets the map of {@link User} objects to {@link UserData} objects. + * * @return The map of {@link User} objects to {@link UserData} objects. */ public Map getUserDataMap() diff --git a/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java b/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java index 6ef8948..2239b4b 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/BossBarDisplay.java @@ -275,6 +275,7 @@ public class BossBarDisplay /** * Adds a flag to the boss bar. + * * @param flag The flag to add. * @return The builder. */ @@ -286,6 +287,7 @@ public class BossBarDisplay /** * Adds multiple flags to the boss bar. + * * @param flags The flags to add. * @return The builder. */ @@ -297,6 +299,7 @@ public class BossBarDisplay /** * Removes a flag from the boss bar. + * * @param flag The flag to remove. * @return The builder. */ @@ -308,6 +311,7 @@ public class BossBarDisplay /** * Removes multiple flags from the boss bar. + * * @param flags The flags to remove. * @return The builder. */ @@ -319,6 +323,7 @@ public class BossBarDisplay /** * Clears all flags from the boss bar. + * * @return The builder. */ public BossBarBuilder clearFlags() @@ -329,6 +334,7 @@ public class BossBarDisplay /** * Sets the color of the boss bar. + * * @param color The color of the boss bar. * @return The builder. */ @@ -340,6 +346,7 @@ public class BossBarDisplay /** * Sets the overlay of the boss bar. + * * @param overlay The overlay of the boss bar. * @return The builder. */ @@ -351,6 +358,7 @@ public class BossBarDisplay /** * Sets the progress of the boss bar. This must satisfy {@code 0 <= progress <= 100}. + * * @param progress The progress of the boss bar. * @return The builder. */ @@ -362,6 +370,7 @@ public class BossBarDisplay /** * Builds the boss bar. + * * @return The {@link BossBar}. */ public BossBar build() diff --git a/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java b/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java index a7816c7..70aa1ad 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/ClickAction.java @@ -3,13 +3,15 @@ package me.totalfreedom.display; import org.bukkit.entity.Player; /** - * Represents an action to be performed when a player clicks on an inventory slot in the respective {@link AbstractMenu}. + * Represents an action to be performed when a player clicks on an inventory slot in the respective + * {@link AbstractMenu}. */ @FunctionalInterface public interface ClickAction { /** * Called when a player clicks on an inventory slot in the respective {@link AbstractMenu}. + * * @param player The player who clicked. */ void onClick(final Player player); diff --git a/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java b/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java index a5110bd..b6bf7cc 100644 --- a/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java +++ b/Patchwork/src/main/java/me/totalfreedom/display/TitleDisplay.java @@ -20,6 +20,7 @@ public class TitleDisplay /** * Creates a new {@link TitleDisplay} with the given {@link Title}. + * * @param title The {@link Title} to display. */ public TitleDisplay(final Title title) @@ -37,6 +38,7 @@ public class TitleDisplay /** * Displays the {@link Title} to the given {@link Audience}. + * * @param audience The {@link Audience} to display the {@link Title} to. */ public void displayTo(final Audience audience) @@ -55,6 +57,7 @@ public class TitleDisplay /** * Sets the {@link Title} to display. + * * @param title The {@link Title} to display. */ public void setTitle(final Title title) @@ -64,6 +67,7 @@ public class TitleDisplay /** * Displays the {@link Title} to the given {@link ForwardingAudience}. + * * @param forwardingAudience The {@link ForwardingAudience} to display the {@link Title} to. */ public void displayForwarded(final ForwardingAudience forwardingAudience) @@ -99,8 +103,7 @@ public class TitleDisplay private Duration displayDuration; /** - * Creates a new {@link TitleBuilder} with default values. - * The default values are: + * Creates a new {@link TitleBuilder} with default values. The default values are: *

    *
  • Empty main title
  • *
  • Empty subtitle
  • @@ -108,6 +111,7 @@ public class TitleDisplay *
  • Default fade out time
  • *
  • Default display duration
  • *
+ * * @see Title#DEFAULT_TIMES */ public TitleBuilder() @@ -121,6 +125,7 @@ public class TitleDisplay /** * Sets the main title of the {@link Title}. + * * @param title The main title of the {@link Title}. * @return The {@link TitleBuilder} instance. */ @@ -132,7 +137,8 @@ public class TitleDisplay /** * Sets the main title of the {@link Title}. - * @param title The main title of the {@link Title}. + * + * @param title The main title of the {@link Title}. * @param titleColor The color of the main title. * @return The {@link TitleBuilder} instance. */ @@ -144,6 +150,7 @@ public class TitleDisplay /** * Sets the main title of the {@link Title}. + * * @param mainTitle The main title of the {@link Title}. * @return The {@link TitleBuilder} instance. */ @@ -155,6 +162,7 @@ public class TitleDisplay /** * Sets the subtitle of the {@link Title}. + * * @param title The subtitle of the {@link Title}. * @return The {@link TitleBuilder} instance. */ @@ -166,7 +174,8 @@ public class TitleDisplay /** * Sets the subtitle of the {@link Title}. - * @param title The subtitle of the {@link Title}. + * + * @param title The subtitle of the {@link Title}. * @param titleColor The color of the subtitle. * @return The {@link TitleBuilder} instance. */ @@ -178,6 +187,7 @@ public class TitleDisplay /** * Sets the subtitle of the {@link Title}. + * * @param subTitle The subtitle of the {@link Title}. * @return The {@link TitleBuilder} instance. */ @@ -189,6 +199,7 @@ public class TitleDisplay /** * Sets the fade in time of the {@link Title}. + * * @param duration The fade in time of the {@link Title}. * @return The {@link TitleBuilder} instance. */ @@ -200,6 +211,7 @@ public class TitleDisplay /** * Sets the fade out time of the {@link Title}. + * * @param duration The fade out time of the {@link Title}. * @return The {@link TitleBuilder} instance. */ @@ -211,6 +223,7 @@ public class TitleDisplay /** * Sets the display duration of the {@link Title}. + * * @param duration The display duration of the {@link Title}. * @return The {@link TitleBuilder} instance. */ @@ -222,14 +235,15 @@ public class TitleDisplay /** * Builds the {@link Title} with the given parameters. + * * @return The built {@link Title}. */ public Title build() { return Title.title( - this.mainTitle, - this.subTitle, - Title.Times.times(this.fadeIn, this.displayDuration, this.fadeOut) + this.mainTitle, + this.subTitle, + Title.Times.times(this.fadeIn, this.displayDuration, this.fadeOut) ); } } diff --git a/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntity.java b/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntity.java index 59b11c2..f2b2c69 100644 --- a/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntity.java +++ b/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntity.java @@ -6,7 +6,8 @@ package me.totalfreedom.economy; public interface EconomicEntity { /** - * Gets the {@link EconomicEntityData} (which contains various common metadata about this {@link EconomicEntity}) associated with this class + * Gets the {@link EconomicEntityData} (which contains various common metadata about this {@link EconomicEntity}) + * associated with this class * * @return the {@link EconomicEntityData} */ diff --git a/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntityData.java b/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntityData.java index 7e1f5aa..ac3d372 100644 --- a/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntityData.java +++ b/Patchwork/src/main/java/me/totalfreedom/economy/EconomicEntityData.java @@ -15,6 +15,12 @@ public interface EconomicEntityData */ long getBalance(); + /** + * Sets the balance of the associated instance + * + * @param newBalance the new balance + */ + void setBalance(final long newBalance); /** * Adds the provided amount to the associated instance's balance @@ -31,11 +37,4 @@ public interface EconomicEntityData * @return the new balance */ long removeFromBalance(final long amount); - - /** - * Sets the balance of the associated instance - * - * @param newBalance the new balance - */ - 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 0deebc8..89a14a4 100644 --- a/Patchwork/src/main/java/me/totalfreedom/economy/MutableTransaction.java +++ b/Patchwork/src/main/java/me/totalfreedom/economy/MutableTransaction.java @@ -3,7 +3,8 @@ package me.totalfreedom.economy; /** * A transaction that can be changed. *

- * IMPORTANT NOTE: Please ensure that all modifications of {@link MutableTransaction} happen BEFORE it is passed to a {@link Transactor} implementation + * IMPORTANT NOTE: 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/logging/InteractionFormatter.java b/Patchwork/src/main/java/me/totalfreedom/logging/InteractionFormatter.java index c34bf1a..19a5f01 100644 --- a/Patchwork/src/main/java/me/totalfreedom/logging/InteractionFormatter.java +++ b/Patchwork/src/main/java/me/totalfreedom/logging/InteractionFormatter.java @@ -1,6 +1,5 @@ package me.totalfreedom.logging; -import me.totalfreedom.sql.SQL; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; @@ -120,8 +119,8 @@ public final class InteractionFormatter final int dotIndex = trimmed.indexOf('.'); return (dotIndex != -1) - ? trimmed.substring(0, dotIndex) - : trimmed; + ? trimmed.substring(0, dotIndex) + : trimmed; } // Format: , diff --git a/Patchwork/src/main/java/me/totalfreedom/particle/NoteColorUtil.java b/Patchwork/src/main/java/me/totalfreedom/particle/NoteColorUtil.java new file mode 100644 index 0000000..a415118 --- /dev/null +++ b/Patchwork/src/main/java/me/totalfreedom/particle/NoteColorUtil.java @@ -0,0 +1,50 @@ +package me.totalfreedom.particle; + +import org.bukkit.Particle; +import org.bukkit.World; + +/** + * A utility class for the 24 different note colors available in Minecraft. Each note is represented as a double value + * between 0 and 1. Furthermore, each note is a multiple of 1/24 within that range of 0 to 1. + *

+ * For example, the note G is represented as 1/24, or 0.042. The note C is represented as 6/24, or 0.25. + *

+ * When spawning particles, the count must be set to 0 and the extra value set between 0 and 1. The extra value is the + * size of the note particle. To add a color, use one of the provided methods in this class for the xOffset value in + * {@link World#spawnParticle(Particle, double, double, double, int, double, double, double, double)}. The xOffset value + * is the note color, with the yOffset and zOffset values set to 0. + */ +public final class NoteColorUtil +{ + public static final double CYAN_NOTE_F_SHARP_LOW = 0; + public static final double CYAN_NOTE_G = 0.042; + public static final double GRAY_NOTE_G_SHARP = 0.083; + public static final double GRAY_NOTE_A = 0.125; + public static final double GRAY_NOTE_A_SHARP = 0.167; + public static final double MAGENTA_NOTE_B = 0.208; + public static final double RED_NOTE_C = 0.25; + public static final double YELLOW_NOTE_C_SHARP = 0.292; + public static final double YELLOW_NOTE_D = 0.333; + public static final double YELLOW_NOTE_D_SHARP_LOW = 0.375; + public static final double GRAY_NOTE_E = 0.417; + public static final double GRAY_NOTE_F = 0.458; + public static final double GRAY_NOTE_F_SHARP = 0.5; + public static final double LIGHT_BLUE_NOTE_G = 0.542; + public static final double BLUE_NOTE_G_SHARP = 0.583; + public static final double PURPLE_NOTE_A = 0.625; + public static final double PURPLE_NOTE_A_SHARP = 0.667; + public static final double PURPLE_NOTE_B = 0.708; + public static final double GRAY_NOTE_C = 0.75; + public static final double GRAY_NOTE_C_SHARP = 0.792; + public static final double GRAY_NOTE_D = 0.833; + public static final double YELLOW_NOTE_D_SHARP_HIGH = 0.875; + public static final double YELLOW_NOTE_E = 0.917; + public static final double YELLOW_NOTE_F = 0.958; + public static final double CYAN_NOTE_F_SHARP_HIGH = 1; + public static final double BLACK_NOTE_NA = 32768; + + private NoteColorUtil() + { + throw new AssertionError(); + } +} diff --git a/Patchwork/src/main/java/me/totalfreedom/particle/NoteWrapper.java b/Patchwork/src/main/java/me/totalfreedom/particle/NoteWrapper.java deleted file mode 100644 index ef656ce..0000000 --- a/Patchwork/src/main/java/me/totalfreedom/particle/NoteWrapper.java +++ /dev/null @@ -1,157 +0,0 @@ -package me.totalfreedom.particle; - -import org.bukkit.Particle; -import org.bukkit.World; - -import java.math.RoundingMode; -import java.text.DecimalFormat; - -/** - * A utility class for the 24 different note colors available in Minecraft. Each note is represented as a double value - * between 0 and 1. Furthermore, each note is a multiple of 1/24 within that range of 0 to 1. - *

- * For example, the note G is represented as 1/24, or 0.042. The note C is represented as 6/24, or 0.25. - *

- * When spawning particles, the count must be set to 0 and the extra value set between 0 and 1. The extra value is the - * size of the note particle. To add a color, use one of the provided methods in this class for the xOffset value in - * {@link World#spawnParticle(Particle, double, double, double, int, double, double, double, double)}. The xOffset value - * is the note color, with the yOffset and zOffset values set to 0. - */ -public final class NoteWrapper -{ - public static final double CYAN_NOTE_F_SHARP_LOW = 0; - public static final double CYAN_NOTE_F_SHARP_HIGH = 1; - - private static final DecimalFormat FORMAT; - - static - { - FORMAT = new DecimalFormat("#.###"); - FORMAT.setRoundingMode(RoundingMode.HALF_UP); - } - - private NoteWrapper() - { - throw new AssertionError(); - } - - private static double round(final double value) - { - return Double.parseDouble(FORMAT.format(value)); - } - - public static double cyanNoteG() - { - return round(1 / 24D); - } - - public static double grayNoteGSharp() - { - return round(2 / 24D); - } - - public static double grayNoteA() - { - return round(3 / 24D); - } - - public static double grayNoteASharp() - { - return round(4 / 24D); - } - - public static double magentaNoteB() - { - return round(5 / 24D); - } - - public static double redNoteC() - { - return round(6 / 24D); - } - - public static double yellowNoteCSharp() - { - return round(7 / 24D); - } - - public static double yellowNoteD() - { - return round(8 / 24D); - } - - public static double yellowNoteDSharpLow() - { - return round(9 / 24D); - } - - public static double grayNoteE() - { - return round(10 / 24D); - } - - public static double grayNoteF() - { - return round(11 / 24D); - } - - public static double grayNoteFSharp() - { - return round(12 / 24D); - } - - public static double lightBlueNoteG() - { - return round(13 / 24D); - } - - public static double blueNoteGSharp() - { - return round(14 / 24D); - } - - public static double purpleNoteA() - { - return round(15 / 24D); - } - - public static double purpleNoteASharp() - { - return round(16 / 24D); - } - - public static double purpleNoteB() - { - return round(17 / 24D); - } - - public static double grayNoteC() - { - return round(18 / 24D); - } - - public static double grayNoteCSharp() - { - return round(19 / 24D); - } - - public static double grayNoteD() - { - return round(20 / 24D); - } - - public static double yellowNoteDSharpHigh() - { - return round(21 / 24D); - } - - public static double greenNoteE() - { - return round(22 / 24D); - } - - public static double lightBlueNoteF() - { - return round(23 / 24D); - } -} diff --git a/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java b/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java index dc3c517..b6ef17f 100644 --- a/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java +++ b/Patchwork/src/main/java/me/totalfreedom/particle/Trail.java @@ -17,9 +17,8 @@ import java.util.UUID; public interface Trail { /** - * Returns the UUID of the player associated with the trail. This is for usage with our persistant storage - * container so that we can safely send and retrieve the trails without having to directly reference a player - * object. + * Returns the UUID of the player associated with the trail. This is for usage with our persistant storage container + * so that we can safely send and retrieve the trails without having to directly reference a player object. *
* TL;DR Memory optimization! * @@ -30,9 +29,9 @@ public interface Trail /** * Returns the player associated with this trail. Trails are user specific, and should be persistent across all - * usages. This is also used when displaying the particles, as they will be relative to the player's back, which - * is an inverse offset of the player's eye location. We use OfflinePlayer as we can make a simple check and cast - * to determine if the player is online when spawning trails. + * usages. This is also used when displaying the particles, as they will be relative to the player's back, which is + * an inverse offset of the player's eye location. We use OfflinePlayer as we can make a simple check and cast to + * determine if the player is online when spawning trails. * * @return The player associated with this Trail. */ @@ -50,8 +49,8 @@ public interface Trail TrailType getTrailType(); /** - * This method is nullable because if the value of {@link #isGradient()} is true, then - * {@link #getColors()} should be used instead, as that will contain the color data for our trail. + * This method is nullable because if the value of {@link #isGradient()} is true, then {@link #getColors()} should + * be used instead, as that will contain the color data for our trail. *
* However, this method will also be null if the particle type is not colorable. * @@ -71,8 +70,8 @@ public interface Trail void setColor(@NotNull Color color); /** - * This method is nullable because if the value of {@link #isGradient()} is false, then - * {@link #getColor()} should be used instead, as our trail is a single static color. + * This method is nullable because if the value of {@link #isGradient()} is false, then {@link #getColor()} should + * be used instead, as our trail is a single static color. *
* However, this method will also be null if the particle type is not colorable. * diff --git a/Patchwork/src/main/java/me/totalfreedom/particle/TrailType.java b/Patchwork/src/main/java/me/totalfreedom/particle/TrailType.java index c0a5001..e7afbe2 100644 --- a/Patchwork/src/main/java/me/totalfreedom/particle/TrailType.java +++ b/Patchwork/src/main/java/me/totalfreedom/particle/TrailType.java @@ -1,6 +1,5 @@ package me.totalfreedom.particle; -import org.bukkit.Note; import org.bukkit.Particle; public enum TrailType diff --git a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java index aa61ac0..b878c85 100644 --- a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java +++ b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java @@ -18,16 +18,16 @@ public class ContextProvider public T fromString(final String string, final Class clazz) { return Stream.of(toBoolean(string), - toDouble(string), - toInt(string), - toLong(string), - toFloat(string), - toMaterial(string), - toPlayer(string), - toWorld(string), - toLocation(string), - toCommandSender(string), - toComponent(string)) + toDouble(string), + toInt(string), + toLong(string), + toFloat(string), + toMaterial(string), + toPlayer(string), + toWorld(string), + toLocation(string), + toCommandSender(string), + toComponent(string)) .filter(Objects::nonNull) .findFirst() .map(clazz::cast) @@ -36,14 +36,12 @@ public class ContextProvider private @Nullable Boolean toBoolean(final String string) { - try - { - return Boolean.parseBoolean(string); - } - catch (Exception ignored) - { - return null; - } + // Previoulsy we used Boolean#parseBoolean, but that will always return a value and does not throw + // an exception. This means that if the string is not "true" or "false", it will return false. + if (string.equalsIgnoreCase("true")) return true; + if (string.equalsIgnoreCase("false")) return false; + + return null; } private @Nullable Double toDouble(final String string) @@ -51,8 +49,7 @@ public class ContextProvider try { return Double.parseDouble(string); - } - catch (Exception ignored) + } catch (NumberFormatException ignored) { return null; } @@ -63,8 +60,7 @@ public class ContextProvider try { return Integer.parseInt(string); - } - catch (Exception ignored) + } catch (NumberFormatException ignored) { return null; } @@ -75,8 +71,7 @@ public class ContextProvider try { return Long.parseLong(string); - } - catch (Exception ignored) + } catch (NumberFormatException ignored) { return null; } @@ -87,8 +82,7 @@ public class ContextProvider try { return Float.parseFloat(string); - } - catch (Exception ignored) + } catch (NumberFormatException ignored) { return null; } diff --git a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java index 5724f09..f090314 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/FreedomExecutor.java @@ -119,8 +119,8 @@ public class FreedomExecutor } /** - * Gets the synchronous executor instance. This is a convenience for {@link CompletableFuture} invocations, - * when defining a custom executor for the {@link CompletableFuture}. + * Gets the synchronous executor instance. This is a convenience for {@link CompletableFuture} invocations, when + * defining a custom executor for the {@link CompletableFuture}. * * @return The synchronous executor instance. */ @@ -130,8 +130,8 @@ public class FreedomExecutor } /** - * Gets the asynchronous executor instance. This is a convenience for {@link CompletableFuture} invocations, - * when defining a custom executor for the {@link CompletableFuture}. + * Gets the asynchronous executor instance. This is a convenience for {@link CompletableFuture} invocations, when + * defining a custom executor for the {@link CompletableFuture}. * * @return The asynchronous executor instance. */ diff --git a/Patchwork/src/main/java/me/totalfreedom/service/Task.java b/Patchwork/src/main/java/me/totalfreedom/service/Task.java index cea71a6..3275705 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/Task.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/Task.java @@ -52,10 +52,10 @@ public abstract class Task extends BukkitRunnable } /** - * Creates a new task with the given name and delay. This will intialize a single execute task with an - * initial delay before execution. + * Creates a new task with the given name and delay. This will intialize a single execute task with an initial delay + * before execution. * - * @param name The name of the task. + * @param name The name of the task. * @param delay How long the task should wait before executing. */ protected Task(final String name, final long delay) @@ -64,44 +64,44 @@ public abstract class Task extends BukkitRunnable } /** - * Creates a new task with the given name and delay. - * This is the same as longs, except that here, we naturally support durations which are automatically converted to - * ticks for you. This means that using {@link Duration#ofSeconds(long)} will work as expected. + * Creates a new task with the given name and delay. This is the same as longs, except that here, we naturally + * support durations which are automatically converted to ticks for you. This means that using + * {@link Duration#ofSeconds(long)} will work as expected. * - * @param name The name of the task. + * @param name The name of the task. * @param delay How long the task should wait before executing. */ protected Task(final String name, final Duration delay) { - this(name, DurationTools.getTickedSeconds(delay), -1L); + this(name, DurationTools.getTicks(delay), -1L); } /** - * Creates a new task with the given name, delay, and interval. - * This is the same as longs, except that here, we naturally support durations which are automatically converted to - * ticks for you. This means that using {@link Duration#ofSeconds(long)} will work as expected. + * Creates a new task with the given name, delay, and interval. This is the same as longs, except that here, we + * naturally support durations which are automatically converted to ticks for you. This means that using + * {@link Duration#ofSeconds(long)} will work as expected. * - * @param name The name of the task. - * @param delay How long the task should wait before executing. + * @param name The name of the task. + * @param delay How long the task should wait before executing. * @param interval How long the task should wait between executions. */ protected Task(final String name, final Duration delay, final Duration interval) { - this(name, DurationTools.getTickedSeconds(delay), DurationTools.getTickedSeconds(interval)); + this(name, DurationTools.getTicks(delay), DurationTools.getTicks(interval)); } /** - * Creates a new task with the given name, delay, and interval. - * This method is a convenience method to use a {@link Duration} for the interval, while also being able to - * specify the delay as -1L so the task does not have an initial delay before execution. + * Creates a new task with the given name, delay, and interval. This method is a convenience method to use a + * {@link Duration} for the interval, while also being able to specify the delay as -1L so the task does not have an + * initial delay before execution. * - * @param name The name of the task. - * @param delay The delay of the task. + * @param name The name of the task. + * @param delay The delay of the task. * @param interval The interval of the task. */ protected Task(final String name, final long delay, final Duration interval) { - this(name, delay, DurationTools.getTickedSeconds(interval)); + this(name, delay, DurationTools.getTicks(interval)); } /** diff --git a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java index f7b7c0b..9e5c3e1 100644 --- a/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java +++ b/Patchwork/src/main/java/me/totalfreedom/service/TaskSubscription.java @@ -9,10 +9,10 @@ import org.bukkit.scheduler.BukkitTask; import java.util.concurrent.Executor; /** - * Represents a subscription to a task. Task subscriptions offer a nice wrapper for managing tasks, which are - * inevitably just bukkit runnables with a bit more lenience in terms of instantiation modification and execution. - * It also offers a more intuitive way to manage our tasks; rather than having to keep track of task ids for each - * {@link BukkitTask} object that gets returned by the {@link BukkitScheduler}. + * Represents a subscription to a task. Task subscriptions offer a nice wrapper for managing tasks, which are inevitably + * just bukkit runnables with a bit more lenience in terms of instantiation modification and execution. It also offers a + * more intuitive way to manage our tasks; rather than having to keep track of task ids for each {@link BukkitTask} + * object that gets returned by the {@link BukkitScheduler}. * * @param The type of task. */ diff --git a/Patchwork/src/main/java/me/totalfreedom/shop/ReactionTask.java b/Patchwork/src/main/java/me/totalfreedom/shop/ReactionTask.java index 4af9233..cceb27e 100644 --- a/Patchwork/src/main/java/me/totalfreedom/shop/ReactionTask.java +++ b/Patchwork/src/main/java/me/totalfreedom/shop/ReactionTask.java @@ -10,25 +10,29 @@ import net.kyori.adventure.bossbar.BossBar; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -public class ReactionTask extends Task implements Listener { +public class ReactionTask extends Task implements Listener +{ private final Reaction reaction; private final BossBarDisplay bossBarDisplay; - public ReactionTask(final String name, final Reaction reaction) { + public ReactionTask(final String name, final Reaction reaction) + { super(name, -1L, -1); this.reaction = reaction; final BossBar bossBar = BossBarDisplay.builder() - .setName(reaction.getReactionMessage()) - .setColor(BossBar.Color.GREEN) - .setProgress(0.0F) - .build(); + .setName(reaction.getReactionMessage()) + .setColor(BossBar.Color.GREEN) + .setProgress(0.0F) + .build(); this.bossBarDisplay = new BossBarDisplay(bossBar); } @Override - public void run() { - if (isCancelled()) { + public void run() + { + if (isCancelled()) + { } final BossBarTimer timer = new BossBarTimer(bossBarDisplay, reaction.getReactionDuration()); @@ -36,13 +40,15 @@ public class ReactionTask extends Task implements Listener { } @EventHandler - public void onPlayerChat(final AsyncChatEvent event) { + public void onPlayerChat(final AsyncChatEvent event) + { if (event.message() - .equals(reaction.getReactionMessage())) { + .equals(reaction.getReactionMessage())) + { final EconomicEntity entity = CommonsBase.getInstance() - .getRegistrations() - .getUserRegistry() - .getUser(event.getPlayer()); + .getRegistrations() + .getUserRegistry() + .getUser(event.getPlayer()); reaction.onReact(entity); } diff --git a/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java b/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java index 2127b1d..5a0566b 100644 --- a/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java +++ b/Patchwork/src/main/java/me/totalfreedom/sql/SQLProperties.java @@ -22,10 +22,10 @@ public interface SQLProperties default String toURLPlain() { return String.format("jdbc:%s://%s:%s/%s", - this.getDriver(), - this.getHost(), - this.getPort(), - this.getDatabase()); + this.getDriver(), + this.getHost(), + this.getPort(), + this.getDatabase()); } String getDriver(); @@ -39,12 +39,12 @@ public interface SQLProperties 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(); diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/DurationTools.java b/Patchwork/src/main/java/me/totalfreedom/utils/DurationTools.java index 1f833bc..b629f09 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/DurationTools.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/DurationTools.java @@ -16,7 +16,7 @@ public final class DurationTools throw new AssertionError(); } - public static final long getTickedSeconds(final Duration duration) + public static final long getTicks(final Duration duration) { return duration.toMillis() / 50L; } diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java b/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java index 2e282cb..7be41c0 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/InterpolationUtils.java @@ -34,7 +34,7 @@ public final class InterpolationUtils } private static Set hsvGradient(final int length, final Color from, final Color to, - final Interpolator interpolator) + final Interpolator interpolator) { // returns a float-array where hsv[0] = hue, hsv[1] = saturation, hsv[2] = value/brightness final float[] hsvFrom = java.awt.Color.RGBtoHSB(from.getRed(), from.getGreen(), from.getBlue(), null); @@ -69,18 +69,18 @@ public final class InterpolationUtils { final LinkedHashSet base = new LinkedHashSet<>(); final Set redToOrange = componentRGBGradient(length, NamedTextColor.RED, - NamedTextColor.GOLD, InterpolationUtils::linear); + NamedTextColor.GOLD, InterpolationUtils::linear); final Set orangeToYellow = componentRGBGradient(length, NamedTextColor.GOLD, - NamedTextColor.YELLOW, InterpolationUtils::linear); + NamedTextColor.YELLOW, InterpolationUtils::linear); final Set yellowToGreen = componentRGBGradient(length, NamedTextColor.YELLOW, - NamedTextColor.GREEN, InterpolationUtils::linear); + NamedTextColor.GREEN, InterpolationUtils::linear); final Set greenToBlue = componentRGBGradient(length, NamedTextColor.GREEN, - NamedTextColor.BLUE, InterpolationUtils::linear); + NamedTextColor.BLUE, InterpolationUtils::linear); final Set blueToPurple = componentRGBGradient(length, NamedTextColor.BLUE, - NamedTextColor.LIGHT_PURPLE, - InterpolationUtils::linear); + NamedTextColor.LIGHT_PURPLE, + InterpolationUtils::linear); final Set purpleToRed = componentRGBGradient(length, TextColor.color(75, 0, 130), - TextColor.color(255, 0, 0), InterpolationUtils::linear); + TextColor.color(255, 0, 0), InterpolationUtils::linear); base.addAll(redToOrange); base.addAll(orangeToYellow); base.addAll(yellowToGreen); @@ -91,7 +91,7 @@ public final class InterpolationUtils } private static Set componentRGBGradient(final int length, final TextColor from, final TextColor to, - final Interpolator interpolator) + final Interpolator interpolator) { final double[] r = interpolator.interpolate(from.red(), to.red(), length); final double[] g = interpolator.interpolate(from.green(), to.green(), length); @@ -113,7 +113,7 @@ public final class InterpolationUtils } private static Set rgbGradient(final int length, final Color from, final Color to, - final Interpolator interpolator) + final Interpolator interpolator) { final double[] r = interpolator.interpolate(from.getRed(), to.getRed(), length); final double[] g = interpolator.interpolate(from.getGreen(), to.getGreen(), length); diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/ShapeUtils.java b/Patchwork/src/main/java/me/totalfreedom/utils/ShapeUtils.java index 5a142a0..e4b533c 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/ShapeUtils.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/ShapeUtils.java @@ -21,7 +21,7 @@ public class ShapeUtils } public List generate(final int count, final DoubleUnaryOperator x, final DoubleUnaryOperator y, - final DoubleUnaryOperator z) + final DoubleUnaryOperator z) { final double step = (start - end) / (count - 1); final LinkedList lset = new LinkedList<>(); diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/container/Tuple.java b/Patchwork/src/main/java/me/totalfreedom/utils/container/Trio.java similarity index 81% rename from Patchwork/src/main/java/me/totalfreedom/utils/container/Tuple.java rename to Patchwork/src/main/java/me/totalfreedom/utils/container/Trio.java index 794637d..90bf673 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/container/Tuple.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/container/Trio.java @@ -1,12 +1,12 @@ package me.totalfreedom.utils.container; -public final class Tuple +public final class Trio { private final A a; private final B b; private final C c; - public Tuple(final A a, final B b, final C c) + public Trio(final A a, final B b, final C c) { this.a = a; this.b = b; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTuple.java b/Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTrio.java similarity index 81% rename from Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTuple.java rename to Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTrio.java index 85bdee3..cf2e27f 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTuple.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/container/UnaryTrio.java @@ -1,12 +1,12 @@ package me.totalfreedom.utils.container; -public class UnaryTuple +public class UnaryTrio { private final T primary; private final T secondary; private final T tertiary; - public UnaryTuple(final T primary, final T secondary, final T tertiary) + public UnaryTrio(final T primary, final T secondary, final T tertiary) { this.primary = primary; this.secondary = secondary; diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomAdventure.java b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomAdventure.java index f24cbc7..3dc548a 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomAdventure.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomAdventure.java @@ -12,7 +12,7 @@ import java.util.function.Supplier; public class FreedomAdventure { private static final PlainTextComponentSerializer PLAIN_TEXT_COMPONENT_SERIALIZER = - PlainTextComponentSerializer.plainText(); + PlainTextComponentSerializer.plainText(); private FreedomAdventure() { diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomMiniMessage.java b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomMiniMessage.java index e39552c..3db5cdc 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomMiniMessage.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/FreedomMiniMessage.java @@ -35,14 +35,14 @@ public class FreedomMiniMessage private static final MiniMessage unsafe = MiniMessage.miniMessage(); private static final MiniMessage safe = MiniMessage.builder() .tags(TagResolver.resolver( - StandardTags.color(), - StandardTags.rainbow(), - StandardTags.gradient(), - StandardTags.newline(), - StandardTags.decorations(TextDecoration.ITALIC), - StandardTags.decorations(TextDecoration.BOLD), - StandardTags.decorations(TextDecoration.STRIKETHROUGH), - StandardTags.decorations(TextDecoration.UNDERLINED) + StandardTags.color(), + StandardTags.rainbow(), + StandardTags.gradient(), + StandardTags.newline(), + StandardTags.decorations(TextDecoration.ITALIC), + StandardTags.decorations(TextDecoration.BOLD), + StandardTags.decorations(TextDecoration.STRIKETHROUGH), + StandardTags.decorations(TextDecoration.UNDERLINED) )) .build(); @@ -52,9 +52,8 @@ public class FreedomMiniMessage } /** - * Deserializes an input string using an instance of MiniMessage that is either safe (resolves only a specific - * set of tags) - * or unsafe (resolves all tags). + * Deserializes an input string using an instance of MiniMessage that is either safe (resolves only a specific set + * of tags) or unsafe (resolves all tags). * * @param safe Whether to use a safe instance of MiniMessage * @param input An input string formatted with MiniMessage's input diff --git a/Patchwork/src/main/java/me/totalfreedom/utils/kyori/KyoriConstants.java b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/KyoriConstants.java index 5ba62d5..0ffbe29 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/kyori/KyoriConstants.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/kyori/KyoriConstants.java @@ -9,12 +9,11 @@ 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 is now a requirement for all message requests to players due to the new chat signature system. + * 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 - * have made the appropriate API changes to accomodate chat signatures. + * Even though Scissors has this feature disabled, upstream (Paper) and Kyori Adventure have made the appropriate API + * changes to accomodate chat signatures. *
* As a result, we need to conform to those specifications even if we do not use this feature. */ @@ -34,8 +33,8 @@ public final class KyoriConstants /** * Represents a Chat Bound for a plugin. *
- * This is a convenience method so you are not required to dependency inject - * your plugin instance any time that you need a Bound. + * This is a convenience method so you are not required to dependency inject your plugin instance any time that you + * need a Bound. * * @param pluginClass The plugin class to get the plugin instance from. * @return A ChatType.Bound instance for the plugin. @@ -55,11 +54,10 @@ public final class KyoriConstants } /** - * Represents a Chat Bound for a player. - * Chat bounds are required for sending messages to players. + * Represents a Chat Bound for a player. Chat bounds are required for sending messages to players. *
- * 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. + * 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 player The player to get the bound for. * @return A ChatType.Bound instance for the player. @@ -72,8 +70,8 @@ public final class KyoriConstants /** * Represents a Chat Bound for the console. *
- * 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. + * 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/logging/FreedomLogger.java b/Patchwork/src/main/java/me/totalfreedom/utils/logging/FreedomLogger.java index 2a093c4..97cec23 100644 --- a/Patchwork/src/main/java/me/totalfreedom/utils/logging/FreedomLogger.java +++ b/Patchwork/src/main/java/me/totalfreedom/utils/logging/FreedomLogger.java @@ -33,8 +33,7 @@ public class FreedomLogger implements Audience } /** - * This method allows you to log a message to the console, - * while also returning a Component that could be used to + * This method allows you to log a message to the console, while also returning a Component that could be used to * message a player. * * @param message The message to send. @@ -47,8 +46,7 @@ public class FreedomLogger implements Audience } /** - * This method allows you to log a component to the console, - * while also returning a String representation of the + * This method allows you to log a component to the console, while also returning a String representation of the * component * * @param component The component to send. @@ -71,7 +69,9 @@ public class FreedomLogger implements Audience logger.info(plainText); return plainText; - } /** + } + + /** * This method allows you to log a message to the console. * * @param message The message to send. @@ -104,9 +104,8 @@ public class FreedomLogger implements Audience } /** - * This method logs an error message to the console. - * It is highly recommended to deconstruct the stack trace and pass it - * in a more readable format to this method. + * This method logs an error message to the console. It is highly recommended to deconstruct the stack trace and + * pass it in a more readable format to this method. * * @param message The message to send. */ @@ -126,11 +125,9 @@ public class FreedomLogger implements Audience } /** - * This method allows you to log an error message to the console, - * while also returning a Component that could be used to - * message a player. It is highly recommended that you deconstruct and limit - * the stack trace before passing it to this method, if you are intending to - * use it for player communication. + * This method allows you to log an error message to the console, while also returning a Component that could be + * used to message a player. It is highly recommended that you deconstruct and limit the stack trace before passing + * it to this method, if you are intending to use it for player communication. * * @param message The message to send. * @return A component representation of the message. @@ -142,9 +139,8 @@ public class FreedomLogger implements Audience } /** - * This method allows you to log an error component to the console, - * while also returning a String representation of the error - * component. + * This method allows you to log an error component to the console, while also returning a String representation of + * the error component. * * @param component The component to send. * @return A String representation of the component. @@ -169,10 +165,9 @@ public class FreedomLogger implements Audience } /** - * This method allows you to log a debug message to the console, - * while also returning a Component that could be used to - * message a player. This method will only log if debug mode is enabled. - * If debug mode is not enabled, this method will return an empty component. + * This method allows you to log a debug message to the console, while also returning a Component that could be used + * to message a player. This method will only log if debug mode is enabled. If debug mode is not enabled, this + * method will return an empty component. * * @param message The message to send. * @return A component representation of the message. @@ -188,8 +183,8 @@ public class FreedomLogger implements Audience } /** - * This method allows you to log a debug component to the console, - * while also returning a String representation of the debug component. + * This method allows you to log a debug component to the console, while also returning a String representation of + * the debug component. * * @param component The component to send. * @return A String representation of the message. @@ -204,8 +199,8 @@ public class FreedomLogger implements Audience } /** - * This method allows you to log a debug component to the console. - * This method will only log if debug mode is enabled. + * 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. */ @@ -219,8 +214,8 @@ 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 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. */ @@ -231,8 +226,6 @@ public class FreedomLogger implements Audience } - - @Override public void sendMessage(@NotNull final ComponentLike message) { @@ -269,7 +262,7 @@ public class FreedomLogger implements Audience 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, + 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/README.md b/README.md index 1007c96..2b2bbba 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Datura: - [ ] Permission Handling *(In Progress...)* - [ ] Permission Registration & Assignment *(In Progress...)* - [ ] SQL Data Handling *(In Progress...)* -- [ ] Configuration Implementations +- [ ] Configuration Implementations - [ ] User Data Implementations *(In Progress...)* - [x] Punishment Systems (e.x. Locker, Halter, Cager) @@ -101,7 +101,7 @@ Fossil: - [ ] Particle Implementation / Trails *(In Progress...)* - [ ] Command Implementations *(In Progress...)* - [ ] Implement a shop for the economy *(In Progress...)* -- [ ] Chat reaction / game system +- [ ] Chat reaction / game system - [ ] Jumppads Corvo: From de1da2bd6120c90a21bcaebc17ba11b164db97be Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Fri, 9 Jun 2023 21:17:42 -0500 Subject: [PATCH 13/14] Edited with Notepad++ --- .../src/main/java/me/totalfreedom/provider/ContextProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java index b878c85..1bb01f7 100644 --- a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java +++ b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java @@ -36,7 +36,7 @@ public class ContextProvider private @Nullable Boolean toBoolean(final String string) { - // Previoulsy we used Boolean#parseBoolean, but that will always return a value and does not throw + // Previously we used Boolean#parseBoolean, but that will always return a value and does not throwl // an exception. This means that if the string is not "true" or "false", it will return false. if (string.equalsIgnoreCase("true")) return true; if (string.equalsIgnoreCase("false")) return false; From a22f7fb215b8e19dc1d09f5c453dc8727940ea71 Mon Sep 17 00:00:00 2001 From: Paul Reilly Date: Fri, 9 Jun 2023 21:18:29 -0500 Subject: [PATCH 14/14] Super edited with Notepad++ --- .../src/main/java/me/totalfreedom/provider/ContextProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java index 1bb01f7..680219d 100644 --- a/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java +++ b/Patchwork/src/main/java/me/totalfreedom/provider/ContextProvider.java @@ -36,7 +36,7 @@ public class ContextProvider private @Nullable Boolean toBoolean(final String string) { - // Previously we used Boolean#parseBoolean, but that will always return a value and does not throwl + // Previously we used Boolean#parseBoolean, but that will always return a value and does not throw // an exception. This means that if the string is not "true" or "false", it will return false. if (string.equalsIgnoreCase("true")) return true; if (string.equalsIgnoreCase("false")) return false;