Bump to 0.0.2, Added a dictionary so all front end text can be configured

This commit is contained in:
wolf
2025-08-01 15:39:41 -05:00
parent 402df54dcf
commit 231e7e4472
14 changed files with 236 additions and 105 deletions

View File

@@ -6,7 +6,7 @@ plugins {
} }
group = "me.trouper.dupealias" group = "me.trouper.dupealias"
version = "0.0.1" version = "0.0.2"
description = "A powerful dupe plugin with niche features for servers looking to stand out." description = "A powerful dupe plugin with niche features for servers looking to stand out."
java { java {

View File

@@ -4,6 +4,7 @@ import me.trouper.alias.AliasContext;
import me.trouper.alias.AliasContextProvider; import me.trouper.alias.AliasContextProvider;
import me.trouper.alias.data.Common; import me.trouper.alias.data.Common;
import me.trouper.dupealias.data.files.CommonConfig; import me.trouper.dupealias.data.files.CommonConfig;
import me.trouper.dupealias.data.files.Dictionary;
import me.trouper.dupealias.data.files.DupeConfig; import me.trouper.dupealias.data.files.DupeConfig;
import me.trouper.dupealias.server.DupeManager; import me.trouper.dupealias.server.DupeManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@@ -60,6 +61,10 @@ public final class DupeAlias extends JavaPlugin {
return alias.getDataManager().get(DupeConfig.class); return alias.getDataManager().get(DupeConfig.class);
} }
public Dictionary getDictionary() {
return alias.getDataManager().get(Dictionary.class);
}
public DupeManager getDupe() { public DupeManager getDupe() {
return dupe; return dupe;
} }

View File

@@ -3,6 +3,7 @@ package me.trouper.dupealias;
import me.trouper.alias.server.ContextAware; import me.trouper.alias.server.ContextAware;
import me.trouper.alias.server.events.listeners.GuiInputListener; import me.trouper.alias.server.events.listeners.GuiInputListener;
import me.trouper.dupealias.data.files.CommonConfig; import me.trouper.dupealias.data.files.CommonConfig;
import me.trouper.dupealias.data.files.Dictionary;
import me.trouper.dupealias.data.files.DupeConfig; import me.trouper.dupealias.data.files.DupeConfig;
import me.trouper.dupealias.server.DupeManager; import me.trouper.dupealias.server.DupeManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@@ -18,11 +19,15 @@ public interface DupeContext extends ContextAware {
} }
default CommonConfig getCommonConfig() { default CommonConfig getCommonConfig() {
return getDataManager().get(CommonConfig.class); return getInstance().getCommonConfig();
} }
default DupeConfig getConfig() { default DupeConfig getConfig() {
return getDataManager().get(DupeConfig.class); return getInstance().getDupeConfig();
}
default Dictionary dict() {
return getInstance().getDictionary();
} }
default GuiInputListener getGuiListener() { default GuiInputListener getGuiListener() {

View File

@@ -0,0 +1,97 @@
package me.trouper.dupealias.data.files;
import me.trouper.alias.data.JsonSerializable;
import me.trouper.dupealias.DupeContext;
import java.io.File;
import java.util.List;
public class Dictionary implements JsonSerializable<Dictionary>, DupeContext {
@Override
public File getFile() {
return new File(getInstance().getDataFolder(), "dictionary.json");
}
public DictGuiDupe guiDupe = new DictGuiDupe();
public DictItemModificationEvents itemModificationEvents = new DictItemModificationEvents();
public DictDupeCommand dupeCommand = new DictDupeCommand();
public class DictGuiDupe {
public String title = "<aqua><bold>Available GUIs";
public String noPermission = "You do not have permission to use the main dupe gui.";
public String noSpecificPermission = "You do not have permission to use that GUI.";
public String replicatorName = "<blue>Replicator GUI";
public String replicatorLore = "<gray>Open the single-item dupe GUI.";
public String inventoryName = "<yellow>Inventory GUI";
public String inventoryLore = "<gray>Open a mirror of your own inventory.";
public String chestName = "<green>Chest GUI";
public String chestLore = "<gray>Open the multi-item dupe GUI.";
public String noDupeGuiName = "<dark_red>Unavailable GUI";
public List<String> noDupeGuiLore = List.of(
"",
"<red>You lack the permission to",
"<red>use the <italic>{0}</italic> gui."
);
public String noDefaultGui = "There is currently no default Dupe GUI.";
public DictGuiReplicator guiReplicator = new DictGuiReplicator();
public DictGuiInventory guiInventory = new DictGuiInventory();
public DictGuiChest guiChest = new DictGuiChest();
public DictCommonItems commonItems = new DictCommonItems();
public class DictGuiReplicator {
public String title = "<gradient:#cc22ff:#cc99ff><bold>REPLICATOR</gradient>";
public String uniqueItemWarning = "Your {0} is or contains a unique item!";
public String inputItemDisplayName = "<gold>Replicator Input";
public List<String> inputItemLoreCooldown = List.of("Replicator input on cooldown.");
public List<String> inputItemLoreNoItemSelected = List.of("<gray>No item selected.", "<dark_red>Drag an item into this slot.");
public List<String> inputItemLoreItemSelected = List.of("<white>Set Item: {0}", "<dark_green>Replication Ready!");
}
public class DictGuiInventory {
public String title = "<gradient:#cc22ff:#cc99ff><bold>YOUR INVENTORY</gradient>";
}
public class DictGuiChest {
public String title = "<gradient:#cc22ff:#cc99ff><bold>DUPE CHEST</gradient>";
}
public class DictCommonItems {
public String refillName = "<yellow>Item Refilling...";
public String uniqueName = "<red>UNIQUE ITEM";
public String uniqueLore = "<gray>You are unable to dupe <white>{0}";
}
}
public class DictItemModificationEvents {
public String dropInfiniteItem = "You have dropped your infinite {0}!";
public String craftProtectedItem = "You cannot craft protected items!";
public String modifyFinalItem = "You cannot modify final items!";
public String useProtectedItem = "You cannot use protected items!";
public String placeProtectedItem = "You cannot place protected items!";
public String placeFinalBanner = "You cannot place final banners!";
public String fillFinalItem = "You cannot fill final items!";
public String drainFinalBucket = "You cannot drain final buckets!";
public String drainProtectedBucket = "You cannot drain protected buckets!";
public String fillFinalBucket = "You cannot fill final buckets!";
public String fillProtectedBucket = "You cannot fill protected buckets!";
public String fishFinalBucket = "You cannot fish with final buckets!";
public String fishProtectedBucket = "You cannot fish with protected buckets!";
public String consumeProtectedItem = "You cannot consume protected items!";
public String useFinalBow = "You cannot use final bows!";
public String shootProtectedItem = "You cannot shoot protected items!";
}
public class DictDupeCommand {
public String noPermission = "You are not allowed to dupe via commands.";
public String onCooldown = "You can command dupe again in {0}.";
public String dupeLimitExceeded = "Your maximum permitted dupe amplifier is {0}!";
public String noItemHeld = "You must hold an item to duplicate it with commands.";
public String uniqueItemWarning = "Your {0} is or contains a unique item that cannot be duped!";
public String inventoryFull = "Your inventory is now full.";
public String successMessage = "You have duplicated {0} items!";
public String invalidNumber = "{0} is not a valid number.";
}
}

View File

@@ -40,8 +40,6 @@ public class DupeConfig implements JsonSerializable<DupeConfig>, DupeContext {
ItemTag.INFINITE, "<dark_green><bold>|</bold><green> Finite" ItemTag.INFINITE, "<dark_green><bold>|</bold><green> Finite"
)); ));
public boolean blockDupePlus = false;
public List<GlobalRule> globalRules = new ArrayList<>(); public List<GlobalRule> globalRules = new ArrayList<>();
public Replicator replicator = new Replicator(); public Replicator replicator = new Replicator();

