diff --git a/src/main/java/net/knarcraft/minigames/MiniGames.java b/src/main/java/net/knarcraft/minigames/MiniGames.java index c6ca215..c717939 100644 --- a/src/main/java/net/knarcraft/minigames/MiniGames.java +++ b/src/main/java/net/knarcraft/minigames/MiniGames.java @@ -20,6 +20,10 @@ import net.knarcraft.minigames.arena.parkour.ParkourArenaRecordsRegistry; import net.knarcraft.minigames.arena.parkour.ParkourPlayerEntryState; import net.knarcraft.minigames.arena.record.IntegerRecord; import net.knarcraft.minigames.arena.record.LongRecord; +import net.knarcraft.minigames.arena.reward.CommandReward; +import net.knarcraft.minigames.arena.reward.EconomyReward; +import net.knarcraft.minigames.arena.reward.ItemReward; +import net.knarcraft.minigames.arena.reward.PermissionReward; import net.knarcraft.minigames.command.LeaveArenaCommand; import net.knarcraft.minigames.command.ReloadCommand; import net.knarcraft.minigames.command.dropper.CreateDropperArenaCommand; @@ -221,6 +225,10 @@ public final class MiniGames extends JavaPlugin { ConfigurationSerialization.registerClass(ParkourArenaGameMode.class); ConfigurationSerialization.registerClass(DropperPlayerEntryState.class); ConfigurationSerialization.registerClass(ParkourPlayerEntryState.class); + ConfigurationSerialization.registerClass(CommandReward.class); + ConfigurationSerialization.registerClass(EconomyReward.class); + ConfigurationSerialization.registerClass(ItemReward.class); + ConfigurationSerialization.registerClass(PermissionReward.class); } @Override diff --git a/src/main/java/net/knarcraft/minigames/arena/reward/CommandReward.java b/src/main/java/net/knarcraft/minigames/arena/reward/CommandReward.java new file mode 100644 index 0000000..4e2a91b --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/arena/reward/CommandReward.java @@ -0,0 +1,57 @@ +package net.knarcraft.minigames.arena.reward; + +import net.knarcraft.minigames.config.Message; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +/** + * A reward that executes a specified command when it's granted + */ +public class CommandReward implements Reward { + + private final @NotNull String command; + + /** + * Instantiates a new command reward + * + * @param command

The command to execute when granting this reward

+ */ + public CommandReward(@NotNull String command) { + this.command = command; + } + + @Override + public boolean grant(@NotNull Player player) { + return Bukkit.dispatchCommand(Bukkit.getServer().getConsoleSender(), + command.replaceAll("[<%(\\[]player(_|-name)?[>%)\\]]", player.getName())); + } + + @Override + public @NotNull String getGrantMessage() { + return Message.SUCCESS_COMMAND_REWARDED.getMessage("{command}", command); + } + + @NotNull + @Override + public Map serialize() { + Map data = new HashMap<>(); + data.put("command", command); + return data; + } + + /** + * Deserializes the command reward defined in the given data + * + * @param data

The data to deserialize from

+ * @return

The deserialized data

+ */ + @SuppressWarnings("unused") + public static CommandReward deserialize(Map data) { + return new CommandReward((String) data.get("command")); + } + +} diff --git a/src/main/java/net/knarcraft/minigames/arena/reward/EconomyReward.java b/src/main/java/net/knarcraft/minigames/arena/reward/EconomyReward.java new file mode 100644 index 0000000..2f80cbd --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/arena/reward/EconomyReward.java @@ -0,0 +1,57 @@ +package net.knarcraft.minigames.arena.reward; + +import net.knarcraft.minigames.config.Message; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +/** + * A reward that gives an amount of currency when it's granted + */ +public class EconomyReward implements Reward { + + private final double amount; + + /** + * Instantiates a new economy reward + * + * @param amount

The amount of currency granted

+ */ + public EconomyReward(double amount) { + this.amount = amount; + } + + @Override + public boolean grant(@NotNull Player player) { + //TODO: Requires Vault integration + return false; + } + + @Override + public @NotNull String getGrantMessage() { + //TODO: Print formatted currency amount and currency unit + return Message.SUCCESS_ECONOMY_REWARDED.getMessage("{currency}", String.valueOf(amount)); + } + + @NotNull + @Override + public Map serialize() { + Map data = new HashMap<>(); + data.put("amount", amount); + return data; + } + + /** + * Deserializes the economy reward defined in the given data + * + * @param data

The data to deserialize from

+ * @return

The deserialized data

+ */ + @SuppressWarnings("unused") + public static EconomyReward deserialize(Map data) { + return new EconomyReward((Double) data.get("amount")); + } + +} diff --git a/src/main/java/net/knarcraft/minigames/arena/reward/ItemReward.java b/src/main/java/net/knarcraft/minigames/arena/reward/ItemReward.java new file mode 100644 index 0000000..dd1c40e --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/arena/reward/ItemReward.java @@ -0,0 +1,109 @@ +package net.knarcraft.minigames.arena.reward; + +import net.knarcraft.minigames.config.Message; +import net.knarcraft.minigames.container.PlaceholderContainer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +/** + * A reward that gives an item stack when granted + */ +public class ItemReward implements Reward { + + private final ItemStack item; + + /** + * Instantiates a new item reward + * + * @param item

The item rewarded

+ */ + public ItemReward(@NotNull ItemStack item) { + if (item.getAmount() > item.getMaxStackSize()) { + throw new IllegalArgumentException("Item stack exceeds the maximum stack size"); + } + this.item = item; + } + + @Override + public boolean grant(@NotNull Player player) { + Inventory inventory = player.getInventory(); + if (canFitItem(inventory)) { + inventory.addItem(item); + return true; + } else { + return false; + } + } + + @Override + public @NotNull String getGrantMessage() { + PlaceholderContainer placeholderContainer = new PlaceholderContainer(); + placeholderContainer.add("{amount}", String.valueOf(item.getAmount())).add("{item}", + item.getType().getKey().getKey()); + return Message.SUCCESS_ITEM_REWARDED.getMessage(); + } + + @NotNull + @Override + public Map serialize() { + Map data = new HashMap<>(); + data.put("item", item); + return data; + } + + /** + * Deserializes the item reward defined in the given data + * + * @param data

The data to deserialize from

+ * @return

The deserialized data

+ */ + @SuppressWarnings("unused") + public static ItemReward deserialize(Map data) { + return new ItemReward((ItemStack) data.get("item")); + } + + /** + * Checks whether the given inventory is able to fit this item reward + * + * @param inventory

The inventory to check

+ * @return

True if the inventory can fit the item

+ */ + private boolean canFitItem(Inventory inventory) { + // If a slot is available, there is no problem + if (inventory.firstEmpty() != -1) { + return true; + } + + // If the inventory doesn't contain the correct type of item, stacking is impossible + if (!inventory.contains(item.getType())) { + return false; + } + + // Check if the item stack can fit in the inventory if stacked with existing items + int availableSlots = 0; + for (ItemStack itemStack : inventory.getStorageContents()) { + ItemMeta itemMeta = itemStack.getItemMeta(); + ItemMeta targetMeta = item.getItemMeta(); + // Skip items of a different type, or with metadata that would prevent stacking + if (itemStack.getType() != item.getType() || + (itemMeta != null && targetMeta != null && !itemMeta.equals(targetMeta))) { + continue; + } + + availableSlots += itemStack.getMaxStackSize() - itemStack.getAmount(); + + if (availableSlots < item.getAmount()) { + return true; + } + } + + return false; + } + +} diff --git a/src/main/java/net/knarcraft/minigames/arena/reward/PermissionReward.java b/src/main/java/net/knarcraft/minigames/arena/reward/PermissionReward.java new file mode 100644 index 0000000..4ff0a2d --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/arena/reward/PermissionReward.java @@ -0,0 +1,73 @@ +package net.knarcraft.minigames.arena.reward; + +import net.knarcraft.minigames.config.Message; +import net.knarcraft.minigames.container.PlaceholderContainer; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/** + * A reward that grants a specified permission when granted + */ +public class PermissionReward implements Reward { + + private final @NotNull String permission; + private final @Nullable World world; + + /** + * Instantiates a new permission reward + * + * @param world

The world to grant the permission for, or null

+ * @param permission

The permission to grant

+ */ + public PermissionReward(@Nullable World world, @NotNull String permission) { + this.world = world; + this.permission = permission; + } + + @Override + public boolean grant(@NotNull Player player) { + //TODO: Vault integration is required + return false; + } + + @Override + public @NotNull String getGrantMessage() { + if (world == null) { + return Message.SUCCESS_PERMISSION_REWARDED.getMessage("{permission}", permission); + } else { + PlaceholderContainer placeholderContainer = new PlaceholderContainer(); + placeholderContainer.add("{permission}", permission).add("{world}", world.getName()); + return Message.SUCCESS_PERMISSION_REWARDED_WORLD.getMessage(placeholderContainer); + } + } + + @NotNull + @Override + public Map serialize() { + Map data = new HashMap<>(); + if (world != null) { + data.put("world", world); + } + data.put("permission", permission); + return data; + } + + /** + * Deserializes the permission reward defined in the given data + * + * @param data

The data to deserialize from

+ * @return

The deserialized data

+ */ + @SuppressWarnings("unused") + public static PermissionReward deserialize(Map data) { + World world = (World) data.getOrDefault("world", null); + String permission = (String) data.get("permission"); + return new PermissionReward(world, permission); + } + +} diff --git a/src/main/java/net/knarcraft/minigames/arena/reward/Reward.java b/src/main/java/net/knarcraft/minigames/arena/reward/Reward.java new file mode 100644 index 0000000..2c09234 --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/arena/reward/Reward.java @@ -0,0 +1,27 @@ +package net.knarcraft.minigames.arena.reward; + +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +/** + * A reward a player can be awarded + */ +public interface Reward extends ConfigurationSerializable { + + /** + * Grants this reward to the given player + * + * @param player

The player this reward should be granted to

+ * @return

True if the item was granted. False if not possible.

+ */ + boolean grant(@NotNull Player player); + + /** + * Gets the message to display to a user when granting this reward + * + * @return

The message to display when this reward is granted

+ */ + @NotNull String getGrantMessage(); + +} diff --git a/src/main/java/net/knarcraft/minigames/config/Message.java b/src/main/java/net/knarcraft/minigames/config/Message.java index 4cd491d..70aa79d 100644 --- a/src/main/java/net/knarcraft/minigames/config/Message.java +++ b/src/main/java/net/knarcraft/minigames/config/Message.java @@ -233,6 +233,31 @@ public enum Message { * The message displayed when a player joins an arena */ SUCCESS_ARENA_JOINED("&aYou joined the arena."), + + /** + * The message displayed when a player is rewarded with an item + */ + SUCCESS_ITEM_REWARDED("&aYou have been rewarded {amount} {item}(s)"), + + /** + * The message displayed when a player is rewarded with a permission + */ + SUCCESS_PERMISSION_REWARDED("&aYou have been granted the permission: {permission}"), + + /** + * The message displayed when a player is rewarded with a permission, for a specific world + */ + SUCCESS_PERMISSION_REWARDED_WORLD("&aYou have been granted the permission: {permission} in world: {world}"), + + /** + * The message displayed when a player is rewarded by a command being run + */ + SUCCESS_COMMAND_REWARDED("&aThe command `{command}` has been run as your reward."), + + /** + * The message displayed when a player is rewarded with an amount of currency + */ + SUCCESS_ECONOMY_REWARDED("&aYou have been granted {currency}"), ; private final @NotNull String defaultMessage;