View File

@@ -20,21 +20,34 @@ import java.util.List;
public class DupeManager implements DupeContext { public class DupeManager implements DupeContext {
/**
* Runs a recursive check on the item to see if it is tagged as UNIQUE.
*/
public boolean isUnique(ItemStack item) { public boolean isUnique(ItemStack item) {
if (item == null || item.isEmpty()) return false; if (item == null || item.isEmpty()) return false;
return !new UniqueCheck().passes(item); return !new UniqueCheck().passes(item);
} }
/**
* Checks if the input item has the requested tag.
*/
public boolean hasIndividualTag(ItemStack input, ItemTag tag) { public boolean hasIndividualTag(ItemStack input, ItemTag tag) {
return input.hasItemMeta() && input.getPersistentDataContainer().has(tag.getKey()); return input.hasItemMeta() && input.getPersistentDataContainer().has(tag.getKey());
} }
/**
* Checks the value of the individual tag. Throws IllegalArgumentException if the item does not have the tag.
*/
public boolean checkIndividualTag(ItemStack input, ItemTag tag) { public boolean checkIndividualTag(ItemStack input, ItemTag tag) {
boolean set = hasIndividualTag(input,tag); boolean set = hasIndividualTag(input,tag);
if (!set) throw new IllegalArgumentException("Tried to check a tag which was not set, this may produce unexpected behavior!"); if (!set) throw new IllegalArgumentException("Tried to check a tag which was not set, this may produce unexpected behavior!");
return Boolean.TRUE.equals(input.getPersistentDataContainer().get(tag.getKey(), PersistentDataType.BOOLEAN)); return Boolean.TRUE.equals(input.getPersistentDataContainer().get(tag.getKey(), PersistentDataType.BOOLEAN));
} }
/**
* Compares individual and global rules to see if the selected tag is applicable for the item.
*/
public boolean checkEffectiveTag(ItemStack input, ItemTag tag) { public boolean checkEffectiveTag(ItemStack input, ItemTag tag) {
if (tag == null || input == null) return false; if (tag == null || input == null) return false;
if (input.isEmpty()) return false; if (input.isEmpty()) return false;
@@ -42,10 +55,8 @@ public class DupeManager implements DupeContext {
boolean set = hasIndividualTag(input,tag); boolean set = hasIndividualTag(input,tag);
boolean individual = set && Boolean.TRUE.equals(input.getPersistentDataContainer().get(tag.getKey(), PersistentDataType.BOOLEAN)); boolean individual = set && Boolean.TRUE.equals(input.getPersistentDataContainer().get(tag.getKey(), PersistentDataType.BOOLEAN));
// Check individual tag first
if (set) return individual; if (set) return individual;
// Check global rules
return checkGlobalRuleTag(input, tag); return checkGlobalRuleTag(input, tag);
} }
@@ -143,6 +154,9 @@ public class DupeManager implements DupeContext {
return true; return true;
} }
/**
* Adds the selected tag to the item, updating its lore too.
*/
public boolean addTag(ItemStack item, ItemTag tag) { public boolean addTag(ItemStack item, ItemTag tag) {
if (hasIndividualTag(item, tag) && getDupe().checkIndividualTag(item, tag)) return false; if (hasIndividualTag(item, tag) && getDupe().checkIndividualTag(item, tag)) return false;
@@ -158,6 +172,9 @@ public class DupeManager implements DupeContext {
return true; return true;
} }
/**
* Removes the selected tag from the item, updating its lore too.
*/
public boolean removeTag(ItemStack item, ItemTag tag) { public boolean removeTag(ItemStack item, ItemTag tag) {
ItemBuilder builder = ItemBuilder.of(item); ItemBuilder builder = ItemBuilder.of(item);
@@ -185,6 +202,10 @@ public class DupeManager implements DupeContext {
return true; return true;
} }
/**
* Sets the selected tag to the exact value, updating the lore too.
*/
public void setTag(ItemStack item, ItemTag tag, boolean value) { public void setTag(ItemStack item, ItemTag tag, boolean value) {
ItemBuilder builder = ItemBuilder.of(item); ItemBuilder builder = ItemBuilder.of(item);
@@ -210,6 +231,9 @@ public class DupeManager implements DupeContext {
item.setItemMeta(result.getItemMeta()); item.setItemMeta(result.getItemMeta());
} }
/**
* Removes the selected tag from the item meta and lore.
*/
public void removeTagLore(ItemMeta meta, ItemTag tag) { public void removeTagLore(ItemMeta meta, ItemTag tag) {
List<Component> lore = meta.lore(); List<Component> lore = meta.lore();
if (lore != null) { if (lore != null) {
@@ -232,13 +256,9 @@ public class DupeManager implements DupeContext {
} }
} }
public ItemTag getTag(NamespacedKey key) { /**
for (ItemTag value : ItemTag.values()) { * Checks the player's permission from the root node (ending in a dot), taking the highest or lowest value found.
if (value.getKey().equals(key)) return value; */
}
throw new IllegalArgumentException("Invalid NameSpacedKey '%s'".formatted(key.value()));
}
public int getPermissionValue(Player player, String rootPermission, int fallback, boolean takeHighest) { public int getPermissionValue(Player player, String rootPermission, int fallback, boolean takeHighest) {
int result = takeHighest ? Integer.MIN_VALUE : Integer.MAX_VALUE; int result = takeHighest ? Integer.MIN_VALUE : Integer.MAX_VALUE;

View File

@@ -62,7 +62,7 @@ public class DupeCommand implements QuickCommand, DupeContext {
dupeGui.openDefaultGui(player); dupeGui.openDefaultGui(player);
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
warningAny(player,"{0} is not a valid number.", args.get(0).toString()); warningAny(player, dict().dupeCommand.invalidNumber, args.get(0).toString());
} }
} }
@@ -75,17 +75,17 @@ public class DupeCommand implements QuickCommand, DupeContext {
private boolean verifyDupe(Player player, int amount) { private boolean verifyDupe(Player player, int amount) {
if (!player.hasPermission("dupealias.dupe")) { if (!player.hasPermission("dupealias.dupe")) {
warningAny(player,"You are not allowed to dupe via commands."); warningAny(player, dict().dupeCommand.noPermission);
return false; return false;
} }
if (dupeCooldown.isOnCooldown(player.getUniqueId())) { if (dupeCooldown.isOnCooldown(player.getUniqueId())) {
warningAny(player,"You can command dupe again in {0}.", dupeCooldown.formatLong(player.getUniqueId())); warningAny(player, dict().dupeCommand.onCooldown, dupeCooldown.formatLong(player.getUniqueId()));
return false; return false;
} }
int playerMax = getDupe().getPermissionValue(player,"dupealias.dupe.limit.",Integer.MAX_VALUE,true); int playerMax = getDupe().getPermissionValue(player,"dupealias.dupe.limit.",Integer.MAX_VALUE,true);
if (amount > playerMax) { if (amount > playerMax) {
warningAny(player,"Your maximum permitted dupe amplifier is {0}!", playerMax); warningAny(player, dict().dupeCommand.dupeLimitExceeded, playerMax);
return false; return false;
} }
@@ -93,13 +93,13 @@ public class DupeCommand implements QuickCommand, DupeContext {
ItemStack offHand = player.getInventory().getItemInOffHand(); ItemStack offHand = player.getInventory().getItemInOffHand();
if (toDupe.isEmpty() && offHand.isEmpty()) { if (toDupe.isEmpty() && offHand.isEmpty()) {
warningAny(player,"You must hold an item to duplicate it with commands."); warningAny(player, dict().dupeCommand.noItemHeld);
return false; return false;
} }
if (toDupe.isEmpty() || getDupe().isUnique(toDupe)) { if (toDupe.isEmpty() || getDupe().isUnique(toDupe)) {
if (getDupe().isUnique(offHand)) { if (getDupe().isUnique(offHand)) {
warningAny(player,"Your {0} is or contains a unique item that cannot be duped!", toDupe.getType()); warningAny(player, dict().dupeCommand.uniqueItemWarning, toDupe.getType());
return false; return false;
} else { } else {
toDupe = offHand; toDupe = offHand;
@@ -129,13 +129,13 @@ public class DupeCommand implements QuickCommand, DupeContext {
batch.setAmount(stackAmt); batch.setAmount(stackAmt);
if (!player.getInventory().addItem(batch).isEmpty()) { if (!player.getInventory().addItem(batch).isEmpty()) {
infoAny(player,"Your inventory is now full."); infoAny(player, dict().dupeCommand.inventoryFull);
return; return;
} }
} }
} }
int totalGiven = baseCount * ((1 << amount) - 1); int totalGiven = baseCount * ((1 << amount) - 1);
successAny(player,"You have duplicated {0} items!", totalGiven); successAny(player, dict().dupeCommand.successMessage, totalGiven);
} }
} }

View File

@@ -44,7 +44,7 @@ public class InfiniteItemEvents implements QuickListener, DupeContext {
stack.setItemMeta(stackMeta); stack.setItemMeta(stackMeta);
e.getItemDrop().setItemStack(stack); e.getItemDrop().setItemStack(stack);
} else { } else {
infoAny(player,"You have dropped your infinite {0}!", FormatUtils.formatEnum(stack.getType())); infoAny(player,dict().itemModificationEvents.dropInfiniteItem, FormatUtils.formatEnum(stack.getType()));
} }
} }

View File

@@ -42,7 +42,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(result, ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(result, ItemTag.PROTECTED)) {
event.getInventory().setResult(null); event.getInventory().setResult(null);
warningAny(Audience.audience(event.getViewers()), "You cannot craft protected items!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.craftProtectedItem);
return; return;
} }
@@ -51,13 +51,13 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(ingredient, ItemTag.FINAL)) { if (getDupe().checkEffectiveTag(ingredient, ItemTag.FINAL)) {
if (isModifyingCraft(ingredient, result)) { if (isModifyingCraft(ingredient, result)) {
event.getInventory().setResult(null); event.getInventory().setResult(null);
warningAny(Audience.audience(event.getViewers()), "You cannot modify final items!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.modifyFinalItem);
return; return;
} }
} }
if (getDupe().checkEffectiveTag(ingredient, ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(ingredient, ItemTag.PROTECTED)) {
event.getInventory().setResult(null); event.getInventory().setResult(null);
warningAny(Audience.audience(event.getViewers()), "You cannot use protected items!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.useProtectedItem);
return; return;
} }
} }
@@ -92,7 +92,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(item, ItemTag.FINAL)) { if (getDupe().checkEffectiveTag(item, ItemTag.FINAL)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(event.getEnchanter(), "You cannot modify final items!"); warningAny(event.getEnchanter(), dict().itemModificationEvents.modifyFinalItem);
} }
} }
@@ -249,41 +249,41 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
switch (inv) { switch (inv) {
case LoomInventory loom -> { case LoomInventory loom -> {
if (getDupe().checkEffectiveTag(loom.getItem(1), ItemTag.PROTECTED) || getDupe().checkEffectiveTag(loom.getItem(2), ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(loom.getItem(1), ItemTag.PROTECTED) || getDupe().checkEffectiveTag(loom.getItem(2), ItemTag.PROTECTED)) {
warningAny(Audience.audience(event.getViewers()), "You cannot use a protected item!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.useProtectedItem);
event.getInventory().close(); event.getInventory().close();
} }
if (getDupe().checkEffectiveTag(loom.getItem(0), ItemTag.FINAL)) { if (getDupe().checkEffectiveTag(loom.getItem(0), ItemTag.FINAL)) {
warningAny(Audience.audience(event.getViewers()), "You cannot modify a final item!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.modifyFinalItem);
event.getInventory().close(); event.getInventory().close();
} }
} }
case CartographyInventory carto -> { case CartographyInventory carto -> {
if (getDupe().checkEffectiveTag(carto.getResult(), ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(carto.getResult(), ItemTag.PROTECTED)) {
warningAny(Audience.audience(event.getViewers()), "You cannot use a protected item!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.useProtectedItem);
event.getInventory().close(); event.getInventory().close();
} }
if (getDupe().checkEffectiveTag(carto.getItem(0), ItemTag.FINAL) || getDupe().checkEffectiveTag(carto.getItem(1), ItemTag.FINAL)) { if (getDupe().checkEffectiveTag(carto.getItem(0), ItemTag.FINAL) || getDupe().checkEffectiveTag(carto.getItem(1), ItemTag.FINAL)) {
warningAny(Audience.audience(event.getViewers()), "You cannot modify a final item!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.modifyFinalItem);
event.getInventory().close(); event.getInventory().close();
} }
} }
case GrindstoneInventory grind -> { case GrindstoneInventory grind -> {
if (getDupe().checkEffectiveTag(grind.getResult(), ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(grind.getResult(), ItemTag.PROTECTED)) {
warningAny(Audience.audience(event.getViewers()), "You cannot use a protected item!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.useProtectedItem);
event.getInventory().close(); event.getInventory().close();
} }
if (getDupe().checkEffectiveTag(grind.getItem(0), ItemTag.FINAL) || getDupe().checkEffectiveTag(grind.getItem(1), ItemTag.FINAL)) { if (getDupe().checkEffectiveTag(grind.getItem(0), ItemTag.FINAL) || getDupe().checkEffectiveTag(grind.getItem(1), ItemTag.FINAL)) {
warningAny(Audience.audience(event.getViewers()), "You cannot modify a final item!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.modifyFinalItem);
event.getInventory().close(); event.getInventory().close();
} }
} }
case StonecutterInventory stone -> { case StonecutterInventory stone -> {
if (getDupe().checkEffectiveTag(stone.getResult(), ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(stone.getResult(), ItemTag.PROTECTED)) {
warningAny(Audience.audience(event.getViewers()), "You cannot use a protected item!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.useProtectedItem);
event.getInventory().close(); event.getInventory().close();
} }
if (getDupe().checkEffectiveTag(stone.getItem(0), ItemTag.FINAL)) { if (getDupe().checkEffectiveTag(stone.getItem(0), ItemTag.FINAL)) {
warningAny(Audience.audience(event.getViewers()), "You cannot modify a final item!"); warningAny(Audience.audience(event.getViewers()), dict().itemModificationEvents.modifyFinalItem);
event.getInventory().close(); event.getInventory().close();
} }
} }
@@ -314,12 +314,12 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (main.getType().equals(Material.BUCKET) || main.getType().equals(Material.GLASS_BOTTLE) || main.getType().name().contains("BANNER") || main.getType().name().contains("ARMOR")) { if (main.getType().equals(Material.BUCKET) || main.getType().equals(Material.GLASS_BOTTLE) || main.getType().name().contains("BANNER") || main.getType().name().contains("ARMOR")) {
if (getDupe().checkEffectiveTag(main, ItemTag.FINAL) || getDupe().checkEffectiveTag(main, ItemTag.FINAL)) { if (getDupe().checkEffectiveTag(main, ItemTag.FINAL) || getDupe().checkEffectiveTag(main, ItemTag.FINAL)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(player, "That item is final and cannot be modified!"); warningAny(player, dict().itemModificationEvents.modifyFinalItem);
} }
} else if (off.getType().equals(Material.BUCKET) || off.getType().equals(Material.GLASS_BOTTLE) || off.getType().name().contains("BANNER") || off.getType().name().contains("ARMOR")) { } else if (off.getType().equals(Material.BUCKET) || off.getType().equals(Material.GLASS_BOTTLE) || off.getType().name().contains("BANNER") || off.getType().name().contains("ARMOR")) {
if (getDupe().checkEffectiveTag(off, ItemTag.FINAL) || getDupe().checkEffectiveTag(off, ItemTag.FINAL)) { if (getDupe().checkEffectiveTag(off, ItemTag.FINAL) || getDupe().checkEffectiveTag(off, ItemTag.FINAL)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(player, "That item is final and cannot be modified!"); warningAny(player, dict().itemModificationEvents.modifyFinalItem);
} }
} }
@@ -338,7 +338,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
for (String finalCommandRegex : getConfig().finalCommandRegex) { for (String finalCommandRegex : getConfig().finalCommandRegex) {
if (command.matches(finalCommandRegex)) { if (command.matches(finalCommandRegex)) {
e.setCancelled(true); e.setCancelled(true);
warningAny(e.getPlayer(), "That item is final and cannot be modified!"); warningAny(e.getPlayer(), dict().itemModificationEvents.modifyFinalItem);
return; return;
} }
} }
@@ -363,11 +363,11 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(event.getPlayer(), "You cannot place protected items!"); warningAny(event.getPlayer(), dict().itemModificationEvents.placeProtectedItem);
} }
if (item.getItemMeta() instanceof BannerMeta && getDupe().checkEffectiveTag(item, ItemTag.FINAL)) { if (item.getItemMeta() instanceof BannerMeta && getDupe().checkEffectiveTag(item, ItemTag.FINAL)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(event.getPlayer(), "You cannot place final banners!"); warningAny(event.getPlayer(), dict().itemModificationEvents.placeFinalBanner);
} }
} }
@@ -378,14 +378,14 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(event.getPlayer(), "You cannot use protected items!"); warningAny(event.getPlayer(), dict().itemModificationEvents.useProtectedItem);
} }
Block targetBlock = event.getPlayer().getTargetBlockExact(4, FluidCollisionMode.ALWAYS); Block targetBlock = event.getPlayer().getTargetBlockExact(4, FluidCollisionMode.ALWAYS);
if (targetBlock != null && targetBlock.getType() == Material.WATER) { if (targetBlock != null && targetBlock.getType() == Material.WATER) {
if (getDupe().checkEffectiveTag(item, ItemTag.FINAL) && item != null && (item.getType().equals(Material.GLASS_BOTTLE) || item.getType().equals(Material.BUCKET))) { if (getDupe().checkEffectiveTag(item, ItemTag.FINAL) && item != null && (item.getType().equals(Material.GLASS_BOTTLE) || item.getType().equals(Material.BUCKET))) {
event.setCancelled(true); event.setCancelled(true);
warningAny(event.getPlayer(), "You cannot fill final items!"); warningAny(event.getPlayer(), dict().itemModificationEvents.fillFinalItem);
} }
} }
} }
@@ -397,7 +397,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
boolean isFinal = getDupe().checkEffectiveTag(item, ItemTag.FINAL); boolean isFinal = getDupe().checkEffectiveTag(item, ItemTag.FINAL);
boolean isProtected = getDupe().checkEffectiveTag(item, ItemTag.PROTECTED); boolean isProtected = getDupe().checkEffectiveTag(item, ItemTag.PROTECTED);
if (isProtected || isFinal) { if (isProtected || isFinal) {
String message = isFinal ? "You cannot drain final buckets!" : "You cannot drain protected buckets!"; String message = isFinal ? dict().itemModificationEvents.drainFinalBucket : dict().itemModificationEvents.drainProtectedBucket;
warningAny(event.getPlayer(), message); warningAny(event.getPlayer(), message);
event.setCancelled(true); event.setCancelled(true);
} }
@@ -410,7 +410,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
boolean isFinal = getDupe().checkEffectiveTag(item, ItemTag.FINAL); boolean isFinal = getDupe().checkEffectiveTag(item, ItemTag.FINAL);
boolean isProtected = getDupe().checkEffectiveTag(item, ItemTag.PROTECTED); boolean isProtected = getDupe().checkEffectiveTag(item, ItemTag.PROTECTED);
if (isProtected || isFinal) { if (isProtected || isFinal) {
String message = isFinal ? "You cannot fill final buckets!" : "You cannot fill protected buckets!"; String message = isFinal ? dict().itemModificationEvents.fillFinalBucket : dict().itemModificationEvents.fillProtectedBucket;
warningAny(event.getPlayer(), message); warningAny(event.getPlayer(), message);
event.setCancelled(true); event.setCancelled(true);
} }
@@ -423,7 +423,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
boolean isFinal = getDupe().checkEffectiveTag(item, ItemTag.FINAL); boolean isFinal = getDupe().checkEffectiveTag(item, ItemTag.FINAL);
boolean isProtected = getDupe().checkEffectiveTag(item, ItemTag.PROTECTED); boolean isProtected = getDupe().checkEffectiveTag(item, ItemTag.PROTECTED);
if (isProtected || isFinal) { if (isProtected || isFinal) {
String message = isFinal ? "You cannot fish with final buckets!" : "You cannot fish with protected buckets!"; String message = isFinal ? dict().itemModificationEvents.fishFinalBucket : dict().itemModificationEvents.fishProtectedBucket;
warningAny(event.getPlayer(), message); warningAny(event.getPlayer(), message);
event.setCancelled(true); event.setCancelled(true);
} }
@@ -445,7 +445,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(event.getPlayer(), "You cannot consume protected items!"); warningAny(event.getPlayer(), dict().itemModificationEvents.consumeProtectedItem);
} }
} }
@@ -462,7 +462,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
event.setCancelled(true); event.setCancelled(true);
if (event.getEntity() instanceof Player player) { if (event.getEntity() instanceof Player player) {
if (consumable != null) player.getInventory().addItem(consumable); if (consumable != null) player.getInventory().addItem(consumable);
String message = isFinal ? "You cannot use final bows!" : "You cannot shoot protected items!"; String message = isFinal ? dict().itemModificationEvents.useFinalBow : dict().itemModificationEvents.shootProtectedItem;
warningAny(player, message); warningAny(player, message);
} }
} }
@@ -480,7 +480,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(player, "You cannot use protected items!"); warningAny(player, dict().itemModificationEvents.useProtectedItem);
} }
} }
} }
@@ -493,7 +493,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(player, "You cannot use protected items!"); warningAny(player, dict().itemModificationEvents.useProtectedItem);
} }
} }
} }
@@ -506,7 +506,7 @@ public class ItemModificationEvents implements QuickListener, DupeContext {
if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) { if (getDupe().checkEffectiveTag(item, ItemTag.PROTECTED)) {
event.setCancelled(true); event.setCancelled(true);
warningAny(player, "You cannot use protected items!"); warningAny(player, dict().itemModificationEvents.useProtectedItem);
} }
} }

View File

@@ -50,15 +50,15 @@ public interface CommonItems extends DupeContext {
default ItemStack createPopulatedItem(ItemStack item, double progress) { default ItemStack createPopulatedItem(ItemStack item, double progress) {
if (progress < 1) { if (progress < 1) {
return ItemBuilder.of(EMPTY(Material.RED_STAINED_GLASS_PANE)) return ItemBuilder.of(EMPTY(Material.RED_STAINED_GLASS_PANE))
.displayName("<yellow>Item Refilling...") .displayName(dict().guiDupe.commonItems.refillName)
.loreComponent(getTextSystem().createProgressBar(progress,(char) '|',20, TextColor.color(0x5AFF89),TextColor.color(0x6F6F6F))) .loreComponent(getTextSystem().createProgressBar(progress,(char) '|',20, TextColor.color(0x5AFF89),TextColor.color(0x6F6F6F)))
.build(); .build();
} }
if (item == null || item.isEmpty()) return EMPTY(Material.GRAY_STAINED_GLASS_PANE); if (item == null || item.isEmpty()) return EMPTY(Material.GRAY_STAINED_GLASS_PANE);
ItemStack clone = item.clone(); ItemStack clone = item.clone();
if (getDupe().isUnique(clone)) return ItemBuilder.of(EMPTY(Material.BARRIER)) if (getDupe().isUnique(clone)) return ItemBuilder.of(EMPTY(Material.BARRIER))
.displayName("<red><bold>UNIQUE ITEM") .displayName(dict().guiDupe.commonItems.uniqueName)
.loreMiniMessage("<gray>You are unable to dupe <white>" + FormatUtils.formatEnum(clone.getType())) .loreMiniMessage(dict().guiDupe.commonItems.uniqueLore.replace("{0}",FormatUtils.formatEnum(clone.getType())))
.build(); .build();
return clone; return clone;
} }

View File

@@ -8,9 +8,6 @@ import me.trouper.dupealias.server.gui.dupe.sub.AbstractDupeGui;
import me.trouper.dupealias.server.gui.dupe.sub.DupeChestGui; import me.trouper.dupealias.server.gui.dupe.sub.DupeChestGui;
import me.trouper.dupealias.server.gui.dupe.sub.DupeInventoryGui; import me.trouper.dupealias.server.gui.dupe.sub.DupeInventoryGui;
import me.trouper.dupealias.server.gui.dupe.sub.DupeReplicatorGui; import me.trouper.dupealias.server.gui.dupe.sub.DupeReplicatorGui;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@@ -23,20 +20,20 @@ public class DupeGui implements DupeContext, CommonItems {
public void openMainGui(Player player) { public void openMainGui(Player player) {
if (!player.hasPermission("dupealias.gui")) { if (!player.hasPermission("dupealias.gui")) {
warningAny(player,"You do not have permission to use the main dupe gui."); warningAny(player,dict().guiDupe.noPermission);
return; return;
} }
QuickGui gui = QuickGui.create() QuickGui gui = QuickGui.create()
.rows(5) .rows(5)
.titleMini("<aqua><bold>Available GUIs") .titleMini(dict().guiDupe.title)
.item(20, .item(20,
permissionItem( permissionItem(
player, player,
"dupealias.gui.replicator", "dupealias.gui.replicator",
ItemBuilder.of(Material.DISPENSER) ItemBuilder.of(Material.DISPENSER)
.displayName("<blue>Replicator GUI") .displayName(dict().guiDupe.replicatorName)
.loreMiniMessage("<gray>Open the single-item dupe GUI.") .loreMiniMessage(dict().guiDupe.replicatorLore)
), ),
openSession(replicatorGui,"dupealias.gui.replicator")) openSession(replicatorGui,"dupealias.gui.replicator"))
@@ -44,8 +41,8 @@ public class DupeGui implements DupeContext, CommonItems {
player, player,
"dupealias.gui.inventory", "dupealias.gui.inventory",
ItemBuilder.of(Material.NETHERITE_CHESTPLATE) ItemBuilder.of(Material.NETHERITE_CHESTPLATE)
.displayName("<yellow>Inventory GUI") .displayName(dict().guiDupe.inventoryName)
.loreMiniMessage("<gray>Open a mirror of your own inventory.") .loreMiniMessage(dict().guiDupe.inventoryLore)
), ),
openSession(inventoryGui,"dupealias.gui.inventory")) openSession(inventoryGui,"dupealias.gui.inventory"))
@@ -53,8 +50,8 @@ public class DupeGui implements DupeContext, CommonItems {
player, player,
"dupealias.gui.chest", "dupealias.gui.chest",
ItemBuilder.of(Material.ENDER_CHEST) ItemBuilder.of(Material.ENDER_CHEST)
.displayName("<green>Chest GUI") .displayName(dict().guiDupe.chestName)
.loreMiniMessage("<gray>Open the multi-item dupe GUI.") .loreMiniMessage(dict().guiDupe.chestLore)
), ),
openSession(chestGui,"dupealias.gui.chest")) openSession(chestGui,"dupealias.gui.chest"))
@@ -69,11 +66,13 @@ public class DupeGui implements DupeContext, CommonItems {
if (player.hasPermission(permission)) { if (player.hasPermission(permission)) {
return builder.build(); return builder.build();
} else { } else {
Component name = builder.build().effectiveName(); return builder.displayName(dict().guiDupe.noDupeGuiName)
return builder.displayName("<dark_red>Unavailable GUI") .loreMiniMessage(
.loreMiniMessage() dict().guiDupe.noDupeGuiLore
.loreComponent(Component.text("You lack the permission to",NamedTextColor.RED),Component.text("use the ", NamedTextColor.RED).decoration(TextDecoration.ITALIC,false).append(name).append(Component.text("."))) .stream()
.build().withType(Material.BARRIER); .map(line->line.replace("{0}",permission.replace("dupealias.gui.","")))
.toList()
).build().withType(Material.BARRIER);
} }
} }
@@ -94,7 +93,7 @@ public class DupeGui implements DupeContext, CommonItems {
} }
} else { } else {
player.closeInventory(); player.closeInventory();
warningAny(player,"You do not have permission to use that GUI."); warningAny(player,dict().guiDupe.noSpecificPermission);
} }
} }
@@ -105,7 +104,7 @@ public class DupeGui implements DupeContext, CommonItems {
case "CHEST" -> openIfPermission(player,chestGui,"dupealias.gui.chest"); case "CHEST" -> openIfPermission(player,chestGui,"dupealias.gui.chest");
case "MENU" -> openMainGui(player); case "MENU" -> openMainGui(player);
default -> { default -> {
infoAny(player,"There is currently no default Dupe GUI."); infoAny(player,dict().guiDupe.noDefaultGui);
} }
} }
} }

View File

@@ -1,6 +1,7 @@
package me.trouper.dupealias.server.gui.dupe.sub; package me.trouper.dupealias.server.gui.dupe.sub;
import me.trouper.alias.server.systems.gui.QuickGui; import me.trouper.alias.server.systems.gui.QuickGui;
import me.trouper.dupealias.DupeAlias;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
@@ -31,7 +32,7 @@ public class DupeChestGui extends AbstractDupeGui<DupeChestGui.ChestSession> {
private int delayTicks; private int delayTicks;
public ChestSession(Player owner) { public ChestSession(Player owner) {
super(owner, "<gradient:#cc22ff:#cc99ff><bold>DUPE CHEST</gradient>", 6); super(owner, DupeAlias.getDupeAlias().getDictionary().guiDupe.guiChest.title, 6);
this.delayTicks = getDupe().getPermissionValue(owner, "dupealias.gui.chest.refresh.", getConfig().chest.baseRefreshDelayTicks,false); this.delayTicks = getDupe().getPermissionValue(owner, "dupealias.gui.chest.refresh.", getConfig().chest.baseRefreshDelayTicks,false);
} }

View File

@@ -1,6 +1,7 @@
package me.trouper.dupealias.server.gui.dupe.sub; package me.trouper.dupealias.server.gui.dupe.sub;
import me.trouper.alias.server.systems.gui.QuickGui; import me.trouper.alias.server.systems.gui.QuickGui;
import me.trouper.dupealias.DupeAlias;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@@ -28,7 +29,7 @@ public class DupeInventoryGui extends AbstractDupeGui<DupeInventoryGui.Inventory
private int delayTicks; private int delayTicks;
public InventorySession(Player owner) { public InventorySession(Player owner) {
super(owner, "<gradient:#cc22ff:#cc99ff><bold>YOUR INVENTORY</gradient>", 6); super(owner, DupeAlias.getDupeAlias().getDictionary().guiDupe.guiInventory.title, 6);
this.delayTicks = getDupe().getPermissionValue(owner, "dupealias.gui.inventory.refresh.", getConfig().inventory.baseRefreshDelayTicks,false); this.delayTicks = getDupe().getPermissionValue(owner, "dupealias.gui.inventory.refresh.", getConfig().inventory.baseRefreshDelayTicks,false);
} }

View File

@@ -4,6 +4,8 @@ import me.trouper.alias.server.systems.gui.QuickGui;
import me.trouper.alias.utils.FormatUtils; import me.trouper.alias.utils.FormatUtils;
import me.trouper.alias.utils.ItemBuilder; import me.trouper.alias.utils.ItemBuilder;
import me.trouper.alias.utils.SoundPlayer; import me.trouper.alias.utils.SoundPlayer;
import me.trouper.dupealias.DupeAlias;
import me.trouper.dupealias.DupeContext;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
@@ -13,7 +15,10 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
public class DupeReplicatorGui extends AbstractDupeGui<DupeReplicatorGui.ReplicatorSession> { import java.util.List;
import java.util.stream.Collectors;
public class DupeReplicatorGui extends AbstractDupeGui<DupeReplicatorGui.ReplicatorSession> implements DupeContext {
private final int[] inputRing = {1, 2, 3, 12, 21, 20, 19, 10}; private final int[] inputRing = {1, 2, 3, 12, 21, 20, 19, 10};
private final int[] outputRing = {5, 6, 7, 16, 25, 24, 23, 14}; private final int[] outputRing = {5, 6, 7, 16, 25, 24, 23, 14};
@@ -46,7 +51,7 @@ public class DupeReplicatorGui extends AbstractDupeGui<DupeReplicatorGui.Replica
private boolean ready = false; private boolean ready = false;
public ReplicatorSession(Player owner, ItemStack input) { public ReplicatorSession(Player owner, ItemStack input) {
super(owner, "<gradient:#cc22ff:#cc99ff><bold>REPLICATOR</gradient>", 3); super(owner, DupeAlias.getDupeAlias().getDictionary().guiDupe.guiReplicator.title, 3);
getVerbose().send("Creating a new replicator with input of {0}", input.getType().name()); getVerbose().send("Creating a new replicator with input of {0}", input.getType().name());
setInput(input); setInput(input);
this.delayTicks = getDupe().getPermissionValue(owner, "dupealias.gui.replicator.refresh.", getConfig().replicator.baseRefreshDelayTicks,false); this.delayTicks = getDupe().getPermissionValue(owner, "dupealias.gui.replicator.refresh.", getConfig().replicator.baseRefreshDelayTicks,false);
@@ -165,7 +170,7 @@ public class DupeReplicatorGui extends AbstractDupeGui<DupeReplicatorGui.Replica
public boolean setInput(ItemStack newInput) { public boolean setInput(ItemStack newInput) {
if (getDupe().isUnique(newInput)) { if (getDupe().isUnique(newInput)) {
SoundPlayer.play(getOwner(), Sound.ENTITY_VILLAGER_NO, 1, 0.8F); SoundPlayer.play(getOwner(), Sound.ENTITY_VILLAGER_NO, 1, 0.8F);
warningAny(getOwner(), "Your {0} is or contains a unique item!", FormatUtils.formatEnum(newInput.getType())); warningAny(getOwner(), dict().guiDupe.guiReplicator.uniqueItemWarning, FormatUtils.formatEnum(newInput.getType()));
getGui().getInventory().setItem(11, createInputItem(this.input, 1)); getGui().getInventory().setItem(11, createInputItem(this.input, 1));
return false; return false;
} }
@@ -205,22 +210,22 @@ public class DupeReplicatorGui extends AbstractDupeGui<DupeReplicatorGui.Replica
private ItemStack createInputItem(ItemStack input, double cooldownProgress) { private ItemStack createInputItem(ItemStack input, double cooldownProgress) {
if (cooldownProgress < 1) { if (cooldownProgress < 1) {
return ItemBuilder.of(EMPTY(Material.BARRIER)) return ItemBuilder.of(EMPTY(Material.BARRIER))
.displayName("<gold>Replicator Input") .displayName(dict().guiDupe.guiReplicator.inputItemDisplayName)
.loreComponent(getTextSystem().createProgressBar(cooldownProgress, '|',30, TextColor.color(0xFF895A),TextColor.color(0x6F6F6F))) .loreComponent(getTextSystem().createProgressBar(cooldownProgress, '|',30, TextColor.color(0xFF895A),TextColor.color(0x6F6F6F)))
.loreComponent(Component.text("Replicator input on cooldown.", NamedTextColor.DARK_RED)) .loreMiniMessage(dict().guiDupe.guiReplicator.inputItemLoreCooldown)
.build(); .build();
} }
if (input == null || input.getType() == Material.AIR) { if (input == null || input.getType() == Material.AIR) {
return ItemBuilder.headOfTexture("http://textures.minecraft.net/texture/86bd920b402815ad89018df82977be9f7ea19e799ecf016f7f0da4ab47ca23c5") return ItemBuilder.headOfTexture("http://textures.minecraft.net/texture/86bd920b402815ad89018df82977be9f7ea19e799ecf016f7f0da4ab47ca23c5")
.displayName("<gold>Replicator Input") .displayName(dict().guiDupe.guiReplicator.inputItemDisplayName)
.loreMiniMessage("<gray>No item selected.") .loreMiniMessage(dict().guiDupe.guiReplicator.inputItemLoreNoItemSelected)
.loreMiniMessage("<dark_red>Drag an item into this slot.")
.build(); .build();
} else { } else {
return ItemBuilder.headOfTexture("http://textures.minecraft.net/texture/32d250f5336449b32bfe990bdfd307a1b39ae5ca07e9a1593b1bb6ed33ec14ba") return ItemBuilder.headOfTexture("http://textures.minecraft.net/texture/32d250f5336449b32bfe990bdfd307a1b39ae5ca07e9a1593b1bb6ed33ec14ba")
.displayName("<gold>Replicator Input") .displayName(dict().guiDupe.guiReplicator.inputItemDisplayName)
.loreMiniMessage("<white>Set Item: " + FormatUtils.formatEnum(input.getType())) .loreMiniMessage(dict().guiDupe.guiReplicator.inputItemLoreItemSelected.stream()
.loreMiniMessage("<dark_green>Replication Ready!") .map(line->line.replace("{0}", FormatUtils.formatEnum(input.getType())))
.toList())
.build(); .build();
} }
} }