├── src └── main │ ├── resources │ ├── config.yml │ ├── plugin.yml │ └── messages.yml │ └── java │ └── goldenshadow │ └── displayentityeditor │ ├── enums │ ├── InputType.java │ └── LockSearchMode.java │ ├── events │ ├── PlayerLeave.java │ ├── InventoryClose.java │ ├── PlayerJoin.java │ ├── OffhandSwap.java │ └── InventoryClick.java │ ├── conversation │ ├── InputData.java │ ├── TextPrompt.java │ ├── IntegerPrompt.java │ ├── BytePrompt.java │ ├── FloatPrompt.java │ └── InputManager.java │ ├── commands │ ├── TabComplete.java │ └── Command.java │ ├── EditingHandler.java │ ├── MessageManager.java │ ├── SelectionMode.java │ ├── DisplayEntityEditor.java │ ├── inventories │ └── InventoryFactory.java │ ├── Utilities.java │ └── items │ ├── GUIItems.java │ └── InventoryItems.java ├── README.md ├── .gitignore └── pom.xml /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | send-update-message-on-join: true 2 | alternate-text-input: false 3 | use-minimessage-format: false 4 | use-messages-file: false -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DisplayEntityEditor 2 | 3 | DisplayEntityEditor is a minecraft plugin that gives you access to a full suite of tools to edit display entities. 4 | It is designed to be feel similar to ArmorStandTools and provides similar tools and gui options! 5 | 6 | You can download the plugin here: https://www.spigotmc.org/resources/display-entity-editor.110267/ 7 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/enums/InputType.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.enums; 2 | 3 | /** 4 | * An enum used to define what kind of text input is being expected 5 | */ 6 | public enum InputType { 7 | NAME, 8 | VIEW_RANGE, 9 | DISPLAY_HEIGHT, 10 | DISPLAY_WIDTH, 11 | SHADOW_RADIUS, 12 | SHADOW_STRENGTH, 13 | TEXT_OPACITY, 14 | LINE_WIDTH, 15 | BACKGROUND_OPACITY, 16 | BACKGROUND_COLOR, 17 | TEXT, 18 | TEXT_APPEND, 19 | GLOW_COLOR, 20 | BLOCK_STATE 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: DisplayEntityEditor 2 | version: '${project.version}' 3 | main: goldenshadow.displayentityeditor.DisplayEntityEditor 4 | api-version: 1.19 5 | authors: [_GoldenShadow] 6 | description: A full suite of tools to edit text, item and block display entities 7 | commands: 8 | displayentityeditor: 9 | aliases: 10 | - dee 11 | - deeditor 12 | - detools 13 | - det 14 | permission: DisplayEntityEditor.admin 15 | description: This command gives you all the tools needed to edit display entities 16 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/events/PlayerLeave.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.events; 2 | 3 | import goldenshadow.displayentityeditor.commands.Command; 4 | import org.bukkit.event.EventHandler; 5 | import org.bukkit.event.Listener; 6 | import org.bukkit.event.player.PlayerQuitEvent; 7 | 8 | public class PlayerLeave implements Listener { 9 | 10 | /** 11 | * Used to listen for when a player leaves 12 | * @param event The event 13 | */ 14 | @EventHandler 15 | public void onLeave(PlayerQuitEvent event) { 16 | Command.returnInventory(event.getPlayer()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/conversation/InputData.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.conversation; 2 | 3 | import goldenshadow.displayentityeditor.enums.InputType; 4 | import org.bukkit.Material; 5 | import org.bukkit.entity.Display; 6 | 7 | import javax.annotation.Nullable; 8 | 9 | /** 10 | * A record class used to store data about an awaited text input 11 | * @param entity The entity being edited 12 | * @param inputType What is being edited 13 | * @param blockMaterial The block material if the block state is being edited, otherwise null 14 | */ 15 | public record InputData(Display entity, InputType inputType, @Nullable Material blockMaterial) {} 16 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/events/InventoryClose.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.events; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import org.bukkit.event.EventHandler; 5 | import org.bukkit.event.Listener; 6 | import org.bukkit.event.inventory.InventoryCloseEvent; 7 | 8 | public class InventoryClose implements Listener { 9 | 10 | /** 11 | * Used to listen to when a player closes an inventory 12 | * @param event The event 13 | */ 14 | @EventHandler 15 | public void close(InventoryCloseEvent event) { 16 | DisplayEntityEditor.currentEditMap.remove(event.getPlayer().getUniqueId()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/enums/LockSearchMode.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.enums; 2 | 3 | import java.util.function.Predicate; 4 | 5 | import org.bukkit.entity.Display; 6 | 7 | public enum LockSearchMode { 8 | 9 | ALL(display -> true), 10 | LOCKED(display -> display.getScoreboardTags().contains("dee:locked")), 11 | UNLOCKED(display -> !display.getScoreboardTags().contains("dee:locked")); 12 | 13 | private static final LockSearchMode[] MODES = LockSearchMode.values(); 14 | 15 | private final Predicate predicate; 16 | 17 | private LockSearchMode(final Predicate predicate) { 18 | this.predicate = predicate; 19 | } 20 | 21 | public Predicate getPredicate() { 22 | return predicate; 23 | } 24 | 25 | public LockSearchMode previousMode() { 26 | int i = ordinal(); 27 | return i == 0 ? MODES[MODES.length - 1] : MODES[i - 1]; 28 | } 29 | 30 | public LockSearchMode nextMode() { 31 | int i = ordinal(); 32 | return i + 1 == MODES.length ? MODES[0] : MODES[i + 1]; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/conversation/TextPrompt.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.conversation; 2 | 3 | import org.bukkit.conversations.ConversationContext; 4 | import org.bukkit.conversations.Prompt; 5 | import org.bukkit.conversations.StringPrompt; 6 | import org.bukkit.entity.Player; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | 11 | public class TextPrompt extends StringPrompt { 12 | 13 | private final String message; 14 | 15 | /** 16 | * Used to create a new string prompt 17 | * @param message The message that should be displayed 18 | */ 19 | public TextPrompt(String message) { 20 | this.message = message; 21 | } 22 | 23 | /** 24 | * Used to get the prompt text 25 | * @param conversationContext The conversation context 26 | * @return The message specified when this object was created 27 | */ 28 | @NotNull 29 | @Override 30 | public String getPromptText(@NotNull ConversationContext conversationContext) { 31 | return message; 32 | } 33 | 34 | /** 35 | * Used for when a valid input was given 36 | * @param conversationContext The conversation context 37 | * @param s The value that was given 38 | * @return End of the conversation 39 | */ 40 | @Nullable 41 | @Override 42 | public Prompt acceptInput(@NotNull ConversationContext conversationContext, @Nullable String s) { 43 | InputData inputData = (InputData) conversationContext.getSessionData("data"); 44 | assert inputData != null; 45 | if (s != null) { 46 | Player player = (Player) conversationContext.getForWhom(); 47 | InputManager.successfulTextInput(inputData, s, player); 48 | } 49 | return END_OF_CONVERSATION; 50 | } 51 | 52 | 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/commands/TabComplete.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.commands; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import org.bukkit.command.Command; 5 | import org.bukkit.command.CommandSender; 6 | import org.bukkit.command.TabCompleter; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | public class TabComplete implements TabCompleter { 14 | 15 | 16 | 17 | List arguments = new ArrayList<>(); 18 | 19 | @Override 20 | public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { 21 | 22 | List result = new ArrayList<>(); 23 | if (args.length == 1) { 24 | if (DisplayEntityEditor.alternateTextInput) { 25 | arguments = new ArrayList<>(List.of("reload", "edit")); 26 | } else { 27 | arguments = new ArrayList<>(List.of("reload")); 28 | } 29 | 30 | for (String a : arguments) { 31 | if (a.toLowerCase().startsWith(args[0].toLowerCase())) 32 | result.add(a); 33 | } 34 | return result; 35 | } 36 | if (args.length == 2) { 37 | if (DisplayEntityEditor.alternateTextInput) { 38 | if (args[0].equalsIgnoreCase("edit")) { 39 | arguments = new ArrayList<>(Arrays.asList("name", "view_range", "display_height", "display_width", "shadow_radius", "shadow_strength", "text_opacity", "line_width", "background_opacity", "background_color", "text", "text_append", "glow_color", "block_state")); 40 | } 41 | } 42 | else arguments.clear(); 43 | for (String a : arguments) { 44 | if (a.toLowerCase().startsWith(args[1].toLowerCase())) 45 | result.add(a); 46 | } 47 | return result; 48 | } 49 | 50 | 51 | if (args.length > 2) { 52 | arguments.clear(); 53 | return arguments; 54 | } 55 | 56 | 57 | return null; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # Eclipse 9 | .settings/ 10 | .classpath 11 | .project 12 | 13 | # IntelliJ 14 | out/ 15 | 16 | # Compiled class file 17 | *.class 18 | 19 | # Log file 20 | *.log 21 | 22 | # BlueJ files 23 | *.ctxt 24 | 25 | # Package Files # 26 | *.jar 27 | *.war 28 | *.nar 29 | *.ear 30 | *.zip 31 | *.tar.gz 32 | *.rar 33 | 34 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 35 | hs_err_pid* 36 | 37 | *~ 38 | 39 | # temporary files which can be created if a process still has a handle open of a deleted file 40 | .fuse_hidden* 41 | 42 | # KDE directory preferences 43 | .directory 44 | 45 | # Linux trash folder which might appear on any partition or disk 46 | .Trash-* 47 | 48 | # .nfs files are created when an open file is removed but is still being accessed 49 | .nfs* 50 | 51 | # General 52 | .DS_Store 53 | .AppleDouble 54 | .LSOverride 55 | 56 | # Icon must end with two \r 57 | Icon 58 | 59 | # Thumbnails 60 | ._* 61 | 62 | # Files that might appear in the root of a volume 63 | .DocumentRevisions-V100 64 | .fseventsd 65 | .Spotlight-V100 66 | .TemporaryItems 67 | .Trashes 68 | .VolumeIcon.icns 69 | .com.apple.timemachine.donotpresent 70 | 71 | # Directories potentially created on remote AFP share 72 | .AppleDB 73 | .AppleDesktop 74 | Network Trash Folder 75 | Temporary Items 76 | .apdisk 77 | 78 | # Windows thumbnail cache files 79 | Thumbs.db 80 | Thumbs.db:encryptable 81 | ehthumbs.db 82 | ehthumbs_vista.db 83 | 84 | # Dump file 85 | *.stackdump 86 | 87 | # Folder config file 88 | [Dd]esktop.ini 89 | 90 | # Recycle Bin used on file shares 91 | $RECYCLE.BIN/ 92 | 93 | # Windows Installer files 94 | *.cab 95 | *.msi 96 | *.msix 97 | *.msm 98 | *.msp 99 | 100 | # Windows shortcuts 101 | *.lnk 102 | 103 | target/ 104 | 105 | pom.xml.tag 106 | pom.xml.releaseBackup 107 | pom.xml.versionsBackup 108 | pom.xml.next 109 | 110 | release.properties 111 | dependency-reduced-pom.xml 112 | buildNumber.properties 113 | .mvn/timing.properties 114 | .mvn/wrapper/maven-wrapper.jar 115 | .flattened-pom.xml 116 | 117 | # Common working directory 118 | run/ 119 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/events/PlayerJoin.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.events; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerLoginEvent; 10 | 11 | public class PlayerJoin implements Listener { 12 | 13 | /** 14 | * Used to listen for when a player joins 15 | * @param event The event 16 | */ 17 | @EventHandler 18 | public void onJoin(PlayerLoginEvent event) { 19 | if (event.getPlayer().isOp()) { 20 | if (DisplayEntityEditor.getPlugin().getConfig().getBoolean("send-update-message-on-join")) { 21 | DisplayEntityEditor. 22 | getVersion(v -> { 23 | if (!DisplayEntityEditor.getPlugin().getDescription().getVersion().equals(v)) { 24 | event.getPlayer().sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("version_check_fail"))); 25 | event.getPlayer().sendMessage(ChatColor.GRAY + DisplayEntityEditor.messageManager.getString("version_check_disable_hint")); 26 | } 27 | }); 28 | 29 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> { 30 | if (DisplayEntityEditor.getPlugin().getConfig().getBoolean("use-messages-file")) { 31 | if (!DisplayEntityEditor.getPlugin().getDescription().getVersion().equals(DisplayEntityEditor.messageManager.getString("file_version"))) { 32 | event.getPlayer().sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("messages_file_outdated_version"))); 33 | } 34 | if (!DisplayEntityEditor.messageManager.isMessageMapComplete()) { 35 | event.getPlayer().sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("messages_file_incomplete"))); 36 | } 37 | } 38 | }, 10L); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/EditingHandler.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor; 2 | 3 | import org.bukkit.entity.Display; 4 | import org.bukkit.entity.Player; 5 | 6 | import goldenshadow.displayentityeditor.enums.LockSearchMode; 7 | 8 | import javax.annotation.Nullable; 9 | import java.util.*; 10 | 11 | public class EditingHandler { 12 | 13 | /** 14 | * The map of player UUIDs to the displays they are currently editing. 15 | */ 16 | private final Map> editingDisplaysMap = new HashMap<>(); 17 | 18 | /** 19 | * @param player The player that should be editing the displays. 20 | * @param displays The collection of displays the player should be editing. 21 | */ 22 | public void setEditingDisplays(Player player, Collection displays) { 23 | editingDisplaysMap.put(player.getUniqueId(), displays); 24 | } 25 | 26 | /** 27 | * @param player The player that should no longer be editing any displays. 28 | */ 29 | public void removeEditingDisplays(Player player) { 30 | editingDisplaysMap.remove(player.getUniqueId()); 31 | } 32 | 33 | /** 34 | * @param player The player that is editing display(s). 35 | * @return The collection of displays the player is currently editing. 36 | * If the player is not editing any displays, an display search is being started according to the players' @{link SelectionMode}. 37 | * 38 | * Please note that this method will use the players' currently selected {@link LockSearchMode}. 39 | */ 40 | @Nullable 41 | public Collection getEditingDisplays(Player player) { 42 | return getEditingDisplays(player, Utilities.getToolSearchMode(player)); 43 | } 44 | 45 | /** 46 | * @param player The player that is editing display(s). 47 | * @param lockSearchMode The lock search mode to check if an entity should be included in the selection or not. 48 | * @return The collection of displays the player is currently editing. 49 | * If the player is not editing any displays, an display search is being started according to the players' @{link SelectionMode}. 50 | * @see SelectionMode#select(Player, LockSearchMode) 51 | */ 52 | @Nullable 53 | public Collection getEditingDisplays(Player player, LockSearchMode lockSearchMode) { 54 | Collection displays = editingDisplaysMap.get(player.getUniqueId()); 55 | if (displays != null) { 56 | return displays; 57 | } 58 | return Utilities.getToolSelectMode(player).select(player, lockSearchMode); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/MessageManager.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor; 2 | 3 | import org.yaml.snakeyaml.Yaml; 4 | 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | 13 | public class MessageManager { 14 | 15 | private final HashMap fallbackMap; 16 | private final HashMap messageMap; 17 | 18 | public MessageManager() throws IOException { 19 | Yaml yaml = new Yaml(); 20 | InputStream fallbackFileStream = DisplayEntityEditor.class.getClassLoader().getResourceAsStream("messages.yml"); 21 | File f = new File(DisplayEntityEditor.getPlugin().getDataFolder().getAbsolutePath() + "/messages.yml"); 22 | InputStream configStream = new FileInputStream(f); 23 | assert fallbackFileStream != null; 24 | fallbackMap = yaml.load(fallbackFileStream); 25 | messageMap = yaml.load(configStream); 26 | configStream.close(); 27 | fallbackFileStream.close(); 28 | } 29 | 30 | public String getString(String key) { 31 | String s = ""; 32 | if (messageMap.containsKey(key) && DisplayEntityEditor.getPlugin().getConfig().getBoolean("use-messages-file")) { 33 | Object o = messageMap.get(key); 34 | if (o instanceof String) { 35 | s = (String) o; 36 | } 37 | } else { 38 | if (fallbackMap.containsKey(key) && !key.equals("file_version")) { //file version should never be gotten from fallback 39 | Object o = fallbackMap.get(key); 40 | if (o instanceof String) { 41 | s = (String) o; 42 | } 43 | } 44 | } 45 | return s; 46 | } 47 | 48 | public List getList(String key) { 49 | Object o = null; 50 | if (messageMap.containsKey(key) && DisplayEntityEditor.getPlugin().getConfig().getBoolean("use-messages-file")) { 51 | o = messageMap.get(key); 52 | } else if (fallbackMap.containsKey(key)) { 53 | o = fallbackMap.get(key); 54 | } 55 | 56 | List returnList = new ArrayList<>(); 57 | if (o instanceof ArrayList list) { 58 | for (Object ob : list) { 59 | if (ob instanceof String s) { 60 | returnList.add(s); 61 | } 62 | } 63 | } 64 | return returnList; 65 | } 66 | 67 | /** 68 | * Used to check if all messages are in the messages.yml being used 69 | * @return True if everything is fine, false if the file should be updated 70 | */ 71 | public boolean isMessageMapComplete() { 72 | for (String key : fallbackMap.keySet()) { 73 | if (!messageMap.containsKey(key)) return false; 74 | } 75 | return true; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/conversation/IntegerPrompt.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.conversation; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import org.bukkit.conversations.ConversationContext; 6 | import org.bukkit.conversations.NumericPrompt; 7 | import org.bukkit.conversations.Prompt; 8 | import org.bukkit.entity.Player; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | 13 | public class IntegerPrompt extends NumericPrompt { 14 | 15 | private final String message; 16 | 17 | /** 18 | * Used to create a new integer prompt 19 | * @param message The message that should be displayed 20 | */ 21 | public IntegerPrompt(String message) { 22 | this.message = message; 23 | } 24 | 25 | /** 26 | * Used to get the prompt text 27 | * @param conversationContext The conversation context 28 | * @return The message specified when this object was created 29 | */ 30 | @NotNull 31 | @Override 32 | public String getPromptText(@NotNull ConversationContext conversationContext) { 33 | return message; 34 | } 35 | 36 | /** 37 | * Used for when a valid input was given 38 | * @param conversationContext The conversation context 39 | * @param number The value that was given 40 | * @return End of the conversation 41 | */ 42 | @Nullable 43 | @Override 44 | protected Prompt acceptValidatedInput(@NotNull ConversationContext conversationContext, @NotNull Number number) { 45 | int i = number.intValue(); 46 | InputData inputData = (InputData) conversationContext.getSessionData("data"); 47 | assert inputData != null; 48 | InputManager.successfulIntegerInput(inputData, i, (Player) conversationContext.getForWhom()); 49 | return END_OF_CONVERSATION; 50 | } 51 | 52 | /** 53 | * Used to check if a given number is valid 54 | * @param context The conversation context 55 | * @param input The input 56 | * @return True if it is an integer, false otherwise 57 | */ 58 | @Override 59 | protected boolean isNumberValid(@NotNull ConversationContext context, @NotNull Number input) { 60 | return input instanceof Integer; 61 | } 62 | 63 | /** 64 | * Used for when an invalid non number input was given 65 | * @param context The conversation context 66 | * @param invalidInput The invalid input 67 | * @return An error message 68 | */ 69 | @Nullable 70 | @Override 71 | protected String getFailedValidationText(@NotNull ConversationContext context, @NotNull Number invalidInput) { 72 | return Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("integer_fail")); 73 | } 74 | 75 | /** 76 | * Used for when an invalid number was given 77 | * @param context The conversation context 78 | * @param invalidInput The invalid input 79 | * @return An error message 80 | */ 81 | @Nullable 82 | @Override 83 | protected String getFailedValidationText(@NotNull ConversationContext context, @NotNull String invalidInput) { 84 | return Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("integer_fail")); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/conversation/BytePrompt.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.conversation; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import org.bukkit.conversations.ConversationContext; 6 | import org.bukkit.conversations.NumericPrompt; 7 | import org.bukkit.conversations.Prompt; 8 | import org.bukkit.entity.Player; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | 13 | public class BytePrompt extends NumericPrompt { 14 | 15 | private final String message; 16 | 17 | /** 18 | * Used to create a new byte prompt 19 | * @param message The message that should be displayed 20 | */ 21 | public BytePrompt(String message) { 22 | this.message = message; 23 | } 24 | 25 | /** 26 | * Used to get the prompt text 27 | * @param conversationContext The conversation context 28 | * @return The message specified when this object was created 29 | */ 30 | @NotNull 31 | @Override 32 | public String getPromptText(@NotNull ConversationContext conversationContext) { 33 | return message; 34 | } 35 | 36 | /** 37 | * Used for when a valid input was given 38 | * @param conversationContext The conversation context 39 | * @param number The value that was given 40 | * @return End of the conversation 41 | */ 42 | @Nullable 43 | @Override 44 | protected Prompt acceptValidatedInput(@NotNull ConversationContext conversationContext, @NotNull Number number) { 45 | int integer = number.intValue(); 46 | Player player = (Player) conversationContext.getForWhom(); 47 | InputData inputData = (InputData) conversationContext.getSessionData("data"); 48 | assert inputData != null; 49 | InputManager.successfulByteInput(inputData, integer, player); 50 | return END_OF_CONVERSATION; 51 | } 52 | 53 | /** 54 | * Used to check if a given number is valid 55 | * @param context The conversation context 56 | * @param input The input 57 | * @return True if it is an integer between 0 and 255, false otherwise 58 | */ 59 | @Override 60 | protected boolean isNumberValid(@NotNull ConversationContext context, @NotNull Number input) { 61 | if (input instanceof Integer i) { 62 | return 0 <= i && i <= 255; 63 | } 64 | return false; 65 | } 66 | 67 | /** 68 | * Used for when an invalid non number input was given 69 | * @param context The conversation context 70 | * @param invalidInput The invalid input 71 | * @return An error message 72 | */ 73 | @Nullable 74 | @Override 75 | protected String getFailedValidationText(@NotNull ConversationContext context, @NotNull Number invalidInput) { 76 | return Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("integer_fail")); 77 | } 78 | 79 | /** 80 | * Used for when an invalid number was given 81 | * @param context The conversation context 82 | * @param invalidInput The invalid input 83 | * @return An error message 84 | */ 85 | @Nullable 86 | @Override 87 | protected String getFailedValidationText(@NotNull ConversationContext context, @NotNull String invalidInput) { 88 | return Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("integer_fail")); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/conversation/FloatPrompt.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.conversation; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import goldenshadow.displayentityeditor.enums.InputType; 6 | import org.bukkit.conversations.ConversationContext; 7 | import org.bukkit.conversations.NumericPrompt; 8 | import org.bukkit.conversations.Prompt; 9 | import org.bukkit.entity.Player; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | 14 | public class FloatPrompt extends NumericPrompt { 15 | 16 | private final String message; 17 | 18 | /** 19 | * Used to create a new float prompt 20 | * @param message The message that should be displayed 21 | */ 22 | public FloatPrompt(String message) { 23 | this.message = message; 24 | } 25 | 26 | /** 27 | * Used to get the prompt text 28 | * @param conversationContext The conversation context 29 | * @return The message specified when this object was created 30 | */ 31 | @NotNull 32 | @Override 33 | public String getPromptText(@NotNull ConversationContext conversationContext) { 34 | return message; 35 | } 36 | 37 | /** 38 | * Used for when a valid input was given 39 | * @param conversationContext The conversation context 40 | * @param number The value that was given 41 | * @return End of the conversation 42 | */ 43 | @Nullable 44 | @Override 45 | protected Prompt acceptValidatedInput(@NotNull ConversationContext conversationContext, @NotNull Number number) { 46 | float f = number.floatValue(); 47 | Player player = (Player) conversationContext.getForWhom(); 48 | InputData inputData = (InputData) conversationContext.getSessionData("data"); 49 | assert inputData != null; 50 | InputManager.successfulFloatInput(inputData, f, player); 51 | return END_OF_CONVERSATION; 52 | } 53 | 54 | /** 55 | * Used to check if a given number is valid 56 | * @param context The conversation context 57 | * @param input The input 58 | * @return True if it is a float, false otherwise. Additionally, if the input type is shadow strength, the value must be between 0 and 1 for true to be returned 59 | */ 60 | @Override 61 | protected boolean isNumberValid(@NotNull ConversationContext context, @NotNull Number input) { 62 | InputData data = (InputData) context.getSessionData("data"); 63 | assert data != null; 64 | if (data.inputType() == InputType.SHADOW_STRENGTH) { 65 | float f = input.floatValue(); 66 | return 0 <= f && f <= 1; 67 | } 68 | return true; 69 | } 70 | 71 | /** 72 | * Used for when an invalid non number input was given 73 | * @param context The conversation context 74 | * @param invalidInput The invalid input 75 | * @return An error message 76 | */ 77 | @Nullable 78 | @Override 79 | protected String getFailedValidationText(@NotNull ConversationContext context, @NotNull String invalidInput) { 80 | return Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("float_fail")); 81 | } 82 | 83 | /** 84 | * Used for when an invalid number was given 85 | * @param context The conversation context 86 | * @param invalidInput The invalid input 87 | * @return An error message 88 | */ 89 | @Nullable 90 | @Override 91 | protected String getFailedValidationText(@NotNull ConversationContext context, @NotNull Number invalidInput) { 92 | InputData data = (InputData) context.getSessionData("data"); 93 | assert data != null; 94 | if (data.inputType() == InputType.SHADOW_STRENGTH) { 95 | return Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("float_shadow_strength_fail")); 96 | } 97 | return Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("float_fail")); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | goldenshadow 8 | DisplayEntityEditor 9 | 1.0.17 10 | jar 11 | 12 | DisplayEntityEditor 13 | 14 | A full suite of tools to edit text, item and block display entities 15 | 16 | 17 17 | UTF-8 18 | 19 | 20 | 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-compiler-plugin 25 | 3.8.1 26 | 27 | ${java.version} 28 | ${java.version} 29 | 30 | 31 | 32 | org.apache.maven.plugins 33 | maven-shade-plugin 34 | 3.2.4 35 | 36 | 37 | package 38 | 39 | shade 40 | 41 | 42 | false 43 | 44 | 45 | 46 | 47 | 48 | org.apache.maven.plugins 49 | maven-shade-plugin 50 | 3.3.0 51 | 52 | 53 | 54 | org.bstats 55 | goldenshadow.displayentityeditor 56 | 57 | 58 | 59 | 60 | 61 | package 62 | 63 | shade 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | src/main/resources 72 | true 73 | 74 | 75 | 76 | 77 | 78 | 79 | spigotmc-repo 80 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 81 | 82 | 83 | sonatype 84 | https://oss.sonatype.org/content/groups/public/ 85 | 86 | 87 | 88 | 89 | 90 | org.spigotmc 91 | spigot-api 92 | 1.19.4-R0.1-SNAPSHOT 93 | provided 94 | 95 | 96 | org.yaml 97 | snakeyaml 98 | 2.1 99 | 100 | 101 | org.jetbrains 102 | annotations 103 | RELEASE 104 | compile 105 | 106 | 107 | org.bstats 108 | bstats-bukkit 109 | 3.0.2 110 | compile 111 | 112 | 113 | net.kyori 114 | adventure-text-minimessage 115 | 4.14.0 116 | 117 | 118 | net.kyori 119 | adventure-platform-bukkit 120 | 4.3.0 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/SelectionMode.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | import java.util.stream.Stream; 9 | 10 | import org.bukkit.Location; 11 | import org.bukkit.World; 12 | import org.bukkit.entity.Display; 13 | import org.bukkit.entity.Entity; 14 | import org.bukkit.entity.Player; 15 | import org.bukkit.util.Vector; 16 | 17 | import goldenshadow.displayentityeditor.enums.LockSearchMode; 18 | 19 | public abstract class SelectionMode { 20 | 21 | private static final Predicate DISPLAY_FILTER = entity -> entity instanceof Display; 22 | private static final Function DISPLAY_CAST = entity -> (Display) entity; 23 | 24 | private static final HashMap idToMode = new HashMap<>(); 25 | private static final ArrayList idOrder = new ArrayList<>(); 26 | 27 | public static int amount() { 28 | return idOrder.size(); 29 | } 30 | 31 | public static SelectionMode get(String mode) { 32 | return idToMode.get(mode); 33 | } 34 | 35 | public static final SelectionMode NEARBY = new SelectionMode("nearby") { 36 | 37 | @Override 38 | protected Stream select(Player p, double range, Predicate lockFilter) { 39 | return p.getWorld().getNearbyEntities(p.getLocation(), range, range, range).stream().filter(DISPLAY_FILTER).map(DISPLAY_CAST) 40 | .filter(lockFilter); 41 | } 42 | 43 | }; 44 | 45 | public static final SelectionMode RAYCAST = new SelectionMode("raycast") { 46 | 47 | @Override 48 | protected Stream select(Player p, double range, Predicate lockFilter) { 49 | Location loc = p.getEyeLocation(); 50 | Vector direction = loc.getDirection().normalize(); 51 | double x = loc.getX(); 52 | double y = loc.getY(); 53 | double z = loc.getZ(); 54 | double dx = direction.getX(); 55 | double dy = direction.getY(); 56 | double dz = direction.getZ(); 57 | World world = p.getWorld(); 58 | List displays; 59 | for (double distance = 0d; distance < range; distance += 0.25d) { 60 | displays = world.getNearbyEntities(loc = new Location(world, x + dx * distance, y + dy * distance, z + dz * distance), 61 | 0.75d, 0.25d, 0.75d).stream().filter(DISPLAY_FILTER).map(DISPLAY_CAST).filter(lockFilter).toList(); 62 | if (displays.isEmpty()) { 63 | continue; 64 | } 65 | double tmp; 66 | Display closest = null; 67 | distance = Double.MAX_VALUE; 68 | for (Display display : displays) { 69 | tmp = loc.distanceSquared(display.getLocation()); 70 | if (tmp < distance) { 71 | distance = tmp; 72 | closest = display; 73 | } 74 | } 75 | return Stream.of(closest); 76 | } 77 | return Stream.empty(); 78 | } 79 | 80 | }; 81 | 82 | private final String id; 83 | 84 | public SelectionMode(String id) { 85 | this.id = id; 86 | idOrder.add(id); 87 | idToMode.put(id, this); 88 | } 89 | 90 | public final String id() { 91 | return id; 92 | } 93 | 94 | public final int index() { 95 | return idOrder.indexOf(id); 96 | } 97 | 98 | public final SelectionMode previousMode() { 99 | int i = idOrder.indexOf(id); 100 | return idToMode.get(i == 0 ? idOrder.get(idOrder.size() - 1) : idOrder.get(i - 1)); 101 | } 102 | 103 | public final SelectionMode nextMode() { 104 | int i = idOrder.indexOf(id); 105 | return idToMode.get(i + 1 == idOrder.size() ? idOrder.get(0) : idOrder.get(i + 1)); 106 | } 107 | 108 | public final List select(Player p, LockSearchMode lockSearchMode) { 109 | List displays = select(p, Utilities.getToolSelectRange(p), lockSearchMode.getPredicate()).toList(); 110 | if (displays.isEmpty()) { 111 | return null; 112 | } 113 | if (displays.size() == 1) { 114 | return displays; 115 | } 116 | if (Utilities.getToolSelectMultiple(p)) { 117 | return displays; 118 | } 119 | Display closest = null; 120 | double tmp, distance = Double.MAX_VALUE; 121 | Location pLoc = p.getLocation(); 122 | for (Display display : displays) { 123 | tmp = pLoc.distanceSquared(display.getLocation()); 124 | if (tmp < distance) { 125 | distance = tmp; 126 | closest = display; 127 | } 128 | } 129 | // Never null 130 | return List.of(closest); 131 | } 132 | 133 | protected abstract Stream select(Player p, double range, Predicate lockFilter); 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/DisplayEntityEditor.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor; 2 | 3 | import goldenshadow.displayentityeditor.commands.Command; 4 | import goldenshadow.displayentityeditor.commands.TabComplete; 5 | import goldenshadow.displayentityeditor.events.*; 6 | import goldenshadow.displayentityeditor.inventories.InventoryFactory; 7 | import goldenshadow.displayentityeditor.items.GUIItems; 8 | import goldenshadow.displayentityeditor.items.InventoryItems; 9 | import net.kyori.adventure.text.minimessage.MiniMessage; 10 | import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 11 | import net.kyori.adventure.text.minimessage.tag.standard.StandardTags; 12 | import org.bstats.bukkit.Metrics; 13 | import org.bukkit.Bukkit; 14 | import org.bukkit.NamespacedKey; 15 | import org.bukkit.conversations.ConversationFactory; 16 | import org.bukkit.entity.Display; 17 | import org.bukkit.entity.Player; 18 | import org.bukkit.plugin.java.JavaPlugin; 19 | 20 | import java.io.*; 21 | import java.net.URL; 22 | import java.nio.file.Files; 23 | import java.nio.file.StandardCopyOption; 24 | import java.util.*; 25 | import java.util.function.Consumer; 26 | 27 | public final class DisplayEntityEditor extends JavaPlugin { 28 | 29 | private static DisplayEntityEditor plugin; 30 | public static ConversationFactory conversationFactory; 31 | public static InventoryFactory inventoryFactory; 32 | public static HashMap currentEditMap = new HashMap<>(); 33 | public static boolean alternateTextInput = false; 34 | public static boolean useMiniMessageFormat = false; 35 | public static MiniMessage miniMessage = MiniMessage.builder() 36 | .tags(TagResolver.builder() 37 | .resolver(StandardTags.color()) 38 | .resolver(StandardTags.decorations()) 39 | .resolver(StandardTags.gradient()) 40 | .resolver(StandardTags.rainbow()) 41 | .resolver(StandardTags.font()) 42 | .resolver(StandardTags.newline()) 43 | .resolver(StandardTags.keybind()) 44 | .resolver(StandardTags.nbt()) 45 | .resolver(StandardTags.score()) 46 | .resolver(StandardTags.transition()) 47 | .build() 48 | ) 49 | .build(); 50 | public static MessageManager messageManager; 51 | 52 | public static NamespacedKey toolSelectionModeKey; 53 | public static NamespacedKey toolSelectionRangeKey; 54 | public static NamespacedKey toolSelectionMultipleKey; 55 | public static NamespacedKey toolSelectionSearchModeKey; 56 | public static NamespacedKey toolPrecisionKey; 57 | public static NamespacedKey toolKey; 58 | 59 | private EditingHandler editingHandler; 60 | 61 | /** 62 | * Used for when the plugin starts up 63 | */ 64 | @Override 65 | public void onEnable() { 66 | plugin = this; 67 | 68 | getConfig().options().copyDefaults(true); 69 | saveConfig(); 70 | alternateTextInput = getConfig().getBoolean("alternate-text-input"); 71 | useMiniMessageFormat = getConfig().getBoolean("use-minimessage-format"); 72 | 73 | try { 74 | checkForMessageFile(); 75 | } catch (IOException e) { 76 | plugin.getLogger().severe("Failed to load messages.yml!"); 77 | } 78 | 79 | this.editingHandler = new EditingHandler(); 80 | 81 | conversationFactory = new ConversationFactory(plugin); 82 | inventoryFactory = new InventoryFactory(new GUIItems(), new InventoryItems()); 83 | Objects.requireNonNull(getCommand("displayentityeditor")).setExecutor(new Command()); 84 | Objects.requireNonNull(getCommand("displayentityeditor")).setTabCompleter(new TabComplete()); 85 | Bukkit.getPluginManager().registerEvents(new Interact(editingHandler), plugin); 86 | Bukkit.getPluginManager().registerEvents(new OffhandSwap(editingHandler), plugin); 87 | Bukkit.getPluginManager().registerEvents(new InventoryClick(), plugin); 88 | Bukkit.getPluginManager().registerEvents(new InventoryClose(), plugin); 89 | Bukkit.getPluginManager().registerEvents(new PlayerJoin(), plugin); 90 | Bukkit.getPluginManager().registerEvents(new PlayerLeave(), plugin); 91 | 92 | toolSelectionModeKey = new NamespacedKey(plugin, "toolSelectionMode"); 93 | toolSelectionRangeKey = new NamespacedKey(plugin, "toolSelectionRange"); 94 | toolSelectionMultipleKey = new NamespacedKey(plugin, "toolSelectionMultiple"); 95 | toolSelectionSearchModeKey = new NamespacedKey(plugin, "toolSelectionSearchMode"); 96 | toolPrecisionKey = new NamespacedKey(plugin, "toolPrecision"); 97 | toolKey = new NamespacedKey(plugin, "tool"); 98 | 99 | new Metrics(plugin, 18672); 100 | 101 | getVersion(v -> { 102 | if (this.getDescription().getVersion().equals(v)) { 103 | getLogger().info(messageManager.getString("version_check_success")); 104 | } else { 105 | getLogger().warning(messageManager.getString("version_check_fail")); 106 | } 107 | }); 108 | 109 | if (getConfig().getBoolean("use-messages-file")) { 110 | if (!getDescription().getVersion().equals(messageManager.getString("file_version"))) { 111 | getLogger().warning(messageManager.getString("messages_file_outdated_version")); 112 | } 113 | if (!messageManager.isMessageMapComplete()) { 114 | getLogger().warning(messageManager.getString("messages_file_incomplete")); 115 | } 116 | } 117 | 118 | } 119 | 120 | @Override 121 | public void onDisable() { 122 | for (Player player : Bukkit.getOnlinePlayers()) { 123 | Command.returnInventory(player); 124 | } 125 | } 126 | 127 | /** 128 | * Getter for the plugin instance 129 | * @return The plugin 130 | */ 131 | public static DisplayEntityEditor getPlugin() { 132 | return plugin; 133 | } 134 | 135 | /** 136 | * Used to get the newest version of the plugin available on spigot 137 | * @param consumer The consumer 138 | */ 139 | public static void getVersion(final Consumer consumer) { 140 | Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { 141 | try (InputStream inputStream = new URL("https://api.spigotmc.org/legacy/update.php?resource=110267").openStream(); Scanner scanner = new Scanner(inputStream)) { 142 | if (scanner.hasNext()) { 143 | consumer.accept(scanner.next()); 144 | } 145 | } catch (IOException exception) { 146 | plugin.getLogger().warning(messageManager.getString("version_check_error").formatted(exception.getMessage())); 147 | } 148 | }); 149 | } 150 | 151 | public static void checkForMessageFile() throws IOException { 152 | File file = new File(getPlugin().getDataFolder().getAbsolutePath() + "/messages.yml"); 153 | if (!file.exists()) { 154 | plugin.getLogger().info("Unable to find messages.yml - generating new file!"); 155 | InputStream ip = DisplayEntityEditor.class.getClassLoader().getResourceAsStream("messages.yml"); 156 | assert ip != null; 157 | Files.copy(ip, file.toPath(), StandardCopyOption.REPLACE_EXISTING); 158 | } 159 | messageManager = new MessageManager(); 160 | } 161 | 162 | public EditingHandler getEditingHandler() { 163 | return editingHandler; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/events/OffhandSwap.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.events; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.EditingHandler; 5 | import goldenshadow.displayentityeditor.Utilities; 6 | import org.bukkit.entity.*; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.player.PlayerSwapHandItemsEvent; 10 | import org.bukkit.inventory.ItemStack; 11 | import org.bukkit.util.Transformation; 12 | import org.joml.Quaternionf; 13 | import org.joml.Vector3f; 14 | 15 | import java.util.Collection; 16 | 17 | public class OffhandSwap implements Listener { 18 | 19 | private final EditingHandler editingHandler; 20 | 21 | public OffhandSwap(EditingHandler handler) { 22 | editingHandler = handler; 23 | } 24 | 25 | @EventHandler 26 | public void offHand(PlayerSwapHandItemsEvent event) { 27 | Player player = event.getPlayer(); 28 | if (!Utilities.hasDataKey(player.getInventory().getItemInMainHand())) { 29 | return; 30 | } 31 | event.setCancelled(true); 32 | 33 | ItemStack item = player.getInventory().getItemInMainHand(); 34 | String toolValue = Utilities.getToolValue(item); 35 | 36 | if (toolValue == null) { 37 | return; 38 | } 39 | 40 | switch(toolValue) { 41 | case "InventoryToolSelectionMode" -> { 42 | Utilities.sendActionbarMessage(player, DisplayEntityEditor.messageManager.getString("value_reset")); 43 | player.getPersistentDataContainer().remove(DisplayEntityEditor.toolSelectionModeKey); 44 | return; 45 | } 46 | case "InventoryToolSelectionRange" -> { 47 | Utilities.sendActionbarMessage(player, DisplayEntityEditor.messageManager.getString("value_reset")); 48 | player.getPersistentDataContainer().remove(DisplayEntityEditor.toolSelectionRangeKey); 49 | return; 50 | } 51 | case "InventoryToolSelectionSearchMode" -> { 52 | Utilities.sendActionbarMessage(player, DisplayEntityEditor.messageManager.getString("value_reset")); 53 | player.getPersistentDataContainer().remove(DisplayEntityEditor.toolSelectionSearchModeKey); 54 | return; 55 | } 56 | case "InventoryToolSelectionMultiple" -> { 57 | Utilities.sendActionbarMessage(player, DisplayEntityEditor.messageManager.getString("value_reset")); 58 | player.getPersistentDataContainer().remove(DisplayEntityEditor.toolSelectionMultipleKey); 59 | return; 60 | } 61 | } 62 | 63 | Collection displays = editingHandler.getEditingDisplays(player); 64 | if (displays == null) { 65 | player.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 66 | return; 67 | } 68 | Utilities.sendActionbarMessage(player, DisplayEntityEditor.messageManager.getString("value_reset")); 69 | switch (toolValue) { 70 | case "InventoryRotateYaw" -> { 71 | displays.forEach(display -> display.setRotation(0, display.getLocation().getPitch())); 72 | } 73 | case "InventoryRotatePitch" -> { 74 | displays.forEach(display -> display.setRotation(display.getLocation().getYaw(), 0)); 75 | } 76 | case "InventoryTX" -> { 77 | displays.forEach(display -> { 78 | Transformation t = display.getTransformation(); 79 | t = new Transformation(new Vector3f(0, t.getTranslation().y(), t.getTranslation().z()), t.getLeftRotation(), t.getScale(), t.getRightRotation()); 80 | display.setTransformation(t); 81 | }); 82 | } 83 | case "InventoryTY" -> { 84 | displays.forEach(display -> { 85 | Transformation t = display.getTransformation(); 86 | t = new Transformation(new Vector3f(t.getTranslation().x(), 0, t.getTranslation().z()), t.getLeftRotation(), t.getScale(), t.getRightRotation()); 87 | display.setTransformation(t); 88 | }); 89 | } 90 | case "InventoryTZ" -> { 91 | displays.forEach(display -> { 92 | Transformation t = display.getTransformation(); 93 | t = new Transformation(new Vector3f(t.getTranslation().x(), t.getTranslation().y(), 0), t.getLeftRotation(), t.getScale(), t.getRightRotation()); 94 | display.setTransformation(t); 95 | }); 96 | } 97 | case "InventorySX" -> { 98 | displays.forEach(display -> { 99 | Transformation t = display.getTransformation(); 100 | t = new Transformation(t.getTranslation(), t.getLeftRotation(), new Vector3f(0, t.getScale().y(), t.getScale().z()), t.getRightRotation()); 101 | display.setTransformation(t); 102 | }); 103 | } 104 | case "InventorySY" -> { 105 | displays.forEach(display -> { 106 | Transformation t = display.getTransformation(); 107 | t = new Transformation(t.getTranslation(), t.getLeftRotation(), new Vector3f(t.getScale().x(), 0, t.getScale().z()), t.getRightRotation()); 108 | display.setTransformation(t); 109 | }); 110 | } 111 | case "InventorySZ" -> { 112 | displays.forEach(display -> { 113 | Transformation t = display.getTransformation(); 114 | t = new Transformation(t.getTranslation(), t.getLeftRotation(), new Vector3f(t.getScale().x(), t.getScale().y(), 0), t.getRightRotation()); 115 | display.setTransformation(t); 116 | }); 117 | } 118 | case "InventoryLRX" -> { 119 | displays.forEach(display -> { 120 | Transformation t = display.getTransformation(); 121 | t = new Transformation(t.getTranslation(), new Quaternionf(0, t.getLeftRotation().y(), t.getLeftRotation().z(), t.getLeftRotation().w()), t.getScale(), t.getRightRotation()); 122 | display.setTransformation(t); 123 | }); 124 | } 125 | case "InventoryLRY" -> { 126 | displays.forEach(display -> { 127 | Transformation t = display.getTransformation(); 128 | t = new Transformation(t.getTranslation(), new Quaternionf(t.getLeftRotation().x(), 0, t.getLeftRotation().z(), t.getLeftRotation().w()), t.getScale(), t.getRightRotation()); 129 | display.setTransformation(t); 130 | }); 131 | } 132 | case "InventoryLRZ" -> { 133 | displays.forEach(display -> { 134 | Transformation t = display.getTransformation(); 135 | t = new Transformation(t.getTranslation(), new Quaternionf(t.getLeftRotation().x(), t.getLeftRotation().y(), 0, t.getLeftRotation().w()), t.getScale(), t.getRightRotation()); 136 | display.setTransformation(t); 137 | }); 138 | } 139 | case "InventoryRRX" -> { 140 | displays.forEach(display -> { 141 | Transformation t = display.getTransformation(); 142 | t = new Transformation(t.getTranslation(), t.getLeftRotation(), t.getScale(), new Quaternionf(0, t.getRightRotation().y(), t.getRightRotation().z(), t.getRightRotation().w())); 143 | display.setTransformation(t); 144 | }); 145 | } 146 | case "InventoryRRY" -> { 147 | displays.forEach(display -> { 148 | Transformation t = display.getTransformation(); 149 | t = new Transformation(t.getTranslation(), t.getLeftRotation(), t.getScale(), new Quaternionf(t.getRightRotation().x(), 0, t.getRightRotation().z(), t.getRightRotation().w())); 150 | display.setTransformation(t); 151 | }); 152 | } 153 | case "InventoryRRZ" -> { 154 | displays.forEach(display -> { 155 | Transformation t = display.getTransformation(); 156 | t = new Transformation(t.getTranslation(), t.getLeftRotation(), t.getScale(), new Quaternionf(t.getRightRotation().x(), t.getRightRotation().y(), 0, t.getRightRotation().w())); 157 | display.setTransformation(t); 158 | }); 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/inventories/InventoryFactory.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.inventories; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import goldenshadow.displayentityeditor.items.GUIItems; 6 | import goldenshadow.displayentityeditor.items.InventoryItems; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.ChatColor; 9 | import org.bukkit.entity.BlockDisplay; 10 | import org.bukkit.entity.ItemDisplay; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.entity.TextDisplay; 13 | import org.bukkit.inventory.Inventory; 14 | import org.bukkit.inventory.ItemStack; 15 | 16 | public class InventoryFactory { 17 | 18 | private final GUIItems guiItems; 19 | private final InventoryItems inventoryItems; 20 | 21 | /** 22 | * Used to create a new inventory factory 23 | * @param guiItems The gui items object it should use 24 | * @param inventoryItems The inventory items object it should use 25 | */ 26 | public InventoryFactory(GUIItems guiItems, InventoryItems inventoryItems) { 27 | this.guiItems = guiItems; 28 | this.inventoryItems = inventoryItems; 29 | } 30 | 31 | /** 32 | * Getter for the gui items 33 | * @return The class containing all gui items 34 | */ 35 | public GUIItems getGuiItems() { 36 | return guiItems; 37 | } 38 | 39 | public InventoryItems getInventoryItems() { 40 | return inventoryItems; 41 | } 42 | 43 | 44 | /** 45 | * Used to create the gui for item displays 46 | * @param entity The item display entity being edited 47 | * @return The gui 48 | */ 49 | public Inventory createItemDisplayGUI(ItemDisplay entity) { 50 | Inventory inventory = Bukkit.createInventory(null, 27, ChatColor.translateAlternateColorCodes('&' ,DisplayEntityEditor.messageManager.getString("item_display_gui_name"))); 51 | for (int i = 0; i < inventory.getSize(); i++) { 52 | switch (i) { 53 | case 4 -> inventory.setItem(i, guiItems.name(entity.getCustomName())); 54 | case 5 -> inventory.setItem(i, guiItems.rightRotNormalize(Utilities.getData(entity, "GUIRRNormalize"))); 55 | case 6 -> inventory.setItem(i, guiItems.height(entity.getDisplayHeight())); 56 | case 7 -> inventory.setItem(i, guiItems.shadowRadius(entity.getShadowRadius())); 57 | case 8 -> inventory.setItem(i, guiItems.skyLight(entity.getBrightness() != null ? entity.getBrightness().getSkyLight() : -1)); 58 | 59 | case 10 -> inventory.setItem(i, entity.getItemStack()); 60 | case 12 -> inventory.setItem(i, guiItems.itemDisplayTransform(entity.getItemDisplayTransform())); 61 | case 13 -> inventory.setItem(i, guiItems.glowing(entity.isGlowing())); 62 | case 14 -> inventory.setItem(i, guiItems.leftRotNormalize(Utilities.getData(entity, "GUILRNormalize"))); 63 | case 15 -> inventory.setItem(i, guiItems.width(entity.getDisplayWidth())); 64 | case 16 -> inventory.setItem(i, guiItems.shadowStrength(entity.getShadowStrength())); 65 | case 17 -> inventory.setItem(i, guiItems.blockLight(entity.getBrightness() != null ? entity.getBrightness().getBlockLight() : -1)); 66 | 67 | case 22 -> inventory.setItem(i, guiItems.glowColor(entity.getGlowColorOverride())); 68 | case 23 -> inventory.setItem(i, guiItems.viewRange(entity.getViewRange())); 69 | case 24 -> inventory.setItem(i, guiItems.billboard(entity.getBillboard())); 70 | case 25 -> inventory.setItem(i, guiItems.lock()); 71 | case 26 -> inventory.setItem(i, guiItems.delete()); 72 | default -> inventory.setItem(i, guiItems.filler()); 73 | } 74 | } 75 | return inventory; 76 | } 77 | 78 | /** 79 | * Used to create the gui for block displays 80 | * @param entity The block display entity being edited 81 | * @return The gui 82 | */ 83 | public Inventory createBlockDisplayGUI(BlockDisplay entity) { 84 | Inventory inventory = Bukkit.createInventory(null, 27, ChatColor.translateAlternateColorCodes('&' ,DisplayEntityEditor.messageManager.getString("block_display_gui_name"))); 85 | for (int i = 0; i < inventory.getSize(); i++) { 86 | switch (i) { 87 | case 4 -> inventory.setItem(i, guiItems.name(entity.getCustomName())); 88 | case 5 -> inventory.setItem(i, guiItems.rightRotNormalize(Utilities.getData(entity, "GUIRRNormalize"))); 89 | case 6 -> inventory.setItem(i, guiItems.height(entity.getDisplayHeight())); 90 | case 7 -> inventory.setItem(i, guiItems.shadowRadius(entity.getShadowRadius())); 91 | case 8 -> inventory.setItem(i, guiItems.skyLight(entity.getBrightness() != null ? entity.getBrightness().getSkyLight() : -1)); 92 | 93 | case 10 -> inventory.setItem(i, new ItemStack(entity.getBlock().getMaterial())); 94 | case 11 -> inventory.setItem(i, guiItems.blockState(entity.getBlock().getAsString(true))); 95 | 96 | case 13 -> inventory.setItem(i, guiItems.glowing(entity.isGlowing())); 97 | case 14 -> inventory.setItem(i, guiItems.leftRotNormalize(Utilities.getData(entity, "GUILRNormalize"))); 98 | case 15 -> inventory.setItem(i, guiItems.width(entity.getDisplayWidth())); 99 | case 16 -> inventory.setItem(i, guiItems.shadowStrength(entity.getShadowStrength())); 100 | case 17 -> inventory.setItem(i, guiItems.blockLight(entity.getBrightness() != null ? entity.getBrightness().getBlockLight() : -1)); 101 | 102 | case 22 -> inventory.setItem(i, guiItems.glowColor(entity.getGlowColorOverride())); 103 | case 23 -> inventory.setItem(i, guiItems.viewRange(entity.getViewRange())); 104 | case 24 -> inventory.setItem(i, guiItems.billboard(entity.getBillboard())); 105 | case 25 -> inventory.setItem(i, guiItems.lock()); 106 | case 26 -> inventory.setItem(i, guiItems.delete()); 107 | default -> inventory.setItem(i, guiItems.filler()); 108 | } 109 | } 110 | return inventory; 111 | } 112 | 113 | /** 114 | * Used to create the gui for text displays 115 | * @param entity The text display entity being edited 116 | * @return The gui 117 | */ 118 | @SuppressWarnings("deprecation") 119 | public Inventory createTextDisplayGUI(TextDisplay entity) { 120 | Inventory inventory = Bukkit.createInventory(null, 27, ChatColor.translateAlternateColorCodes('&' ,DisplayEntityEditor.messageManager.getString("text_display_gui_name"))); 121 | for (int i = 0; i < inventory.getSize(); i++) { 122 | switch (i) { 123 | case 2 -> inventory.setItem(i, guiItems.textBackgroundColor(entity.getBackgroundColor())); 124 | case 3 -> inventory.setItem(i, guiItems.textDefaultBackground(entity.isDefaultBackground())); 125 | case 4 -> inventory.setItem(i, guiItems.name(entity.getCustomName())); 126 | case 5 -> inventory.setItem(i, guiItems.rightRotNormalize(Utilities.getData(entity, "GUIRRNormalize"))); 127 | case 6 -> inventory.setItem(i, guiItems.height(entity.getDisplayHeight())); 128 | case 7 -> inventory.setItem(i, guiItems.shadowRadius(entity.getShadowRadius())); 129 | case 8 -> inventory.setItem(i, guiItems.skyLight(entity.getBrightness() != null ? entity.getBrightness().getSkyLight() : -1)); 130 | 131 | case 10 -> inventory.setItem(i, guiItems.text()); 132 | case 11 -> inventory.setItem(i, guiItems.textBackgroundOpacity(entity.getBackgroundColor())); 133 | case 12 -> inventory.setItem(i, guiItems.textSeeThrough(entity.isSeeThrough())); 134 | case 13 -> inventory.setItem(i, guiItems.textOpacity(entity.getTextOpacity())); 135 | case 14 -> inventory.setItem(i, guiItems.leftRotNormalize(Utilities.getData(entity, "GUILRNormalize"))); 136 | case 15 -> inventory.setItem(i, guiItems.width(entity.getDisplayWidth())); 137 | case 16 -> inventory.setItem(i, guiItems.shadowStrength(entity.getShadowStrength())); 138 | case 17 -> inventory.setItem(i, guiItems.blockLight(entity.getBrightness() != null ? entity.getBrightness().getBlockLight() : -1)); 139 | 140 | case 20 -> inventory.setItem(i, guiItems.textAlignment(entity.getAlignment())); 141 | case 21 -> inventory.setItem(i, guiItems.textShadow(entity.isShadowed())); 142 | case 22 -> inventory.setItem(i, guiItems.textLineWidth(entity.getLineWidth())); 143 | case 23 -> inventory.setItem(i, guiItems.viewRange(entity.getViewRange())); 144 | case 24 -> inventory.setItem(i, guiItems.billboard(entity.getBillboard())); 145 | case 25 -> inventory.setItem(i, guiItems.lock()); 146 | case 26 -> inventory.setItem(i, guiItems.delete()); 147 | default -> inventory.setItem(i, guiItems.filler()); 148 | } 149 | } 150 | return inventory; 151 | } 152 | 153 | /** 154 | * Used to generate an array of tools to be easily added to a players inventory 155 | * @return An array of tools 156 | */ 157 | public ItemStack[] getInventoryArray(Player p) { 158 | ItemStack[] array = new ItemStack[36]; 159 | 160 | array[0] = inventoryItems.gui(); 161 | array[1] = inventoryItems.cloneTool(); 162 | array[2] = inventoryItems.groupSelectTool(p); 163 | array[3] = inventoryItems.toolSearchMode(); 164 | array[4] = inventoryItems.toolSelectionMode(p); 165 | array[6] = inventoryItems.toolSelectionMultiple(); 166 | array[5] = inventoryItems.toolSelectionRange(p); 167 | array[7] = inventoryItems.toolPrecision(p); 168 | 169 | array[27] = inventoryItems.spawnItemDisplay(); 170 | array[28] = inventoryItems.spawnBlockDisplay(); 171 | array[29] = inventoryItems.spawnTextDisplay(); 172 | array[30] = inventoryItems.moveX(p); 173 | array[31] = inventoryItems.moveY(p); 174 | array[32] = inventoryItems.moveZ(p); 175 | array[33] = inventoryItems.rotateYaw(p); 176 | array[34] = inventoryItems.rotatePitch(p); 177 | 178 | array[18] = inventoryItems.translationX(p); 179 | array[19] = inventoryItems.translationY(p); 180 | array[20] = inventoryItems.translationZ(p); 181 | array[21] = inventoryItems.scaleX(p); 182 | array[22] = inventoryItems.scaleY(p); 183 | array[23] = inventoryItems.scaleZ(p); 184 | array[24] = inventoryItems.highlightTarget(); 185 | array[25] = inventoryItems.unlock(); 186 | 187 | array[9] = inventoryItems.leftRotationX(p); 188 | array[10] = inventoryItems.leftRotationY(p); 189 | array[11] = inventoryItems.leftRotationZ(p); 190 | array[12] = inventoryItems.rightRotationX(p); 191 | array[13] = inventoryItems.rightRotationY(p); 192 | array[14] = inventoryItems.rightRotationZ(p); 193 | array[15] = inventoryItems.centerPivot(); 194 | array[16] = inventoryItems.centerOnBlock(); 195 | 196 | return array; 197 | } 198 | 199 | 200 | } 201 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/Utilities.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor; 2 | 3 | import net.md_5.bungee.api.ChatMessageType; 4 | import net.md_5.bungee.api.chat.*; 5 | import net.md_5.bungee.api.chat.hover.content.Text; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.Color; 8 | import org.bukkit.Location; 9 | import org.bukkit.NamespacedKey; 10 | import org.bukkit.entity.*; 11 | import org.bukkit.inventory.ItemFlag; 12 | import org.bukkit.inventory.ItemStack; 13 | import org.bukkit.inventory.meta.ItemMeta; 14 | import org.bukkit.persistence.PersistentDataType; 15 | 16 | import goldenshadow.displayentityeditor.enums.LockSearchMode; 17 | 18 | import javax.annotation.Nullable; 19 | import java.util.List; 20 | 21 | public class Utilities { 22 | 23 | /** 24 | * Used to easily set an items meta 25 | * @param item The item 26 | * @param name The name it should get 27 | * @param lore The lore it should get 28 | * @param data The data it should get 29 | */ 30 | public static void setMeta(ItemStack item, String name, List lore, String data) { 31 | ItemMeta meta = item.getItemMeta(); 32 | assert meta != null; 33 | meta.setDisplayName(ChatColor.translateAlternateColorCodes('&' ,name)); 34 | lore.replaceAll(textToTranslate -> ChatColor.translateAlternateColorCodes('&', textToTranslate)); 35 | meta.setLore(lore); 36 | meta.getPersistentDataContainer().set(DisplayEntityEditor.toolKey, PersistentDataType.STRING, data); 37 | 38 | meta.addItemFlags(ItemFlag.values()); 39 | meta.setUnbreakable(true); 40 | item.setItemMeta(meta); 41 | } 42 | 43 | /** 44 | * Used to easily set an items meta 45 | * @param item The item 46 | * @param name The name it should get 47 | * @param lore The lore it should get 48 | * @param data The data it should get 49 | * @param formatData Data that should be used to format a string 50 | */ 51 | public static void setMeta(ItemStack item, String name, List lore, String data, Object... formatData) { 52 | ItemMeta meta = item.getItemMeta(); 53 | assert meta != null; 54 | meta.setDisplayName(ChatColor.translateAlternateColorCodes('&' ,name)); 55 | lore.replaceAll(textToTranslate -> ChatColor.translateAlternateColorCodes('&', textToTranslate).formatted(formatData)); 56 | meta.setLore(lore); 57 | meta.getPersistentDataContainer().set(DisplayEntityEditor.toolKey, PersistentDataType.STRING, data); 58 | 59 | meta.addItemFlags(ItemFlag.values()); 60 | meta.setUnbreakable(true); 61 | item.setItemMeta(meta); 62 | } 63 | 64 | /** 65 | * Used to check if an item has a specific NamespacedKey 66 | * @param item The item 67 | * @return True if it does, otherwise false 68 | */ 69 | public static boolean hasDataKey(ItemStack item) { 70 | if (item.getItemMeta() != null) { 71 | return item.getItemMeta().getPersistentDataContainer().has(DisplayEntityEditor.toolKey, PersistentDataType.STRING); 72 | } 73 | return false; 74 | } 75 | 76 | /** 77 | * Used to get the specific tools type 78 | * @param item The item 79 | * @return The tool type 80 | */ 81 | public static String getToolValue(ItemStack item) { 82 | if (item.getItemMeta() != null) { 83 | return item.getItemMeta().getPersistentDataContainer().get(DisplayEntityEditor.toolKey, PersistentDataType.STRING); 84 | } 85 | return null; 86 | } 87 | 88 | /** 89 | * Used to add a new namespacedKey to an entity 90 | * @param entity The entity 91 | * @param dataKey The key 92 | * @param dataValue The value 93 | * @implNote Yes, I am aware that PersistentDataType.BOOLEAN exists, but I was getting NoSuchField exceptions, so I chose the path of least resistance 94 | */ 95 | public static void setData(Display entity, String dataKey, boolean dataValue) { 96 | entity.getPersistentDataContainer().set(new NamespacedKey(DisplayEntityEditor.getPlugin(), dataKey), PersistentDataType.STRING, Boolean.toString(dataValue)); 97 | } 98 | 99 | /** 100 | * Used to get data stored in an entity 101 | * @param entity The entity 102 | * @param dataKey The key 103 | * @implNote Yes, I am aware that PersistentDataType.BOOLEAN exists, but I was getting NoSuchField exceptions, so I chose the path of least resistance 104 | */ 105 | public static boolean getData(Display entity, String dataKey) { 106 | String b = entity.getPersistentDataContainer().get(new NamespacedKey(DisplayEntityEditor.getPlugin(), dataKey), PersistentDataType.STRING); 107 | return b == null || b.equals("true"); 108 | } 109 | 110 | /** 111 | * Used to get a string representation of an RGB color 112 | * @param color The color 113 | * @return The string representation 114 | */ 115 | public static String getColor(Color color) { 116 | if (color == null) return DisplayEntityEditor.messageManager.getString("none"); 117 | return DisplayEntityEditor.messageManager.getString("rgb").formatted(color.getRed(), color.getBlue(), color.getGreen()); 118 | } 119 | 120 | /** 121 | * Used to format an info message for chat 122 | * @param message The raw message 123 | * @return The formatted message 124 | */ 125 | public static String getInfoMessageFormat(String message) { 126 | return ChatColor.translateAlternateColorCodes('&', DisplayEntityEditor.messageManager.getString("info_message_format").formatted(message)); 127 | } 128 | 129 | /** 130 | * Used to format an error message for chat 131 | * @param message The raw message 132 | * @return The formatted message 133 | */ 134 | public static String getErrorMessageFormat(String message) { 135 | return ChatColor.translateAlternateColorCodes('&', DisplayEntityEditor.messageManager.getString("error_message_format").formatted(message)); 136 | } 137 | 138 | /** 139 | * Used to get the nearest display entity 140 | * @param location The location from where the nearest display entity should be gotten 141 | * @param lockSearchToggle If this method should look for locked or unlocked entities. If true, it will only look for unlocked entities, and if false it will only look for locked ones 142 | * @return The nearest display entity or null if none were found 143 | */ 144 | @Nullable 145 | public static Display getNearestDisplayEntity(Location location, boolean lockSearchToggle) { 146 | Display entity = null; 147 | double distance = 5; 148 | assert location.getWorld() != null; 149 | for (Entity e : location.getWorld().getNearbyEntities(location, 5,5,5)) { 150 | if (e instanceof Display d) { 151 | if (lockSearchToggle) { 152 | if (!d.getScoreboardTags().contains("dee:locked")) { 153 | double dis = d.getLocation().distance(location); 154 | if (dis < distance) { 155 | entity = d; 156 | distance = dis; 157 | } 158 | } 159 | } else { 160 | if (d.getScoreboardTags().contains("dee:locked")) { 161 | double dis = d.getLocation().distance(location); 162 | if (dis < distance) { 163 | entity = d; 164 | distance = dis; 165 | } 166 | } 167 | } 168 | } 169 | } 170 | return entity; 171 | } 172 | 173 | public static BaseComponent[] getCommandMessage(String commandMessage, String hint) { 174 | TextComponent click = new TextComponent(net.md_5.bungee.api.ChatColor.translateAlternateColorCodes('&', DisplayEntityEditor.messageManager.getString("command_message").formatted(commandMessage, hint))); 175 | click.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/deeditor edit " + commandMessage)); 176 | 177 | return new ComponentBuilder(click).create(); 178 | } 179 | 180 | public static void sendActionbarMessage(Player p, String message) { 181 | p.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(net.md_5.bungee.api.ChatColor.DARK_AQUA + message)); 182 | } 183 | 184 | public static BaseComponent[] getClipboardMessage(String messageKey, String clipboardContent) { 185 | TextComponent text = new TextComponent(net.md_5.bungee.api.ChatColor.translateAlternateColorCodes('&', DisplayEntityEditor.messageManager.getString(messageKey))); 186 | 187 | text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(clipboardContent))); 188 | text.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, clipboardContent)); 189 | return new ComponentBuilder(text).create(); 190 | } 191 | 192 | public static String getObjectNameMessage(Object object) { 193 | if (object instanceof Boolean b) { 194 | return DisplayEntityEditor.messageManager.getList("boolean").get(b ? 0 : 1); 195 | } 196 | else if (object instanceof Display.Billboard b) { 197 | return DisplayEntityEditor.messageManager.getList("billboard").get(b.ordinal()); 198 | } 199 | else if (object instanceof TextDisplay.TextAlignment t) { 200 | return DisplayEntityEditor.messageManager.getList("text_alignment").get(t.ordinal()); 201 | } 202 | else if (object instanceof ItemDisplay.ItemDisplayTransform t) { 203 | return DisplayEntityEditor.messageManager.getList("item_display_transform").get(t.ordinal()); 204 | } 205 | else if (object instanceof LockSearchMode m) { 206 | return DisplayEntityEditor.messageManager.getList("lock_search_mode").get(m.ordinal()); 207 | } 208 | else if (object instanceof SelectionMode m) { 209 | return DisplayEntityEditor.messageManager.getList("selection_mode").get(m.index()); 210 | } 211 | else return ""; 212 | } 213 | 214 | public static SelectionMode getToolSelectMode(Player p) { 215 | return SelectionMode.get(p.getPersistentDataContainer().getOrDefault(DisplayEntityEditor.toolSelectionModeKey, PersistentDataType.STRING, "nearby")); 216 | } 217 | 218 | public static LockSearchMode getToolSearchMode(Player p) { 219 | return LockSearchMode.valueOf(p.getPersistentDataContainer().getOrDefault(DisplayEntityEditor.toolSelectionSearchModeKey, PersistentDataType.STRING, "UNLOCKED")); 220 | } 221 | 222 | public static boolean getToolSelectMultiple(Player p) { 223 | return p.getPersistentDataContainer().getOrDefault(DisplayEntityEditor.toolSelectionMultipleKey, PersistentDataType.BOOLEAN, false); 224 | } 225 | 226 | public static float getToolSelectRange(Player p) { 227 | return p.getPersistentDataContainer().getOrDefault(DisplayEntityEditor.toolSelectionRangeKey, PersistentDataType.DOUBLE, 5d).floatValue(); 228 | } 229 | 230 | public static float getToolPrecision(Player p) { 231 | Double i = p.getPersistentDataContainer().get(DisplayEntityEditor.toolPrecisionKey, PersistentDataType.DOUBLE); 232 | return i != null ? i.floatValue() : 1; 233 | } 234 | 235 | public static String reduceFloatLength(String s) { 236 | return s.substring(0, Math.min(s.length(), 4)); 237 | } 238 | 239 | } 240 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/commands/Command.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.commands; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import goldenshadow.displayentityeditor.conversation.InputData; 6 | import goldenshadow.displayentityeditor.conversation.InputManager; 7 | import goldenshadow.displayentityeditor.enums.InputType; 8 | import org.bukkit.ChatColor; 9 | import org.bukkit.command.CommandExecutor; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.entity.BlockDisplay; 12 | import org.bukkit.entity.Display; 13 | import org.bukkit.entity.Player; 14 | import org.bukkit.entity.TextDisplay; 15 | import org.bukkit.inventory.ItemStack; 16 | import org.bukkit.persistence.PersistentDataType; 17 | import org.jetbrains.annotations.NotNull; 18 | 19 | import java.io.IOException; 20 | import java.util.HashMap; 21 | import java.util.UUID; 22 | 23 | 24 | public class Command implements CommandExecutor { 25 | 26 | 27 | private static final HashMap savedInventories = new HashMap<>(); 28 | 29 | /** 30 | * Used for when the deeditor command is issued 31 | * @param sender The sender 32 | * @param command The command 33 | * @param label The commands label 34 | * @param args The commands arguments 35 | * @return True if the command was correctly handled, false otherwise 36 | */ 37 | @Override 38 | public boolean onCommand(@NotNull CommandSender sender,@NotNull org.bukkit.command.Command command,@NotNull String label, String[] args) { 39 | if (sender instanceof Player p) { 40 | if (args.length == 0) { 41 | if (savedInventories.containsKey(p.getUniqueId())) { 42 | returnInventory(p); 43 | p.sendMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("inventory_returned"))); 44 | return true; 45 | } 46 | saveInventory(p); 47 | ItemStack[] array = DisplayEntityEditor.inventoryFactory.getInventoryArray(p); 48 | for (int i = 0; i < array.length; i++) { 49 | p.getInventory().setItem(i, array[i]); 50 | } 51 | if (!p.getPersistentDataContainer().has(DisplayEntityEditor.toolPrecisionKey, PersistentDataType.DOUBLE)) { 52 | p.getPersistentDataContainer().set(DisplayEntityEditor.toolPrecisionKey, PersistentDataType.DOUBLE, 1d); 53 | } 54 | p.sendMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("tools_received_1"))); 55 | p.sendMessage(ChatColor.translateAlternateColorCodes('&', DisplayEntityEditor.messageManager.getString("tools_received_2"))); 56 | return true; 57 | } 58 | if (args.length == 1) { 59 | if (args[0].equalsIgnoreCase("reload")) { 60 | DisplayEntityEditor.getPlugin().reloadConfig(); 61 | DisplayEntityEditor.alternateTextInput = DisplayEntityEditor.getPlugin().getConfig().getBoolean("alternate-text-input"); 62 | DisplayEntityEditor.useMiniMessageFormat = DisplayEntityEditor.getPlugin().getConfig().getBoolean("use-minimessage-format"); 63 | try { 64 | DisplayEntityEditor.checkForMessageFile(); 65 | } catch (IOException e) { 66 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("messages_reload_fail"))); 67 | } 68 | p.sendMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("config_reload"))); 69 | return true; 70 | } 71 | } 72 | 73 | if (args.length > 2) { 74 | if (DisplayEntityEditor.alternateTextInput) { 75 | if (args[0].equalsIgnoreCase("edit")) { 76 | String input = collectArgsToString(args); 77 | Display display = Utilities.getNearestDisplayEntity(p.getLocation(), true); 78 | if (display == null) { 79 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 80 | return true; 81 | } 82 | if (args[1].equalsIgnoreCase("name")) { 83 | InputManager.successfulTextInput(new InputData(display, InputType.NAME, null), input, p); 84 | return true; 85 | } 86 | if (args[1].equalsIgnoreCase("background_color")) { 87 | if (display instanceof TextDisplay) { 88 | InputManager.successfulTextInput(new InputData(display, InputType.BACKGROUND_COLOR, null), input, p); 89 | return true; 90 | } 91 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 92 | return true; 93 | } 94 | if (args[1].equalsIgnoreCase("text")) { 95 | if (display instanceof TextDisplay) { 96 | InputManager.successfulTextInput(new InputData(display, InputType.TEXT, null), input, p); 97 | return true; 98 | } 99 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 100 | return true; 101 | } 102 | if (args[1].equalsIgnoreCase("text_append")) { 103 | if (display instanceof TextDisplay) { 104 | InputManager.successfulTextInput(new InputData(display, InputType.TEXT_APPEND, null), input, p); 105 | return true; 106 | } 107 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 108 | return true; 109 | } 110 | if (args[1].equalsIgnoreCase("glow_color")) { 111 | if (!(display instanceof TextDisplay)) { 112 | InputManager.successfulTextInput(new InputData(display, InputType.GLOW_COLOR, null), input, p); 113 | return true; 114 | } 115 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 116 | return true; 117 | } 118 | if (args[1].equalsIgnoreCase("block_state")) { 119 | if (display instanceof BlockDisplay) { 120 | InputManager.successfulTextInput(new InputData(display, InputType.BLOCK_STATE, ((BlockDisplay) display).getBlock().getMaterial()), input, p); 121 | return true; 122 | } 123 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 124 | return true; 125 | } 126 | if (args[1].equalsIgnoreCase("view_range")) { 127 | if (InputManager.isFloat(input)) { 128 | InputManager.successfulFloatInput(new InputData(display, InputType.VIEW_RANGE, null), Float.parseFloat(input), p); 129 | return true; 130 | } 131 | } 132 | if (args[1].equalsIgnoreCase("display_height")) { 133 | if (InputManager.isFloat(input)) { 134 | InputManager.successfulFloatInput(new InputData(display, InputType.DISPLAY_HEIGHT, null), Float.parseFloat(input), p); 135 | return true; 136 | } 137 | } 138 | if (args[1].equalsIgnoreCase("display_width")) { 139 | if (InputManager.isFloat(input)) { 140 | InputManager.successfulFloatInput(new InputData(display, InputType.DISPLAY_WIDTH, null), Float.parseFloat(input), p); 141 | return true; 142 | } 143 | } 144 | if (args[1].equalsIgnoreCase("shadow_radius")) { 145 | if (InputManager.isFloat(input)) { 146 | InputManager.successfulFloatInput(new InputData(display, InputType.SHADOW_RADIUS, null), Float.parseFloat(input), p); 147 | return true; 148 | } 149 | } 150 | if (args[1].equalsIgnoreCase("shadow_strength")) { 151 | if (InputManager.isFloat(input)) { 152 | float f = Float.parseFloat(input); 153 | if (0 <= f && f <= 1) { 154 | InputManager.successfulFloatInput(new InputData(display, InputType.SHADOW_STRENGTH, null), Float.parseFloat(input), p); 155 | return true; 156 | } 157 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("shadow_strength_fail"))); 158 | return true; 159 | } 160 | } 161 | if (args[1].equalsIgnoreCase("text_opacity")) { 162 | if (display instanceof TextDisplay) { 163 | if (InputManager.isByte(input)) { 164 | InputManager.successfulByteInput(new InputData(display, InputType.TEXT_OPACITY, null), Integer.parseInt(input), p); 165 | return true; 166 | } 167 | } 168 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 169 | return true; 170 | } 171 | if (args[1].equalsIgnoreCase("background_opacity")) { 172 | if (display instanceof TextDisplay) { 173 | if (InputManager.isByte(input)) { 174 | InputManager.successfulByteInput(new InputData(display, InputType.BACKGROUND_OPACITY, null), Integer.parseInt(input), p); 175 | return true; 176 | } 177 | } 178 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 179 | return true; 180 | } 181 | if (args[1].equalsIgnoreCase("line_width")) { 182 | if (display instanceof TextDisplay) { 183 | if (InputManager.isInteger(input)) { 184 | InputManager.successfulIntegerInput(new InputData(display, InputType.LINE_WIDTH, null), Integer.parseInt(input), p); 185 | return true; 186 | } 187 | } 188 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_fail"))); 189 | return true; 190 | } 191 | } 192 | } 193 | return true; 194 | } 195 | p.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_command_fail"))); 196 | return true; 197 | } 198 | sender.sendMessage(DisplayEntityEditor.messageManager.getString("none_player_fail")); 199 | return true; 200 | } 201 | 202 | /** 203 | * A utility method used to save a players inventory in order to be able to return it later 204 | * @param player The player whose inventory should be saved 205 | */ 206 | private static void saveInventory( Player player) { 207 | savedInventories.put(player.getUniqueId(), player.getInventory().getContents().clone()); 208 | player.getInventory().clear(); 209 | } 210 | 211 | /** 212 | * A utility method used to return a players inventory 213 | * @param player The player whose inventory should be returned 214 | */ 215 | public static void returnInventory(Player player) { 216 | if (!savedInventories.containsKey(player.getUniqueId())) return; 217 | player.getInventory().clear(); 218 | ItemStack[] saved = savedInventories.get(player.getUniqueId()); 219 | for (int i = 0; i < player.getInventory().getSize(); i++) { 220 | player.getInventory().setItem(i, saved[i]); 221 | } 222 | savedInventories.remove(player.getUniqueId()); 223 | } 224 | 225 | private static String collectArgsToString(String[] args) { 226 | StringBuilder s = new StringBuilder(); 227 | for (int i = 2; i < args.length; i++) { 228 | if (i != 2) s.append(" "); 229 | s.append(args[i]); 230 | } 231 | return s.toString(); 232 | } 233 | 234 | } 235 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/conversation/InputManager.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.conversation; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import goldenshadow.displayentityeditor.enums.InputType; 6 | import net.kyori.adventure.text.Component; 7 | import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; 8 | import net.md_5.bungee.api.chat.BaseComponent; 9 | import net.md_5.bungee.api.chat.TextComponent; 10 | import org.bukkit.Bukkit; 11 | import org.bukkit.ChatColor; 12 | import org.bukkit.Color; 13 | import org.bukkit.block.data.BlockData; 14 | import org.bukkit.conversations.Conversation; 15 | import org.bukkit.entity.BlockDisplay; 16 | import org.bukkit.entity.Player; 17 | import org.bukkit.entity.TextDisplay; 18 | 19 | /** 20 | * A manager class for handling text inputs 21 | */ 22 | public class InputManager { 23 | 24 | 25 | /** 26 | * Used to create a text input that awaits a string 27 | * @param player The player whose input is awaited 28 | * @param message The message sent to the player 29 | * @param data The data about the input 30 | */ 31 | public static void createTextInput(Player player, String message, InputData data) { 32 | message = Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("generic_prompt").formatted(message, DisplayEntityEditor.messageManager.getString("prompt_escape_word"))); 33 | Conversation c = DisplayEntityEditor.conversationFactory.withFirstPrompt(new TextPrompt(message)).thatExcludesNonPlayersWithMessage("This must be done by a player!").withLocalEcho(false).withEscapeSequence(DisplayEntityEditor.messageManager.getString("prompt_escape_word")).buildConversation(player); 34 | c.getContext().setSessionData("data", data); 35 | c.begin(); 36 | } 37 | 38 | /** 39 | * Used to create a text input that awaits an integer 40 | * @param player The player whose input is awaited 41 | * @param message The message sent to the player 42 | * @param data The data about the input 43 | */ 44 | public static void createIntegerInput(Player player, String message, InputData data) { 45 | message = Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("generic_prompt").formatted(message, DisplayEntityEditor.messageManager.getString("prompt_escape_word"))); 46 | Conversation c = DisplayEntityEditor.conversationFactory.withFirstPrompt(new IntegerPrompt(message)).thatExcludesNonPlayersWithMessage("This must be done by a player!").withLocalEcho(false).withEscapeSequence(DisplayEntityEditor.messageManager.getString("prompt_escape_word")).buildConversation(player); 47 | c.getContext().setSessionData("data", data); 48 | c.begin(); 49 | } 50 | 51 | /** 52 | * Used to create a text input that awaits a float 53 | * @param player The player whose input is awaited 54 | * @param message The message sent to the player 55 | * @param data The data about the input 56 | */ 57 | public static void createFloatInput(Player player, String message, InputData data) { 58 | message = Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("generic_prompt").formatted(message, DisplayEntityEditor.messageManager.getString("prompt_escape_word"))); 59 | Conversation c = DisplayEntityEditor.conversationFactory.withFirstPrompt(new FloatPrompt(message)).thatExcludesNonPlayersWithMessage("This must be done by a player!").withLocalEcho(false).withEscapeSequence(DisplayEntityEditor.messageManager.getString("prompt_escape_word")).buildConversation(player); 60 | c.getContext().setSessionData("data", data); 61 | c.begin(); 62 | } 63 | 64 | /** 65 | * Used to create a text input that awaits a byte 66 | * @param player The player whose input is awaited 67 | * @param message The message sent to the player 68 | * @param data The data about the input 69 | */ 70 | public static void createByteInput(Player player, String message, InputData data) { 71 | message = Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("generic_prompt").formatted(message, DisplayEntityEditor.messageManager.getString("prompt_escape_word"))); 72 | Conversation c = DisplayEntityEditor.conversationFactory.withFirstPrompt(new BytePrompt(message)).thatExcludesNonPlayersWithMessage("This must be done by a player!").withLocalEcho(false).withEscapeSequence(DisplayEntityEditor.messageManager.getString("prompt_escape_word")).buildConversation(player); 73 | c.getContext().setSessionData("data", data); 74 | c.begin(); 75 | } 76 | 77 | 78 | public static boolean isInteger(String s) { 79 | try { 80 | Integer.parseInt(s); 81 | return true; 82 | } catch (NumberFormatException e) { 83 | return false; 84 | } 85 | } 86 | 87 | public static boolean isFloat(String s) { 88 | try { 89 | Float.parseFloat(s); 90 | return true; 91 | } catch (NumberFormatException e) { 92 | return false; 93 | } 94 | } 95 | 96 | public static boolean isByte(String s) { 97 | if (isInteger(s)) { 98 | int i = Integer.parseInt(s); 99 | return 0 <= i && i <= 255; 100 | } 101 | return false; 102 | } 103 | 104 | public static void successfulIntegerInput(InputData inputData, int i, Player player) { 105 | if (inputData.inputType() == InputType.LINE_WIDTH) { 106 | ((TextDisplay) inputData.entity()).setLineWidth(i); 107 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("line_width_success"))); 108 | } 109 | } 110 | 111 | @SuppressWarnings("deprecation") 112 | public static void successfulByteInput(InputData inputData, int integer, Player player) { 113 | switch (inputData.inputType()) { 114 | case TEXT_OPACITY -> { 115 | byte b = (byte) integer; 116 | ((TextDisplay) inputData.entity()).setTextOpacity(b); 117 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("opacity_success"))); 118 | } 119 | case BACKGROUND_OPACITY -> { 120 | 121 | TextDisplay t = (TextDisplay) inputData.entity(); 122 | if (t.getBackgroundColor() != null) { 123 | t.setBackgroundColor(Color.fromARGB(integer, t.getBackgroundColor().getRed(), t.getBackgroundColor().getGreen(), t.getBackgroundColor().getBlue())); 124 | } else { 125 | t.setBackgroundColor(Color.fromARGB(integer,0,0,0)); 126 | } 127 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("opacity_success"))); 128 | } 129 | } 130 | } 131 | 132 | public static void successfulFloatInput(InputData inputData, float f, Player player) { 133 | switch (inputData.inputType()) { 134 | case VIEW_RANGE -> { 135 | inputData.entity().setViewRange(f); 136 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("view_range_success"))); 137 | } 138 | case DISPLAY_WIDTH -> { 139 | inputData.entity().setDisplayWidth(f); 140 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("display_width_success"))); 141 | } 142 | case DISPLAY_HEIGHT -> { 143 | inputData.entity().setDisplayHeight(f); 144 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("display_height_success"))); 145 | } 146 | case SHADOW_RADIUS -> { 147 | inputData.entity().setShadowRadius(f); 148 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("shadow_radius_success"))); 149 | } 150 | case SHADOW_STRENGTH -> { 151 | if (0 <= f && f <= 1) { 152 | inputData.entity().setShadowStrength(f); 153 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("shadow_strength_success"))); 154 | } else { 155 | player.sendRawMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("shadow_strength_fail"))); 156 | } 157 | } 158 | } 159 | } 160 | 161 | @SuppressWarnings("deprecation") 162 | public static void successfulTextInput(InputData inputData, String s ,Player player) { 163 | switch (inputData.inputType()) { 164 | case NAME -> { 165 | 166 | inputData.entity().setCustomNameVisible(true); 167 | 168 | if (DisplayEntityEditor.useMiniMessageFormat) { 169 | Component c = DisplayEntityEditor.miniMessage.deserialize(s); 170 | BaseComponent[] b = BungeeComponentSerializer.get().serialize(c); 171 | inputData.entity().setCustomName(TextComponent.toLegacyText(b)); 172 | } else { 173 | inputData.entity().setCustomName(ChatColor.translateAlternateColorCodes('&', s)); 174 | } 175 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("name_success"))); 176 | } 177 | case TEXT -> { 178 | String message = s; 179 | 180 | if (DisplayEntityEditor.useMiniMessageFormat) { 181 | Component c = DisplayEntityEditor.miniMessage.deserialize(s); 182 | BaseComponent[] b = BungeeComponentSerializer.get().serialize(c); 183 | ((TextDisplay) inputData.entity()).setText(TextComponent.toLegacyText(b)); 184 | } else { 185 | message = message.replace("\\n", "\n"); 186 | ((TextDisplay) inputData.entity()).setText(ChatColor.translateAlternateColorCodes('&', message)); 187 | } 188 | 189 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("text_success"))); 190 | } 191 | case TEXT_APPEND -> { 192 | String message = s; 193 | if (DisplayEntityEditor.useMiniMessageFormat) { 194 | Component c = DisplayEntityEditor.miniMessage.deserialize(s); 195 | BaseComponent[] b = BungeeComponentSerializer.get().serialize(c); 196 | ((TextDisplay) inputData.entity()).setText(((TextDisplay) inputData.entity()).getText() + TextComponent.toLegacyText(b)); 197 | } else { 198 | message = message.replace("\\n", "\n"); 199 | ((TextDisplay) inputData.entity()).setText(ChatColor.translateAlternateColorCodes('&', ((TextDisplay) inputData.entity()).getText() + message)); 200 | } 201 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("text_append_success"))); 202 | } 203 | case BACKGROUND_COLOR -> { 204 | int[] array = parseStringToRGB(s); 205 | if (array != null) { 206 | TextDisplay t = (TextDisplay) inputData.entity(); 207 | if (t.getBackgroundColor() != null) { 208 | t.setBackgroundColor(Color.fromARGB(t.getBackgroundColor().getAlpha(), array[0], array[1], array[2])); 209 | } else { 210 | t.setBackgroundColor(Color.fromARGB(255,array[0],array[1],array[2])); 211 | } 212 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("background_color_success"))); 213 | } else { 214 | player.sendRawMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_color_fail"))); 215 | } 216 | } 217 | case GLOW_COLOR -> { 218 | int[] array = parseStringToRGB(s); 219 | if (array != null) { 220 | 221 | BlockData blockData; 222 | if (inputData.entity() instanceof BlockDisplay) blockData = ((BlockDisplay) inputData.entity()).getBlock(); 223 | else { 224 | blockData = null; 225 | } 226 | 227 | inputData.entity().setGlowColorOverride(Color.fromRGB(array[0], array[1], array[2])); 228 | 229 | if (inputData.entity() instanceof BlockDisplay) { 230 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> ((BlockDisplay) inputData.entity()).setBlock(blockData), 1L); 231 | } 232 | 233 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("glow_color_success"))); 234 | } else { 235 | player.sendRawMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("generic_color_fail"))); 236 | } 237 | } 238 | case BLOCK_STATE -> { 239 | if (inputData.blockMaterial() != null) { 240 | try { 241 | BlockData blockData = Bukkit.createBlockData(inputData.blockMaterial(), s); 242 | ((BlockDisplay) inputData.entity()).setBlock(blockData); 243 | player.sendRawMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("block_state_success"))); 244 | } catch (IllegalArgumentException e) { 245 | player.sendRawMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("block_state_fail"))); 246 | } 247 | } 248 | } 249 | } 250 | } 251 | 252 | /** 253 | * Used to parse a text input for an RBG value into an array of those values 254 | * @param input The text input 255 | * @return An array where index 0 is red, 1 is green and 2 is blue 256 | */ 257 | private static int[] parseStringToRGB(String input) { 258 | String[] parts = input.split(","); 259 | if (parts.length != 3) { 260 | return null; 261 | } 262 | 263 | try { 264 | int[] values = new int[3]; 265 | for (int i = 0; i < 3; i++) { 266 | values[i] = Integer.parseInt(parts[i].trim()); 267 | } 268 | return values; 269 | } catch (NumberFormatException e) { 270 | return null; 271 | } 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/items/GUIItems.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.items; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.Color; 7 | import org.bukkit.Material; 8 | import org.bukkit.block.data.Levelled; 9 | import org.bukkit.entity.Display; 10 | import org.bukkit.entity.ItemDisplay; 11 | import org.bukkit.entity.TextDisplay; 12 | import org.bukkit.inventory.ItemStack; 13 | import org.bukkit.inventory.meta.BlockDataMeta; 14 | 15 | import java.util.ArrayList; 16 | 17 | /** 18 | * A utility class where all the gui items are created 19 | */ 20 | public class GUIItems { 21 | 22 | /** 23 | * Creates the rename gui item 24 | * @param name The current name 25 | * @return The item 26 | */ 27 | public ItemStack name(String name) { 28 | if (name == null) name = DisplayEntityEditor.messageManager.getString("none"); 29 | ItemStack itemStack = new ItemStack(Material.NAME_TAG); 30 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("name_name"), 31 | DisplayEntityEditor.messageManager.getList("name_lore"), 32 | "GUIName", 33 | name 34 | ); 35 | return itemStack; 36 | } 37 | 38 | /** 39 | * Creates the glowing gui item 40 | * @param current If the entity is currently glowing 41 | * @return The item 42 | */ 43 | public ItemStack glowing(boolean current) { 44 | ItemStack itemStack = new ItemStack(Material.SEA_LANTERN); 45 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("glowing_name"), 46 | DisplayEntityEditor.messageManager.getList("glowing_lore"), 47 | "GUIGlow", 48 | Utilities.getObjectNameMessage(current) 49 | ); 50 | return itemStack; 51 | } 52 | 53 | /** 54 | * Creates the glow color gui item 55 | * @param current The current glow color 56 | * @return The item 57 | */ 58 | public ItemStack glowColor(Color current) { 59 | ItemStack itemStack = new ItemStack(Material.RED_DYE); 60 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("glow_color_name"), 61 | DisplayEntityEditor.messageManager.getList("glow_color_lore"), 62 | "GUIGlowColor", 63 | Utilities.getColor(current) 64 | ); 65 | return itemStack; 66 | } 67 | 68 | /** 69 | * Creates the left rotation normalised gui item 70 | * @param current If left rotation is currently normalised 71 | * @return The item 72 | */ 73 | public ItemStack leftRotNormalize(boolean current) { 74 | ItemStack itemStack = new ItemStack(Material.COMPASS); 75 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("left_rotation_normalize_name"), 76 | DisplayEntityEditor.messageManager.getList("rotation_normalize_lore"), 77 | "GUILRNormalize", 78 | Utilities.getObjectNameMessage(current) 79 | ); 80 | return itemStack; 81 | } 82 | 83 | /** 84 | * Creates the right rotation normalised gui item 85 | * @param current If right rotation is currently normalised 86 | * @return The item 87 | */ 88 | public ItemStack rightRotNormalize(boolean current) { 89 | ItemStack itemStack = new ItemStack(Material.COMPASS); 90 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("right_rotation_normalize_name"), 91 | DisplayEntityEditor.messageManager.getList("rotation_normalize_lore"), 92 | "GUIRRNormalize", 93 | Boolean.toString(current) 94 | ); 95 | return itemStack; 96 | } 97 | 98 | /** 99 | * Creates the view range gui item 100 | * @param current The current view range 101 | * @return The item 102 | */ 103 | public ItemStack viewRange(float current) { 104 | ItemStack itemStack = new ItemStack(Material.SPYGLASS); 105 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("view_range_name"), 106 | DisplayEntityEditor.messageManager.getList("view_range_lore"), 107 | "GUIViewRange", 108 | Float.toString(current) 109 | ); 110 | return itemStack; 111 | } 112 | 113 | /** 114 | * Creates the display width gui item 115 | * @param current The current display width 116 | * @return The item 117 | */ 118 | public ItemStack width(float current) { 119 | ItemStack itemStack = new ItemStack(Material.ARROW); 120 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("width_name"), 121 | DisplayEntityEditor.messageManager.getList("width_lore"), 122 | "GUIWidth", 123 | Float.toString(current) 124 | ); 125 | return itemStack; 126 | } 127 | 128 | /** 129 | * Creates the display height gui item 130 | * @param current The current display height 131 | * @return The item 132 | */ 133 | public ItemStack height(float current) { 134 | ItemStack itemStack = new ItemStack(Material.ARROW); 135 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("height_name"), 136 | DisplayEntityEditor.messageManager.getList("height_lore"), 137 | "GUIHeight", 138 | Float.toString(current) 139 | ); 140 | return itemStack; 141 | } 142 | 143 | /** 144 | * Creates the billboard type gui item 145 | * @param current The current billboard type 146 | * @return The item 147 | */ 148 | public ItemStack billboard(Display.Billboard current) { 149 | ItemStack itemStack = new ItemStack(Material.PAINTING); 150 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("billboard_name"), 151 | DisplayEntityEditor.messageManager.getList("billboard_lore"), 152 | "GUIBillboard", 153 | Utilities.getObjectNameMessage(current) 154 | ); 155 | return itemStack; 156 | } 157 | 158 | /** 159 | * Creates the shadow radius gui item 160 | * @param current The current shadow radius 161 | * @return The item 162 | */ 163 | public ItemStack shadowRadius(float current) { 164 | ItemStack itemStack = new ItemStack(Material.COAL); 165 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("shadow_radius_name"), 166 | DisplayEntityEditor.messageManager.getList("shadow_radius_lore"), 167 | "GUIShadowRadius", 168 | Float.toString(current) 169 | ); 170 | return itemStack; 171 | } 172 | 173 | /** 174 | * Creates the shadow strength gui item 175 | * @param current The current shadow strength 176 | * @return The item 177 | */ 178 | public ItemStack shadowStrength(float current) { 179 | ItemStack itemStack = new ItemStack(Material.FLINT); 180 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("shadow_strength_name"), 181 | DisplayEntityEditor.messageManager.getList("shadow_strength_lore"), 182 | "GUIShadowStrength", 183 | Float.toString(current) 184 | ); 185 | return itemStack; 186 | } 187 | 188 | /** 189 | * Creates the lock gui item 190 | * @return The item 191 | */ 192 | public ItemStack lock() { 193 | ItemStack itemStack = new ItemStack(Material.STRUCTURE_VOID); 194 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("lock_name"), 195 | DisplayEntityEditor.messageManager.getList("lock_lore"), 196 | "GUILock" 197 | ); 198 | return itemStack; 199 | } 200 | 201 | /** 202 | * Creates the skylight gui item 203 | * @param current The current skylight 204 | * @return The item 205 | */ 206 | public ItemStack skyLight(int current) { 207 | ItemStack itemStack = new ItemStack(Material.LIGHT); 208 | setBrightnessLevel(itemStack, current == -1 ? 0 : current); 209 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("sky_light_name"), 210 | DisplayEntityEditor.messageManager.getList("light_lore"), 211 | "GUISkyLight", 212 | (current == -1 ? DisplayEntityEditor.messageManager.getString("default") : String.valueOf(current)) 213 | ); 214 | return itemStack; 215 | } 216 | 217 | /** 218 | * Creates the block light gui item 219 | * @param current The current block light 220 | * @return The item 221 | */ 222 | public ItemStack blockLight(int current) { 223 | ItemStack itemStack = new ItemStack(Material.LIGHT); 224 | setBrightnessLevel(itemStack, current == -1 ? 0 : current); 225 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("block_light_name"), 226 | DisplayEntityEditor.messageManager.getList("light_lore"), 227 | "GUIBlockLight", 228 | (current == -1 ? DisplayEntityEditor.messageManager.getString("default") : String.valueOf(current)) 229 | ); 230 | return itemStack; 231 | } 232 | 233 | /** 234 | * Creates the delete gui item 235 | * @return The item 236 | */ 237 | public ItemStack delete() { 238 | ItemStack itemStack = new ItemStack(Material.BARRIER); 239 | 240 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("delete_name"), 241 | DisplayEntityEditor.messageManager.getList("delete_lore"), 242 | "GUIDelete" 243 | ); 244 | return itemStack; 245 | } 246 | 247 | /** 248 | * Creates the filler gui item 249 | * @return The item 250 | */ 251 | public ItemStack filler() { 252 | ItemStack itemStack = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); 253 | Utilities.setMeta(itemStack, " ", new ArrayList<>(), "GUIFiller"); 254 | return itemStack; 255 | } 256 | 257 | /** 258 | * Creates the item transform gui item 259 | * @param current The current transform type 260 | * @return The item 261 | */ 262 | public ItemStack itemDisplayTransform(ItemDisplay.ItemDisplayTransform current) { 263 | ItemStack itemStack = new ItemStack(Material.ARMOR_STAND); 264 | 265 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("item_display_transform_name"), 266 | DisplayEntityEditor.messageManager.getList("item_display_transform_lore"), 267 | "GUIItemDisplayTransform", 268 | Utilities.getObjectNameMessage(current) 269 | ); 270 | return itemStack; 271 | } 272 | 273 | /** 274 | * Creates the text opacity gui item 275 | * @param current The current text opacity 276 | * @return The item 277 | */ 278 | public ItemStack textOpacity(int current) { 279 | ItemStack itemStack = new ItemStack(Material.DRAGON_BREATH); 280 | if (current < 0) current = 0; 281 | 282 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_opacity_name"), 283 | DisplayEntityEditor.messageManager.getList("text_opacity_lore"), 284 | "GUITextOpacity", 285 | current 286 | ); 287 | return itemStack; 288 | } 289 | 290 | /** 291 | * Creates the line width gui item 292 | * @param current The current line width 293 | * @return The item 294 | */ 295 | public ItemStack textLineWidth(int current) { 296 | ItemStack itemStack = new ItemStack(Material.REPEATER); 297 | 298 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_line_width_name"), 299 | DisplayEntityEditor.messageManager.getList("text_line_width_lore"), 300 | "GUITextLineWidth", 301 | current 302 | ); 303 | return itemStack; 304 | } 305 | 306 | /** 307 | * Creates the default background gui item 308 | * @param current If the background is currently set to default 309 | * @return The item 310 | */ 311 | public ItemStack textDefaultBackground(boolean current) { 312 | ItemStack itemStack = new ItemStack(Material.WHITE_STAINED_GLASS); 313 | 314 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_default_background_name"), 315 | DisplayEntityEditor.messageManager.getList("text_default_background_lore"), 316 | "GUITextDefaultBackground", 317 | Utilities.getObjectNameMessage(current) 318 | ); 319 | return itemStack; 320 | } 321 | 322 | /** 323 | * Creates the text see through gui item 324 | * @param current If the text is currently visible through blocks 325 | * @return The item 326 | */ 327 | public ItemStack textSeeThrough(boolean current) { 328 | ItemStack itemStack = new ItemStack(Material.LIGHT_BLUE_STAINED_GLASS); 329 | 330 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_see_through_name"), 331 | DisplayEntityEditor.messageManager.getList("text_see_through_lore"), 332 | "GUITextSeeThrough", 333 | Utilities.getObjectNameMessage(current) 334 | ); 335 | return itemStack; 336 | } 337 | 338 | /** 339 | * Creates the text shadow gui item 340 | * @param current If the text currently has shadows 341 | * @return The item 342 | */ 343 | public ItemStack textShadow(boolean current) { 344 | ItemStack itemStack = new ItemStack(Material.BLACK_STAINED_GLASS); 345 | 346 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_shadow_name"), 347 | DisplayEntityEditor.messageManager.getList("text_shadow_lore"), 348 | "GUITextShadow", 349 | Utilities.getObjectNameMessage(current) 350 | ); 351 | return itemStack; 352 | } 353 | 354 | /** 355 | * Creates the text background color gui item 356 | * @param current The current background color 357 | * @return The item 358 | */ 359 | public ItemStack textBackgroundColor(Color current) { 360 | ItemStack itemStack = new ItemStack(Material.RED_BANNER); 361 | 362 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_background_color_name"), 363 | DisplayEntityEditor.messageManager.getList("text_background_color_lore"), 364 | "GUITextBackgroundColor", 365 | Utilities.getColor(current) 366 | ); 367 | return itemStack; 368 | } 369 | 370 | /** 371 | * Creates the text background opacity gui item 372 | * @param current The current background color 373 | * @return The item 374 | */ 375 | public ItemStack textBackgroundOpacity(Color current) { 376 | ItemStack itemStack = new ItemStack(Material.END_CRYSTAL); 377 | 378 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_background_opacity_name"), 379 | DisplayEntityEditor.messageManager.getList("text_background_opacity_lore"), 380 | "GUITextBackgroundOpacity", 381 | current.getAlpha() 382 | ); 383 | return itemStack; 384 | } 385 | 386 | /** 387 | * Creates the text alignment gui item 388 | * @param current The current text alignment 389 | * @return The item 390 | */ 391 | public ItemStack textAlignment(TextDisplay.TextAlignment current) { 392 | ItemStack itemStack = new ItemStack(Material.FILLED_MAP); 393 | 394 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_alignment_name"), 395 | DisplayEntityEditor.messageManager.getList("text_alignment_lore"), 396 | "GUITextAlignment", 397 | Utilities.getObjectNameMessage(current) 398 | ); 399 | return itemStack; 400 | } 401 | 402 | /** 403 | * Creates the text gui item 404 | * @return The item 405 | * @implNote This item will not show the current text, as it could be very long and therefore be unreadable when displayed as item lore. If the user wants to see what text is currently being displayed, they should just close the gui for a second and read what's in front of them 406 | */ 407 | public ItemStack text() { 408 | ItemStack itemStack = new ItemStack(Material.OAK_SIGN); 409 | 410 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("text_name"), 411 | DisplayEntityEditor.messageManager.getList("text_lore"), 412 | "GUIText" 413 | ); 414 | return itemStack; 415 | } 416 | 417 | /** 418 | * Creates the block state gui item 419 | * @param current The current block state. If there is no data, it will be displayed as '[]' 420 | * @return The item 421 | */ 422 | public ItemStack blockState(String current) { 423 | ItemStack itemStack = new ItemStack(Material.CHEST_MINECART); 424 | 425 | String currentState = current.contains("[") ? current.substring(current.indexOf('['), current.indexOf(']') + 1) : "[]"; 426 | 427 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("block_state_name"), 428 | DisplayEntityEditor.messageManager.getList("block_state_lore"), 429 | "GUIBlockState", 430 | currentState 431 | ); 432 | return itemStack; 433 | } 434 | 435 | /** 436 | * A utility method used to set the brightness level of a light item 437 | * @param current The brightness level it should be set to 438 | */ 439 | private void setBrightnessLevel(ItemStack itemStack, int current) { 440 | BlockDataMeta meta = (BlockDataMeta) itemStack.getItemMeta(); 441 | assert meta != null; 442 | Levelled level = (Levelled) Bukkit.createBlockData(Material.LIGHT); 443 | level.setLevel(current); 444 | meta.setBlockData(level); 445 | itemStack.setItemMeta(meta); 446 | } 447 | 448 | 449 | } 450 | -------------------------------------------------------------------------------- /src/main/resources/messages.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Display Entity Editor Message Config 3 | # 4 | # File generated by: v${project.version} 5 | # (If this is not the version you are running, consider deleting this config 6 | # to allow a more up-to-date version to be generated) 7 | # 8 | # IMPORTANT: Do not delete '%s', '%d' or '%f'! Those are placeholders for variables! 9 | # 10 | # File version; Do not change this unless you know what you are doing! 11 | file_version: "${project.version}" 12 | # General Messages 13 | version_check_success: "You are on the latest version!" 14 | version_check_fail: "You are not running the latest version! Update your plugin here: https://www.spigotmc.org/resources/display-entity-editor.110267/" 15 | version_check_error: "Unable to check for updates: %s" 16 | version_check_disable_hint: "If you would like to disable these messages, you can do so in the config file." 17 | info_message_format: "&3[DEE] &b%s" 18 | error_message_format: "&4[DEE] &c%s" 19 | command_message: "&3[DEE] &bRun command &7\"/deeditor %s\"&b to edit the entity or click this message. %s" 20 | messages_file_outdated_version: "Your messages.yml file is using an outdated version! Consider deleting it and generating a new one." 21 | messages_file_incomplete: "Your messages.yml file is incomplete! Consider deleting it and generating a new one." 22 | 23 | 24 | # Inventory Items 25 | open_gui_name: "&eOpen GUI" 26 | open_gui_lore: ["&7Click to open the GUI of the", "&7nearest unlocked display entity", " ", "&e&lRIGHT-CLICK&r&e to open"] 27 | rotate_yaw_name: "&eRotate Horizontally (yaw)" 28 | rotate_pitch_name: "&eRotate Vertically (pitch)" 29 | rotate_lore: ["&7Click to rotate the nearest", "&7unlocked display entity", " ", "&e&lRIGHT-CLICK&r&e to rotate by +%s", "&e&lSHIFT RIGHT-CLICK &r&eto rotate by -%s", "&e&lOFFHAND &r&eto reset value"] 30 | move_x_name: "&eMove X (Teleport)" 31 | move_y_name: "&eMove Y (Teleport)" 32 | move_z_name: "&eMove Z (Teleport)" 33 | move_lore: ["&7Click to move the nearest", "&7unlocked display entity", " ", "&e&lRIGHT-CLICK&r&e to move +%s", "&e&lSHIFT RIGHT-CLICK&r&e to move -%s"] 34 | spawn_item_display_name: "&eSpawn item_display" 35 | spawn_item_display_lore: ["&7Click to spawn a new item display", "&7entity at your position", " ", "&e&lRIGHT-CLICK&r&e to spawn"] 36 | spawn_block_display_name: "&eSpawn block_display" 37 | spawn_block_display_lore: ["&7Click to spawn a new block display", "&7entity at your position", " ", "&e&lRIGHT-CLICK&r&e to spawn"] 38 | spawn_text_display_name: "&eSpawn text_display" 39 | spawn_text_display_lore: ["&7Click to spawn a new text display", "&7entity at your position", " ", "&e&lRIGHT-CLICK&r&e to spawn"] 40 | unlock_name: "&eUnlock Nearest Display Entity" 41 | unlock_lore: ["&7Click to unlock the nearest locked", "&7display entity, making it editable again", " ", "&e&lRIGHT-CLICK&r&e to unlock"] 42 | highlight_target_name: "&eHighlight Target" 43 | highlight_target_lore: ["&7Click to highlight the display entity", "&7that will be targeted by your tools", " ", "&e&lRIGHT-CLICK&r&e to highlight"] 44 | left_rotation_x_name: "&eLeft Rotation X" 45 | left_rotation_y_name: "&eLeft Rotation Y" 46 | left_rotation_z_name: "&eLeft Rotation Z" 47 | left_rotation_lore: ["&7Click to change the left rotation", "&7of the nearest unlocked display entity", " ", "&e&lRIGHT-CLICK&r&e to change by +%s", "&e&lSHIFT RIGHT-CLICK&r&e to change by -%s", "&e&lOFFHAND &r&eto reset value"] 48 | right_rotation_x_name: "&eRight Rotation X" 49 | right_rotation_y_name: "&eRight Rotation Y" 50 | right_rotation_z_name: "&eRight Rotation Z" 51 | right_rotation_lore: ["&7Click to change the right rotation", "&7of the nearest unlocked display entity", " ", "&e&lRIGHT-CLICK&r&e to change by +%s", "&e&lSHIFT RIGHT-CLICK&r&e to change by -%s", "&e&lOFFHAND &r&eto reset value"] 52 | center_pivot_name: "&eCenter Pivot Point" 53 | center_pivot_lore: ["&7Click to auto adjust the translation so that", "&7the pivot is centered relative to the scale.", "&7This will make it easier to rotate the entity", "&7around itself", " ", "&e&lRIGHT-CLICK&r&e to center"] 54 | translation_x_name: "&eTranslation X" 55 | translation_y_name: "&eTranslation Y" 56 | translation_z_name: "&eTranslation Z" 57 | translation_lore: ["&7Click to change the translation of", "&7the nearest unlocked display entity.", "&7Changing the translation will move the", "&7visual part of the entity but not its", "&7hitbox or pivot point", " ", "&e&lRIGHT-CLICK&r&e to change by +%s", "&e&lSHIFT RIGHT-CLICK&r&e to change by -%s", "&e&lOFFHAND &r&eto reset value"] 58 | scale_x_name: "&eScale X" 59 | scale_y_name: "&eScale Y" 60 | scale_z_name: "&eScale Z" 61 | scale_lore: ["&7Click to change the scale of the", "&7nearest unlocked display entity.", " ", "&e&lRIGHT-CLICK&r&e to change by +%s", "&e&lSHIFT RIGHT-CLICK&r&e to change by -%s", "&e&lOFFHAND &r&eto reset value"] 62 | center_on_block_name: "&eCenter On Block" 63 | center_on_block_lore: ["&7Click to position the nearest display entity", "&7so that it is centered on the block.", " ", "&e&lRIGHT-CLICK&r&e to center xyz", "&e&lSHIFT RIGHT-CLICK&r&e to center xz"] 64 | tool_precision_name: "&eChange Tool Precision" 65 | tool_precision_lore: ["&7Click to change the multiplier for", "&7your tools precision.", " ", "&e&lRIGHT-CLICK&r&e to change by +%s", "&e&lSHIFT RIGHT-CLICK&r&e to change by -%s"] 66 | clone_tool_name: "&eClone Display Entity" 67 | clone_tool_lore: ["&7Click to duplicate the nearest", "&7display entity", " ", "&e&lRIGHT-CLICK&r&e to clone"] 68 | group_select_name: "&eGroup Select" 69 | group_select_lore: ["&7Click to add a display entities within", "&7the current range to a group, where", "&7all entities will be edited simultaneously", " ", "&e&lRIGHT-CLICK&r&e to select all within %s blocks", "&e&lSHIFT RIGHT-CLICK&r&e to clear group"] 70 | tool_selection_range_name: "&eChange Selection Range" 71 | tool_selection_range_lore: ["&7Click to change your selection range.", " ", "&e&lRIGHT-CLICK&r&e to change by +%s", "&e&lSHIFT RIGHT-CLICK&r&e to change by -%s", "&e&lOFFHAND &r&eto reset value"] 72 | tool_selection_search_mode_name: "&eChange Search Mode" 73 | tool_selection_search_mode_lore: ["&7Click to change your lock search mode.", " ", "&e&lRIGHT_CLICK&r&e to cycle forwards", "&e&lSHIFT RIGHT-CLICK&r&e to cycle backwards", "&e&lOFFHAND &r&eto reset value"] 74 | tool_selection_multiple_name: "&eChange Single/Multi Selection" 75 | tool_selection_multiple_lore: ["&7Click to change if you want to", "&7select one of multiple each operation.", " ", "&e&lRIGHT-CLICK&r&e to toggle", "&e&lOFFHAND &r&eto reset value"] 76 | tool_selection_mode_name: "&eChange Selection Mode" 77 | tool_selection_mode_lore_header: ["&7Click to change your selection mode.", " ", "&7Your current Selection Mode: &e%s", " "] 78 | tool_selection_mode_lore_end: [" ", "&e&lRIGHT_CLICK&r&e to cycle forwards", "&e&lSHIFT RIGHT-CLICK&r&e to cycle backwards", "&e&lOFFHAND &r&eto reset value"] 79 | tool_selection_mode_description_nearby: ["&7This mode will select the closest", "&7entity or entities within &e%2$s blocks", "&7depending on if you are in the", "&7single or multi selection mode."] 80 | tool_selection_mode_description_raycast: ["&7This mode will select the entity", "&7you are looking at."] 81 | 82 | # GUI Items 83 | name_name: "&eSet Name" 84 | name_lore: ["&7Currently: &3%s", " ", "&e&lLEFT-CLICK&r&e to enter new value", "&e&lRIGHT-CLICK&r&e to reset"] 85 | glowing_name: "&eToggle Glowing" 86 | glowing_lore: ["&7Currently: &3%s", " ", "&e&lLEFT-CLICK&r&e to toggle"] 87 | glow_color_name: "&eSet Glow Color" 88 | glow_color_lore: ["&7Currently: &3%s", " ", "&e&lLEFT-CLICK&r&e to set from RGB value"] 89 | left_rotation_normalize_name: "&eToggle Left Rotation Normalization" 90 | right_rotation_normalize_name: "&eToggle Right Rotation Normalization" 91 | rotation_normalize_lore: ["&7Currently: &3%s", "&7Will stop the shape of the display entity from", "&7deforming when rotated. Can usually be left on true", " ", "&e&lLEFT-CLICK&r&e to toggle"] 92 | view_range_name: "&eSet View Range" 93 | view_range_lore: ["&7Currently: &3%s", "&7Defines from how far the entity will be visible.", "&7The value counts in steps of 64 blocks and also factors", "&7in the scale of the entity. Can usually be left at 1.0", " ", "&e&lLEFT-CLICK&r&e to enter new value"] 94 | width_name: "&eSet Display Width" 95 | width_lore: ["&7Currently: &3%s", "&7Defines the maximum render width of the entity.", "&7If set to 0, there will be not render limit.", "&7Can usually be left at 0", " ", "&e&lLEFT-CLICK&r&e to enter new value"] 96 | height_name: "&eSet Display Height" 97 | height_lore: ["&7Currently: &3%s", "&7Defines the maximum render height of the entity.", "&7If set to 0, there will be not render limit.", "&7Can usually be left at 0", " ", "&e&lLEFT-CLICK&r&e to enter new value"] 98 | billboard_name: "&eSet Billboard Type" 99 | billboard_lore: ["&7Currently: &3%s", "&7Defines on what axis, if any, the display entity should", "&7visually rotate in the players direction", " ", "&e&lLEFT-CLICK&r&e to change"] 100 | shadow_radius_name: "&eSet Shadow Radius" 101 | shadow_radius_lore: ["&7Currently: &3%s", "&7Changes the size of the shadow. Values larger", "&7than 64 are treated as 64. Values smaller than", "&71 mean that the entity has no shadow", " ", "&e&lLEFT-CLICK&r&e to enter new value"] 102 | shadow_strength_name: "&eSet Shadow Strength" 103 | shadow_strength_lore: ["&7Currently: &3%s", "&7Changes how strong the shadow should be.", "&7Value must be between 0 and 1 (inclusive)", " ", "&e&lLEFT-CLICK&r&e to enter new value"] 104 | lock_name: "&eLock Entity" 105 | lock_lore: ["&7Makes the entity uneditable until unlocked", "&7with the unlock item. This is useful when you", "&7have lots of entities in a small space and don't", "&7want to accidentally edit the wrong one", " ", "&e&lLEFT-CLICK&r&e to lock"] 106 | sky_light_name: "&eSet Sky Brightness" 107 | block_light_name: "&eSet Block Brightness" 108 | light_lore: ["&7Currently: &3%s", "&7Used to override the default lighting level", "&7used to illuminate the display entity", " ", "&e&lLEFT-CLICK&r&e to change", "&e&lRIGHT-CLICK&r&e to reset"] 109 | delete_name: "&eDelete Entity" 110 | delete_lore: ["&7Permanently deletes this entity", " ", "&e&lLEFT-CLICK&r&e to delete"] 111 | item_display_transform_name: "&eSet Item Render Type" 112 | item_display_transform_lore: ["&7Currently: &3%s", "&7Defines how the item should be rendered", "&7(as if it was on a player head, hand, inventory etc.)", " ", "&e&lLEFT-CLICK&r&e to change"] 113 | text_opacity_name: "&eSet Text Opacity" 114 | text_opacity_lore: ["&7Currently: &3%d", "&7Opacity value between 1 and 255 (inclusive) or 0 for default", " ", "&e&lLEFT-CLICK&r&e to enter new value"] 115 | text_line_width_name: "&eSet Line Width" 116 | text_line_width_lore: ["&7Currently: &3%d", "&7Defines the maximum line width.", "&7Note that \\n can also be used to split lines", " ", "&e&lLEFT-CLICK&r&e to enter new value"] 117 | text_default_background_name: "&eToggle Default Background" 118 | text_default_background_lore: ["&7Currently: &3%s", "&7Defines whether the default background or the", "&7chosen background color should be used", " ", "&e&lLEFT-CLICK&r&e to toggle"] 119 | text_see_through_name: "&eToggle Visibility Through Blocks" 120 | text_see_through_lore: ["&7Currently: &3%s", "&7Defines whether the text should be visible", "&7through blocks", " ", "&e&lLEFT-CLICK&r&e to toggle"] 121 | text_shadow_name: "&eToggle Text Shadow" 122 | text_shadow_lore: ["&7Currently: &3%s", "&7Defines whether the text should", "&7have a shadow", " ", "&e&lLEFT-CLICK&r&e to toggle"] 123 | text_background_color_name: "&eSet Background Color" 124 | text_background_color_lore: ["&7Currently: &3%s", " ", "&e&lLEFT-CLICK&r&e to set from RGB value"] 125 | text_background_opacity_name: "&eSet Background Opacity" 126 | text_background_opacity_lore: ["&7Currently: &3%d", "&7Used to change the opacity of the background color.", "&7Should be able value between 0 and 255 (inclusive)", " ", "&e&lLEFT-CLICK&r&e to enter new value"] 127 | text_alignment_name: "&eSet Text Alignment" 128 | text_alignment_lore: ["&7Currently: &3%s", " ", "&e&lLEFT-CLICK&r&e to change"] 129 | text_name: "&eSet Text" 130 | text_lore: [" ", "&e&lLEFT-CLICK&r&e to change", "&e&lRIGHT-CLICK&r&e to append"] 131 | block_state_name: "&eSet Block State" 132 | block_state_lore: ["&7Currently: &3%s", " ", "&e&lLEFT-CLICK&r&e to enter new value", "&e&lRIGHT-CLICK&r&e to reset"] 133 | 134 | #Input Hints 135 | generic_hint: "Please enter the value in chat!" 136 | name_command_hint_mm: "Use MiniMessage formatting to stylize your input." 137 | name_command_hint: "You can use '&' for color codes." 138 | name_hint_mm: "Please enter the new name in chat! Use MiniMessage formatting to stylize your input." 139 | name_hint: "Please enter the new name in chat! You can use '&' for color codes." 140 | generic_color_command_hint: "Use the format R, G, B" 141 | generic_color_hint: "Please enter the new rgb values in chat! Use the format: R, G, B" 142 | shadow_strength_command_hint: "The value should be between 0 and 1 (inclusive)." 143 | shadow_strength_hint: "Please enter the value in chat! The value should be between 0 and 1 (inclusive)." 144 | lock_hint: "Display entity locked! Use the unlock item to unlock it again!" 145 | delete_hint: "Display entity deleted!" 146 | block_state_command_hint: "You can either use f3 or and online tool to help generate it." 147 | block_state_hint: "Please enter the new block state! You can either use f3 or an online tool to help generate it." 148 | opacity_command_hint: "Value should be between 0 and 255." 149 | opacity_hint: "Please enter the value in chat! Value should be between 0 and 255." 150 | text_command_hint_mm: "Use MiniMessage formatting to stylize your input." 151 | text_command_hint: "You can use '&' for color codes and \\n to create line breaks." 152 | text_hint_mm: "Please enter the new text in chat! Use MiniMessage formatting to stylize your input." 153 | text_hint: "Please enter the new text in chat! You can use '&' for color codes and \\n to create line breaks." 154 | text_clipboard_hint: "&7&nClick here to copy the previous text to your clipboard!" 155 | text_append_hint_mm: "Please enter the text in chat the should be appended! Use MiniMessage formatting to stylize your input." 156 | text_append_hint: "Please enter the text in chat that should be appended! You can use '&' for color codes and \\n to create line breaks." 157 | block_invalid_hint: "Invalid block! The item must be a block item!" 158 | 159 | #Tool feedback 160 | generic_fail: "Couldn't find a display entity that matches your selection settings!" 161 | item_display_spawned: "Spawned new item display entity!" 162 | block_display_spawned: "Spawned new block display entity!" 163 | text_display_spawned: "Spawned new text display entity!" 164 | unlock_fail: "There is no locked display entity within 5 blocks!" 165 | unlock_success: "Display entity unlocked!" 166 | tool_precision: "Tool Precision: %s" 167 | tool_range: "Tool Range: %s" 168 | tool_selection_changed: "Selection Mode: %s" 169 | tool_search_changed: "Lock Search Mode: %s" 170 | tool_multiple_changed: "Select Multiple: %s" 171 | gui_open_fail: "Someone else is editing this entity at the moment!" 172 | gui_only_single_displays: "This GUI is only for modifying single display entities!" 173 | yaw: "Yaw: %s" 174 | pitch: "Pitch: %s" 175 | move_x: "X: %s" 176 | move_y: "Y: %s" 177 | move_z: "Z: %s" 178 | center_pivot: "Centered pivot!" 179 | translation_x: "Translation X: %s" 180 | translation_y: "Translation Y: %s" 181 | translation_z: "Translation Z: %s" 182 | scale_x: "Scale X: %s" 183 | scale_y: "Scale Y: %s" 184 | scale_z: "Scale Z: %s" 185 | normalized: "(normalized)" 186 | left_rot_x: "Left Rotation X %s: %s" 187 | left_rot_y: "Left Rotation Y %s: %s" 188 | left_rot_z: "Left Rotation Z %s: %s" 189 | right_rot_x: "Right Rotation X %s: %s" 190 | right_rot_y: "Right Rotation Y %s: %s" 191 | right_rot_z: "Right Rotation Z %s: %s" 192 | center_block: "Centered at: %f %f %f" 193 | clone: "Display entity cloned!" 194 | group_select_fail: "There are no unlocked display entities within the specified range!" 195 | group_select_success: "Created group containing %s display entities!" 196 | group_select_clear: "Cleared current editing group!" 197 | value_reset: "Value reset!" 198 | 199 | # Input prompts 200 | prompt_escape_word: "cancel" 201 | generic_color_fail: "The value needs to follow the format: R, G, B" 202 | integer_fail: "The value needs to be an integer (whole number)!" 203 | float_fail: "The value need to be a decimal number!" 204 | float_shadow_strength_fail: "The value needs to be a decimal number between 0 and 1 (inclusive)!" 205 | generic_prompt: "%s (enter \"%s\" to abort)" 206 | line_width_success: "Line width set!" 207 | opacity_success: "Opacity set!" 208 | view_range_success: "View range set!" 209 | display_width_success: "Display width set!" 210 | display_height_success: "Display height set!" 211 | shadow_radius_success: "Shadow radius set!" 212 | shadow_strength_success: "Shadow strength set!" 213 | shadow_strength_fail: "The value needs to be between 0 and 1!" 214 | name_success: "Name set!" 215 | text_success: "Set text!" 216 | text_append_success: "Appended text!" 217 | background_color_success: "Background color set!" 218 | glow_color_success: "Glow color set!" 219 | block_state_success: "Block state set!" 220 | block_state_fail: "The value given was not a valid block state! Try looking at a block with the block state you want with f3 on to see its block states or use an online tool!" 221 | 222 | # Command feedback 223 | inventory_returned: "Your inventory has been returned to you!" 224 | tools_received_1: "Given display entity tools. Left click to cycle through them" 225 | tools_received_2: "&3[DEE]&9 Run this command again to have your inventory returned!" 226 | config_reload: "Config reloaded!" 227 | generic_command_fail: "Invalid arguments!" 228 | none_player_fail: "This command must be run by a player!" 229 | messages_reload_fail: "Failed to load messages.yml" 230 | 231 | # Current state names 232 | # (These lists need to stay ordered the way they are and with the amount of entries they currently have) 233 | boolean: ["true", "false"] 234 | default: "Default" 235 | none: "None" 236 | text_alignment: ["CENTER", "LEFT", "RIGHT"] 237 | billboard: ["CENTER", "FIXED", "HORIZONTAL", "VERTICAL"] 238 | rgb: "RGB: %d, %d, %d" 239 | item_display_transform: ["FIRSTPERSON_LEFTHAND", "FIRSTPERSON_RIGHTHAND", "FIXED", "GROUND", "GUI", "HEAD", "NONE", "THIRDPERSON_LEFTHAND", "THIRDPERSON_RIGHTHAND"] 240 | selection_mode: ["Nearby", "Raycast"] 241 | lock_search_mode: ["All", "Locked only", "Unlocked only"] 242 | 243 | #GUI names 244 | block_display_gui_name: "&lBlock Display GUI" 245 | item_display_gui_name: "&lItem Display GUI" 246 | text_display_gui_name: "&lText Display GUI" -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/items/InventoryItems.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.items; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.SelectionMode; 5 | import goldenshadow.displayentityeditor.Utilities; 6 | 7 | import java.util.ArrayList; 8 | 9 | import org.bukkit.Material; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.inventory.ItemStack; 12 | 13 | /** 14 | * A utility class where all inventory items are created 15 | */ 16 | public class InventoryItems { 17 | 18 | /** 19 | * Creates the open gui item 20 | * @return The item 21 | */ 22 | public ItemStack gui() { 23 | ItemStack itemStack = new ItemStack(Material.NETHER_STAR); 24 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("open_gui_name"), 25 | DisplayEntityEditor.messageManager.getList("open_gui_lore"), 26 | "InventoryGUI" 27 | ); 28 | return itemStack; 29 | } 30 | 31 | /** 32 | * Creates the rotate yaw item 33 | * @return The item 34 | */ 35 | public ItemStack rotateYaw(Player p) { 36 | ItemStack itemStack = new ItemStack(Material.MAGMA_CREAM); 37 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("rotate_yaw_name"), 38 | DisplayEntityEditor.messageManager.getList("rotate_lore"), 39 | "InventoryRotateYaw", 40 | Utilities.reduceFloatLength(Double.toString(Utilities.getToolPrecision(p))) 41 | ); 42 | return itemStack; 43 | } 44 | 45 | /** 46 | * Creates the rotate pitch item 47 | * @return The item 48 | */ 49 | public ItemStack rotatePitch(Player p) { 50 | ItemStack itemStack = new ItemStack(Material.SLIME_BALL); 51 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("rotate_pitch_name"), 52 | DisplayEntityEditor.messageManager.getList("rotate_lore"), 53 | "InventoryRotatePitch", 54 | Utilities.reduceFloatLength(Double.toString(Utilities.getToolPrecision(p))) 55 | ); 56 | return itemStack; 57 | } 58 | 59 | /** 60 | * Creates the move x item 61 | * @return The item 62 | */ 63 | public ItemStack moveX(Player p) { 64 | ItemStack itemStack = new ItemStack(Material.SHEARS); 65 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("move_x_name"), 66 | DisplayEntityEditor.messageManager.getList("move_lore"), 67 | "InventoryMoveX", 68 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 69 | ); 70 | return itemStack; 71 | } 72 | 73 | /** 74 | * Creates the move y item 75 | * @return The item 76 | */ 77 | public ItemStack moveY(Player p) { 78 | ItemStack itemStack = new ItemStack(Material.SHEARS); 79 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("move_y_name"), 80 | DisplayEntityEditor.messageManager.getList("move_lore"), 81 | "InventoryMoveY", 82 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 83 | ); 84 | return itemStack; 85 | } 86 | 87 | /** 88 | * Creates the move z item 89 | * @return The item 90 | */ 91 | public ItemStack moveZ(Player p) { 92 | ItemStack itemStack = new ItemStack(Material.SHEARS); 93 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("move_z_name"), 94 | DisplayEntityEditor.messageManager.getList("move_lore"), 95 | "InventoryMoveZ", 96 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 97 | ); 98 | return itemStack; 99 | } 100 | 101 | /** 102 | * Creates the spawn item display item 103 | * @return The item 104 | */ 105 | public ItemStack spawnItemDisplay() { 106 | ItemStack itemStack = new ItemStack(Material.DIAMOND); 107 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("spawn_item_display_name"), 108 | DisplayEntityEditor.messageManager.getList("spawn_item_display_lore"), 109 | "InventorySpawnItem" 110 | ); 111 | return itemStack; 112 | } 113 | 114 | /** 115 | * Creates the spawn block display item 116 | * @return The item 117 | */ 118 | public ItemStack spawnBlockDisplay() { 119 | ItemStack itemStack = new ItemStack(Material.GRASS_BLOCK); 120 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("spawn_block_display_name"), 121 | DisplayEntityEditor.messageManager.getList("spawn_block_display_lore"), 122 | "InventorySpawnBlock" 123 | ); 124 | return itemStack; 125 | } 126 | 127 | /** 128 | * Creates the spawn text display item 129 | * @return The item 130 | */ 131 | public ItemStack spawnTextDisplay() { 132 | ItemStack itemStack = new ItemStack(Material.OAK_SIGN); 133 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("spawn_text_display_name"), 134 | DisplayEntityEditor.messageManager.getList("spawn_text_display_lore"), 135 | "InventorySpawnText" 136 | ); 137 | return itemStack; 138 | } 139 | 140 | /** 141 | * Creates the unlock item 142 | * @return The item 143 | */ 144 | public ItemStack unlock() { 145 | ItemStack itemStack = new ItemStack(Material.MUSIC_DISC_11); 146 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("unlock_name"), 147 | DisplayEntityEditor.messageManager.getList("unlock_lore"), 148 | "InventoryUnlock" 149 | ); 150 | return itemStack; 151 | } 152 | 153 | /** 154 | * Creates the highlight target item 155 | * @return The item 156 | */ 157 | public ItemStack highlightTarget() { 158 | ItemStack itemStack = new ItemStack(Material.GLOWSTONE_DUST); 159 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("highlight_target_name"), 160 | DisplayEntityEditor.messageManager.getList("highlight_target_lore"), 161 | "InventoryHighlight" 162 | ); 163 | return itemStack; 164 | } 165 | 166 | /** 167 | * Creates the left rotation x item 168 | * @return The item 169 | */ 170 | public ItemStack leftRotationX(Player p) { 171 | ItemStack itemStack = new ItemStack(Material.STICK); 172 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("left_rotation_x_name"), 173 | DisplayEntityEditor.messageManager.getList("left_rotation_lore"), 174 | "InventoryLRX", 175 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 176 | ); 177 | return itemStack; 178 | } 179 | 180 | /** 181 | * Creates the left rotation y item 182 | * @return The item 183 | */ 184 | public ItemStack leftRotationY(Player p) { 185 | ItemStack itemStack = new ItemStack(Material.STICK); 186 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("left_rotation_y_name"), 187 | DisplayEntityEditor.messageManager.getList("left_rotation_lore"), 188 | "InventoryLRY", 189 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 190 | ); 191 | return itemStack; 192 | } 193 | 194 | /** 195 | * Creates the left rotation z item 196 | * @return The item 197 | */ 198 | public ItemStack leftRotationZ(Player p) { 199 | ItemStack itemStack = new ItemStack(Material.STICK); 200 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("left_rotation_z_name"), 201 | DisplayEntityEditor.messageManager.getList("left_rotation_lore"), 202 | "InventoryLRZ", 203 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 204 | ); 205 | return itemStack; 206 | } 207 | 208 | /** 209 | * Creates the right rotation x item 210 | * @return The item 211 | */ 212 | public ItemStack rightRotationX(Player p) { 213 | ItemStack itemStack = new ItemStack(Material.BLAZE_ROD); 214 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("right_rotation_x_name"), 215 | DisplayEntityEditor.messageManager.getList("right_rotation_lore"), 216 | "InventoryRRX", 217 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 218 | ); 219 | return itemStack; 220 | } 221 | 222 | /** 223 | * Creates the right rotation y item 224 | * @return The item 225 | */ 226 | public ItemStack rightRotationY(Player p) { 227 | ItemStack itemStack = new ItemStack(Material.BLAZE_ROD); 228 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("right_rotation_y_name"), 229 | DisplayEntityEditor.messageManager.getList("right_rotation_lore"), 230 | "InventoryRRY", 231 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 232 | ); 233 | return itemStack; 234 | } 235 | 236 | /** 237 | * Creates the right rotation z item 238 | * @return The item 239 | */ 240 | public ItemStack rightRotationZ(Player p) { 241 | ItemStack itemStack = new ItemStack(Material.BLAZE_ROD); 242 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("right_rotation_z_name"), 243 | DisplayEntityEditor.messageManager.getList("right_rotation_lore"), 244 | "InventoryRRZ", 245 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 246 | ); 247 | return itemStack; 248 | } 249 | 250 | /** 251 | * Creates the center pivot item 252 | * @return The item 253 | */ 254 | public ItemStack centerPivot() { 255 | ItemStack itemStack = new ItemStack(Material.CHAIN); 256 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("center_pivot_name"), 257 | DisplayEntityEditor.messageManager.getList("center_pivot_lore"), 258 | "InventoryCenterPivot" 259 | ); 260 | return itemStack; 261 | } 262 | 263 | /** 264 | * Creates the translation x item 265 | * @return The item 266 | */ 267 | public ItemStack translationX(Player p) { 268 | ItemStack itemStack = new ItemStack(Material.NETHERITE_SCRAP); 269 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("translation_x_name"), 270 | DisplayEntityEditor.messageManager.getList("translation_lore"), 271 | "InventoryTX", 272 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 273 | ); 274 | return itemStack; 275 | } 276 | 277 | /** 278 | * Creates the translation y item 279 | * @return The item 280 | */ 281 | public ItemStack translationY(Player p) { 282 | ItemStack itemStack = new ItemStack(Material.NETHERITE_SCRAP); 283 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("translation_y_name"), 284 | DisplayEntityEditor.messageManager.getList("translation_lore"), 285 | "InventoryTY", 286 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 287 | ); 288 | return itemStack; 289 | } 290 | 291 | /** 292 | * Creates the translation z item 293 | * @return The item 294 | */ 295 | public ItemStack translationZ(Player p) { 296 | ItemStack itemStack = new ItemStack(Material.NETHERITE_SCRAP); 297 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("translation_z_name"), 298 | DisplayEntityEditor.messageManager.getList("translation_lore"), 299 | "InventoryTZ", 300 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 301 | ); 302 | return itemStack; 303 | } 304 | 305 | /** 306 | * Creates the scale x item 307 | * @return The item 308 | */ 309 | public ItemStack scaleX(Player p) { 310 | ItemStack itemStack = new ItemStack(Material.SHULKER_SHELL); 311 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("scale_x_name"), 312 | DisplayEntityEditor.messageManager.getList("scale_lore"), 313 | "InventorySX", 314 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 315 | ); 316 | return itemStack; 317 | } 318 | 319 | /** 320 | * Creates the scale y item 321 | * @return The item 322 | */ 323 | public ItemStack scaleY(Player p) { 324 | ItemStack itemStack = new ItemStack(Material.SHULKER_SHELL); 325 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("scale_y_name"), 326 | DisplayEntityEditor.messageManager.getList("scale_lore"), 327 | "InventorySY", 328 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 329 | ); 330 | return itemStack; 331 | } 332 | 333 | /** 334 | * Creates the scale z item 335 | * @return The item 336 | */ 337 | public ItemStack scaleZ(Player p) { 338 | ItemStack itemStack = new ItemStack(Material.SHULKER_SHELL); 339 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("scale_z_name"), 340 | DisplayEntityEditor.messageManager.getList("scale_lore"), 341 | "InventorySZ", 342 | Utilities.reduceFloatLength(Double.toString(0.1 * Utilities.getToolPrecision(p))) 343 | ); 344 | return itemStack; 345 | } 346 | 347 | /** 348 | * Creates the center on block item 349 | * @return The item 350 | */ 351 | public ItemStack centerOnBlock() { 352 | ItemStack itemStack = new ItemStack(Material.LIGHTNING_ROD); 353 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("center_on_block_name"), 354 | DisplayEntityEditor.messageManager.getList("center_on_block_lore"), 355 | "InventoryCenterBlock" 356 | ); 357 | return itemStack; 358 | } 359 | 360 | /** 361 | * Creates the tool precision item 362 | * @return The item 363 | */ 364 | public ItemStack toolPrecision(Player p) { 365 | float precision = Utilities.getToolPrecision(p); 366 | ItemStack itemStack = new ItemStack(Material.COMPARATOR); 367 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("tool_precision_name"), 368 | DisplayEntityEditor.messageManager.getList("tool_precision_lore"), 369 | "InventoryToolPrecision", 370 | Utilities.reduceFloatLength(Double.toString(precision < 1 ? 0.1f : 1f)) 371 | ); 372 | return itemStack; 373 | } 374 | 375 | /** 376 | * Creates the tool selection mode item 377 | * @return The item 378 | */ 379 | public ItemStack toolSelectionMode(Player p) { 380 | ItemStack itemStack = new ItemStack(Material.RECOVERY_COMPASS); 381 | SelectionMode mode = Utilities.getToolSelectMode(p); 382 | ArrayList lore = new ArrayList<>(); 383 | lore.addAll(DisplayEntityEditor.messageManager.getList("tool_selection_mode_lore_start")); 384 | lore.addAll(DisplayEntityEditor.messageManager.getList("tool_selection_mode_description_" + mode.id())); 385 | lore.addAll(DisplayEntityEditor.messageManager.getList("tool_selection_mode_lore_end")); 386 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("tool_selection_mode_name"), 387 | lore, 388 | "InventoryToolSelectionMode", 389 | Utilities.getObjectNameMessage(mode), 390 | Utilities.reduceFloatLength(Double.toString(Utilities.getToolSelectRange(p))) 391 | ); 392 | return itemStack; 393 | } 394 | 395 | /** 396 | * Creates the tool selection range item 397 | * @return The item 398 | */ 399 | public ItemStack toolSelectionRange(Player p) { 400 | float range = Utilities.getToolSelectRange(p); 401 | ItemStack itemStack = new ItemStack(Material.SPECTRAL_ARROW); 402 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("tool_selection_range_name"), 403 | DisplayEntityEditor.messageManager.getList("tool_selection_range_lore"), 404 | "InventoryToolSelectionRange", 405 | Utilities.reduceFloatLength(Double.toString(range < 2 ? 0.25f : 1f)) 406 | ); 407 | return itemStack; 408 | } 409 | 410 | /** 411 | * Creates the tool selection search mode item 412 | * @return The item 413 | */ 414 | public ItemStack toolSearchMode() { 415 | ItemStack itemStack = new ItemStack(Material.CLOCK); 416 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("tool_selection_search_mode_name"), 417 | DisplayEntityEditor.messageManager.getList("tool_selection_search_mode_lore"), 418 | "InventoryToolSelectionSearchMode" 419 | ); 420 | return itemStack; 421 | } 422 | 423 | /** 424 | * Creates the tool selection multiple item 425 | * @return The item 426 | */ 427 | public ItemStack toolSelectionMultiple() { 428 | ItemStack itemStack = new ItemStack(Material.CHEST); 429 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("tool_selection_multiple_name"), 430 | DisplayEntityEditor.messageManager.getList("tool_selection_multiple_lore"), 431 | "InventoryToolSelectionMultiple" 432 | ); 433 | return itemStack; 434 | } 435 | 436 | /** 437 | * Creates the clone item 438 | * @return The item 439 | */ 440 | public ItemStack cloneTool() { 441 | ItemStack itemStack = new ItemStack(Material.FLOWER_BANNER_PATTERN); 442 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("clone_tool_name"), 443 | DisplayEntityEditor.messageManager.getList("clone_tool_lore"), 444 | "InventoryClone" 445 | ); 446 | return itemStack; 447 | } 448 | 449 | /** 450 | * Creates the group select item 451 | * @return The item 452 | */ 453 | public ItemStack groupSelectTool(Player p) { 454 | ItemStack itemStack = new ItemStack(Material.MINECART); 455 | Utilities.setMeta(itemStack, DisplayEntityEditor.messageManager.getString("group_select_name"), 456 | DisplayEntityEditor.messageManager.getList("group_select_lore"), 457 | "InventoryGroupSelect", 458 | Utilities.reduceFloatLength(Double.toString(Utilities.getToolSelectRange(p))) 459 | ); 460 | return itemStack; 461 | } 462 | } 463 | -------------------------------------------------------------------------------- /src/main/java/goldenshadow/displayentityeditor/events/InventoryClick.java: -------------------------------------------------------------------------------- 1 | package goldenshadow.displayentityeditor.events; 2 | 3 | import goldenshadow.displayentityeditor.DisplayEntityEditor; 4 | import goldenshadow.displayentityeditor.Utilities; 5 | import goldenshadow.displayentityeditor.conversation.InputData; 6 | import goldenshadow.displayentityeditor.conversation.InputManager; 7 | import goldenshadow.displayentityeditor.enums.InputType; 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.ChatColor; 10 | import org.bukkit.Material; 11 | import org.bukkit.block.data.BlockData; 12 | import org.bukkit.entity.*; 13 | import org.bukkit.event.EventHandler; 14 | import org.bukkit.event.Listener; 15 | import org.bukkit.event.inventory.InventoryClickEvent; 16 | import org.bukkit.inventory.ItemStack; 17 | 18 | 19 | public class InventoryClick implements Listener { 20 | 21 | 22 | /** 23 | * Used to listen for when a player clicks on a gui item 24 | * @param event The event 25 | */ 26 | @EventHandler 27 | public void inventoryClick(InventoryClickEvent event) { 28 | Player player = (Player) event.getWhoClicked(); 29 | if (player.getOpenInventory().getTitle().equals(ChatColor.translateAlternateColorCodes('&' ,DisplayEntityEditor.messageManager.getString("item_display_gui_name"))) || player.getOpenInventory().getTitle().equals(ChatColor.translateAlternateColorCodes('&' ,DisplayEntityEditor.messageManager.getString("block_display_gui_name"))) || player.getOpenInventory().getTitle().equals(ChatColor.translateAlternateColorCodes('&' ,DisplayEntityEditor.messageManager.getString("text_display_gui_name")))) { 30 | Display entity = DisplayEntityEditor.currentEditMap.get(player.getUniqueId()); 31 | if (event.getClickedInventory() != null && !event.getClickedInventory().equals(player.getInventory())) { 32 | if (event.getCurrentItem() != null && Utilities.hasDataKey(event.getCurrentItem())) { 33 | event.setCancelled(true); 34 | String value = Utilities.getToolValue(event.getCurrentItem()); 35 | if (value != null) { 36 | switch (value) { 37 | case "GUIName" -> { 38 | if (event.isLeftClick()) { 39 | player.closeInventory(); 40 | if (DisplayEntityEditor.alternateTextInput) { 41 | if (DisplayEntityEditor.useMiniMessageFormat) { 42 | player.spigot().sendMessage(Utilities.getCommandMessage("name ", DisplayEntityEditor.messageManager.getString("name_command_hint_mm"))); 43 | } else { 44 | player.spigot().sendMessage(Utilities.getCommandMessage("name ", DisplayEntityEditor.messageManager.getString("name_command_hint"))); 45 | } 46 | } else { 47 | if (DisplayEntityEditor.useMiniMessageFormat) { 48 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("name_hint_mm"), new InputData(entity, InputType.NAME, null)); 49 | } else { 50 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("name_hint"), new InputData(entity, InputType.NAME, null)); 51 | } 52 | } 53 | } else { 54 | entity.setCustomNameVisible(false); 55 | entity.setCustomName(null); 56 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().name(null)); 57 | } 58 | } 59 | case "GUIGlow" -> { 60 | if (event.isLeftClick()) { 61 | boolean b = !entity.isGlowing(); 62 | 63 | BlockData blockData; 64 | if (entity instanceof BlockDisplay) blockData = ((BlockDisplay) entity).getBlock(); 65 | else { 66 | blockData = null; 67 | } 68 | 69 | entity.setGlowing(b); 70 | 71 | if (entity instanceof BlockDisplay) { 72 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> ((BlockDisplay) entity).setBlock(blockData), 1L); 73 | } 74 | 75 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().glowing(b)); 76 | } 77 | } 78 | case "GUIGlowColor" -> { 79 | if (event.isLeftClick()) { 80 | player.closeInventory(); 81 | if (DisplayEntityEditor.alternateTextInput) { 82 | player.spigot().sendMessage(Utilities.getCommandMessage("glow_color ", DisplayEntityEditor.messageManager.getString("generic_color_command_hint"))); 83 | } else { 84 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("generic_color_hint"), new InputData(entity, InputType.GLOW_COLOR, null)); 85 | } 86 | } 87 | } 88 | case "GUILRNormalize" -> { 89 | if (event.isLeftClick()) { 90 | boolean b = !Utilities.getData(entity, "GUILRNormalize"); 91 | Utilities.setData(entity, "GUILRNormalize", b); 92 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().leftRotNormalize(b)); 93 | } 94 | } 95 | case "GUIRRNormalize" -> { 96 | if (event.isLeftClick()) { 97 | boolean b = !Utilities.getData(entity, "GUIRRNormalize"); 98 | Utilities.setData(entity, "GUIRRNormalize", b); 99 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().rightRotNormalize(b)); 100 | } 101 | } 102 | case "GUIViewRange" -> { 103 | if (event.isLeftClick()) { 104 | player.closeInventory(); 105 | 106 | if (DisplayEntityEditor.alternateTextInput) { 107 | player.spigot().sendMessage(Utilities.getCommandMessage("view_range ", "")); 108 | } else { 109 | InputManager.createFloatInput(player, DisplayEntityEditor.messageManager.getString("generic_hint"), new InputData(entity, InputType.VIEW_RANGE, null)); 110 | } 111 | } 112 | } 113 | case "GUIWidth" -> { 114 | if (event.isLeftClick()) { 115 | player.closeInventory(); 116 | 117 | if (DisplayEntityEditor.alternateTextInput) { 118 | player.spigot().sendMessage(Utilities.getCommandMessage("display_width ","")); 119 | } else { 120 | InputManager.createFloatInput(player, DisplayEntityEditor.messageManager.getString("generic_hint"), new InputData(entity, InputType.DISPLAY_WIDTH, null)); 121 | } 122 | } 123 | } 124 | case "GUIHeight" -> { 125 | if (event.isLeftClick()) { 126 | player.closeInventory(); 127 | 128 | if (DisplayEntityEditor.alternateTextInput) { 129 | player.spigot().sendMessage(Utilities.getCommandMessage("display_height ", "")); 130 | } else { 131 | InputManager.createFloatInput(player, DisplayEntityEditor.messageManager.getString("generic_hint"), new InputData(entity, InputType.DISPLAY_HEIGHT, null)); 132 | } 133 | } 134 | } 135 | case "GUIBillboard" -> { 136 | if (event.isLeftClick()) { 137 | 138 | BlockData blockData; 139 | if (entity instanceof BlockDisplay) blockData = ((BlockDisplay) entity).getBlock(); 140 | else { 141 | blockData = null; 142 | } 143 | 144 | Display.Billboard billboard = entity.getBillboard(); 145 | billboard = Display.Billboard.values()[(billboard.ordinal()+1) % Display.Billboard.values().length]; 146 | entity.setBillboard(billboard); 147 | 148 | if (entity instanceof BlockDisplay) { 149 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> ((BlockDisplay) entity).setBlock(blockData), 1L); 150 | } 151 | 152 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().billboard(billboard)); 153 | } 154 | } 155 | case "GUIShadowRadius" -> { 156 | if (event.isLeftClick()) { 157 | player.closeInventory(); 158 | 159 | if (DisplayEntityEditor.alternateTextInput) { 160 | player.spigot().sendMessage(Utilities.getCommandMessage("shadow_radius ", "")); 161 | } else { 162 | InputManager.createFloatInput(player, DisplayEntityEditor.messageManager.getString("generic_hint"), new InputData(entity, InputType.SHADOW_RADIUS, null)); 163 | } 164 | } 165 | } 166 | case "GUIShadowStrength" -> { 167 | if (event.isLeftClick()) { 168 | player.closeInventory(); 169 | 170 | if (DisplayEntityEditor.alternateTextInput) { 171 | player.spigot().sendMessage(Utilities.getCommandMessage("shadow_strength ", DisplayEntityEditor.messageManager.getString("shadow_strength_command_hint"))); 172 | } else { 173 | InputManager.createFloatInput(player, DisplayEntityEditor.messageManager.getString("shadow_strength_hint"), new InputData(entity, InputType.SHADOW_STRENGTH, null)); 174 | } 175 | } 176 | } 177 | case "GUILock" -> { 178 | if (event.isLeftClick()) { 179 | entity.addScoreboardTag("dee:locked"); 180 | player.sendMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("lock_hint"))); 181 | player.closeInventory(); 182 | } 183 | } 184 | case "GUISkyLight" -> { 185 | if (event.isLeftClick()) { 186 | 187 | BlockData blockData; 188 | if (entity instanceof BlockDisplay) blockData = ((BlockDisplay) entity).getBlock(); 189 | else { 190 | blockData = null; 191 | } 192 | 193 | Display.Brightness b; 194 | if (entity.getBrightness() != null) { 195 | b = new Display.Brightness(entity.getBrightness().getBlockLight(), (entity.getBrightness().getSkyLight()+1) % 16); 196 | } else { 197 | b = new Display.Brightness(0,0); 198 | } 199 | entity.setBrightness(b); 200 | 201 | if (entity instanceof BlockDisplay) { 202 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> ((BlockDisplay) entity).setBlock(blockData), 1L); 203 | } 204 | 205 | player.getOpenInventory().setItem(8, DisplayEntityEditor.inventoryFactory.getGuiItems().skyLight(b.getSkyLight())); 206 | player.getOpenInventory().setItem(17, DisplayEntityEditor.inventoryFactory.getGuiItems().blockLight(b.getBlockLight())); 207 | } 208 | if (event.isRightClick()) { 209 | 210 | BlockData blockData; 211 | if (entity instanceof BlockDisplay) blockData = ((BlockDisplay) entity).getBlock(); 212 | else { 213 | blockData = null; 214 | } 215 | 216 | entity.setBrightness(null); 217 | 218 | if (entity instanceof BlockDisplay) { 219 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> ((BlockDisplay) entity).setBlock(blockData), 1L); 220 | } 221 | 222 | player.getOpenInventory().setItem(8, DisplayEntityEditor.inventoryFactory.getGuiItems().skyLight(-1)); 223 | player.getOpenInventory().setItem(17, DisplayEntityEditor.inventoryFactory.getGuiItems().blockLight(-1)); 224 | } 225 | } 226 | case "GUIBlockLight" -> { 227 | if (event.isLeftClick()) { 228 | 229 | BlockData blockData; 230 | if (entity instanceof BlockDisplay) blockData = ((BlockDisplay) entity).getBlock(); 231 | else { 232 | blockData = null; 233 | } 234 | 235 | Display.Brightness b; 236 | if (entity.getBrightness() != null) { 237 | b = new Display.Brightness((entity.getBrightness().getBlockLight() + 1) % 16, entity.getBrightness().getSkyLight()); 238 | } else { 239 | b = new Display.Brightness(0,0); 240 | } 241 | entity.setBrightness(b); 242 | 243 | if (entity instanceof BlockDisplay) { 244 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> ((BlockDisplay) entity).setBlock(blockData), 1L); 245 | } 246 | 247 | player.getOpenInventory().setItem(8, DisplayEntityEditor.inventoryFactory.getGuiItems().skyLight(b.getSkyLight())); 248 | player.getOpenInventory().setItem(17, DisplayEntityEditor.inventoryFactory.getGuiItems().blockLight(b.getBlockLight())); 249 | } 250 | if (event.isRightClick()) { 251 | 252 | BlockData blockData; 253 | if (entity instanceof BlockDisplay) blockData = ((BlockDisplay) entity).getBlock(); 254 | else { 255 | blockData = null; 256 | } 257 | 258 | entity.setBrightness(null); 259 | 260 | if (entity instanceof BlockDisplay) { 261 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> ((BlockDisplay) entity).setBlock(blockData), 1L); 262 | } 263 | 264 | player.getOpenInventory().setItem(8, DisplayEntityEditor.inventoryFactory.getGuiItems().skyLight(-1)); 265 | player.getOpenInventory().setItem(17, DisplayEntityEditor.inventoryFactory.getGuiItems().blockLight(-1)); 266 | } 267 | } 268 | case "GUIDelete" -> { 269 | if (event.isLeftClick()) { 270 | entity.remove(); 271 | player.closeInventory(); 272 | player.sendMessage(Utilities.getInfoMessageFormat(DisplayEntityEditor.messageManager.getString("delete_hint"))); 273 | } 274 | } 275 | case "GUIItemDisplayTransform" -> { 276 | if (event.isLeftClick()) { 277 | ItemDisplay itemDisplay = (ItemDisplay) entity; 278 | ItemDisplay.ItemDisplayTransform transform = itemDisplay.getItemDisplayTransform(); 279 | transform = ItemDisplay.ItemDisplayTransform.values()[(transform.ordinal()+1) % ItemDisplay.ItemDisplayTransform.values().length]; 280 | itemDisplay.setItemDisplayTransform(transform); 281 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().itemDisplayTransform(transform)); 282 | } 283 | } 284 | case "GUIBlockState" -> { 285 | if (event.isLeftClick()) { 286 | 287 | player.closeInventory(); 288 | 289 | if (DisplayEntityEditor.alternateTextInput) { 290 | player.spigot().sendMessage(Utilities.getCommandMessage("block_state ", DisplayEntityEditor.messageManager.getString("block_state_command_hint"))); 291 | } else { 292 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("block_state_hint"), new InputData(entity, InputType.BLOCK_STATE, ((BlockDisplay) entity).getBlock().getMaterial())); 293 | } 294 | 295 | player.closeInventory(); 296 | } 297 | if (event.isRightClick()) { 298 | BlockDisplay b = (BlockDisplay) entity; 299 | b.setBlock(Bukkit.createBlockData(b.getBlock().getMaterial())); 300 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().blockState(b.getBlock().getAsString(true))); 301 | } 302 | } 303 | case "GUITextOpacity" -> { 304 | if (event.isLeftClick()) { 305 | player.closeInventory(); 306 | 307 | if (DisplayEntityEditor.alternateTextInput) { 308 | player.spigot().sendMessage(Utilities.getCommandMessage("text_opacity ", DisplayEntityEditor.messageManager.getString("opacity_command_hint"))); 309 | } else { 310 | InputManager.createByteInput(player, DisplayEntityEditor.messageManager.getString("opacity_hint"), new InputData(entity, InputType.TEXT_OPACITY, null)); 311 | } 312 | } 313 | } 314 | case "GUITextLineWidth" -> { 315 | if (event.isLeftClick()) { 316 | player.closeInventory(); 317 | 318 | if (DisplayEntityEditor.alternateTextInput) { 319 | player.spigot().sendMessage(Utilities.getCommandMessage("line_width ", "")); 320 | } else { 321 | InputManager.createIntegerInput(player, DisplayEntityEditor.messageManager.getString("generic_hint"), new InputData(entity, InputType.LINE_WIDTH, null)); 322 | } 323 | } 324 | } 325 | case "GUITextDefaultBackground" -> { 326 | if (event.isLeftClick()) { 327 | TextDisplay t = (TextDisplay) entity; 328 | boolean b = !t.isDefaultBackground(); 329 | t.setDefaultBackground(b); 330 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().textDefaultBackground(b)); 331 | } 332 | } 333 | case "GUITextSeeThrough" -> { 334 | if (event.isLeftClick()) { 335 | TextDisplay t = (TextDisplay) entity; 336 | boolean b = !t.isSeeThrough(); 337 | t.setSeeThrough(b); 338 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().textSeeThrough(b)); 339 | } 340 | } 341 | case "GUITextShadow" -> { 342 | if (event.isLeftClick()) { 343 | TextDisplay t = (TextDisplay) entity; 344 | boolean b = !t.isShadowed(); 345 | t.setShadowed(b); 346 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().textShadow(b)); 347 | } 348 | } 349 | case "GUITextBackgroundColor" -> { 350 | if (event.isLeftClick()) { 351 | player.closeInventory(); 352 | 353 | if (DisplayEntityEditor.alternateTextInput) { 354 | player.spigot().sendMessage(Utilities.getCommandMessage("background_color ", DisplayEntityEditor.messageManager.getString("generic_color_command_hint"))); 355 | } else { 356 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("generic_color_hint"), new InputData(entity, InputType.BACKGROUND_COLOR, null)); 357 | } 358 | } 359 | } 360 | case "GUITextBackgroundOpacity" -> { 361 | if (event.isLeftClick()) { 362 | player.closeInventory(); 363 | 364 | if (DisplayEntityEditor.alternateTextInput) { 365 | player.spigot().sendMessage(Utilities.getCommandMessage("background_opacity ", DisplayEntityEditor.messageManager.getString("opacity_command_hint"))); 366 | } else { 367 | InputManager.createByteInput(player, DisplayEntityEditor.messageManager.getString("opacity_hint"), new InputData(entity, InputType.BACKGROUND_OPACITY, null)); 368 | } 369 | } 370 | } 371 | case "GUITextAlignment" -> { 372 | if (event.isLeftClick()) { 373 | TextDisplay textDisplay = (TextDisplay) entity; 374 | TextDisplay.TextAlignment alignment = textDisplay.getAlignment(); 375 | alignment = TextDisplay.TextAlignment.values()[(alignment.ordinal()+1) % TextDisplay.TextAlignment.values().length]; 376 | textDisplay.setAlignment(alignment); 377 | player.getOpenInventory().setItem(event.getSlot(), DisplayEntityEditor.inventoryFactory.getGuiItems().textAlignment(alignment)); 378 | } 379 | } 380 | case "GUIText" -> { 381 | if (event.isLeftClick()) { 382 | player.closeInventory(); 383 | TextDisplay textDisplay = (TextDisplay) entity; 384 | 385 | if (DisplayEntityEditor.alternateTextInput) { 386 | if (DisplayEntityEditor.useMiniMessageFormat) { 387 | player.spigot().sendMessage(Utilities.getCommandMessage("text ", DisplayEntityEditor.messageManager.getString("text_command_hint_mm"))); 388 | player.spigot().sendMessage(Utilities.getClipboardMessage("text_clipboard_hint", textDisplay.getText())); 389 | } else { 390 | player.spigot().sendMessage(Utilities.getCommandMessage("text ", DisplayEntityEditor.messageManager.getString("text_command_hint"))); 391 | player.spigot().sendMessage(Utilities.getClipboardMessage("text_clipboard_hint", textDisplay.getText())); 392 | } 393 | } else { 394 | if (DisplayEntityEditor.useMiniMessageFormat) { 395 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("text_hint_mm"), new InputData(entity, InputType.TEXT, null)); 396 | player.spigot().sendMessage(Utilities.getClipboardMessage("text_clipboard_hint", textDisplay.getText())); 397 | } else { 398 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("text_hint"), new InputData(entity, InputType.TEXT, null)); 399 | player.spigot().sendMessage(Utilities.getClipboardMessage("text_clipboard_hint", textDisplay.getText())); 400 | } 401 | } 402 | } 403 | if (event.isRightClick()) { 404 | player.closeInventory(); 405 | 406 | if (DisplayEntityEditor.alternateTextInput) { 407 | if (DisplayEntityEditor.useMiniMessageFormat) { 408 | player.spigot().sendMessage(Utilities.getCommandMessage("text_append ", DisplayEntityEditor.messageManager.getString("text_command_hint_mm"))); 409 | } else { 410 | player.spigot().sendMessage(Utilities.getCommandMessage("text_append ", DisplayEntityEditor.messageManager.getString("text_command_hint"))); 411 | } 412 | } else { 413 | if (DisplayEntityEditor.useMiniMessageFormat) { 414 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("text_append_hint_mm"), new InputData(entity, InputType.TEXT_APPEND, null)); 415 | } else { 416 | InputManager.createTextInput(player, DisplayEntityEditor.messageManager.getString("text_append_hint"), new InputData(entity, InputType.TEXT_APPEND, null)); 417 | } 418 | } 419 | } 420 | } 421 | } 422 | } 423 | } 424 | } 425 | if (player.getOpenInventory().getTitle().equals(ChatColor.translateAlternateColorCodes('&' ,DisplayEntityEditor.messageManager.getString("block_display_gui_name")))) { 426 | 427 | assert entity instanceof BlockDisplay; 428 | BlockDisplay blockDisplay = (BlockDisplay) entity; 429 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> { 430 | ItemStack itemStack = player.getOpenInventory().getItem(10); 431 | if (itemStack != null) { 432 | if (itemStack.getType().isBlock()) { 433 | BlockData data = Bukkit.createBlockData(itemStack.getType()); 434 | blockDisplay.setBlock(data); 435 | } else { 436 | BlockData data = Bukkit.createBlockData(Material.AIR); 437 | blockDisplay.setBlock(data); 438 | player.sendMessage(Utilities.getErrorMessageFormat(DisplayEntityEditor.messageManager.getString("block_invalid_hint"))); 439 | player.getOpenInventory().setItem(10, null); 440 | } 441 | } else { 442 | blockDisplay.setBlock(Bukkit.createBlockData(Material.AIR)); 443 | } 444 | }); 445 | 446 | 447 | } else if (player.getOpenInventory().getTitle().equals(ChatColor.translateAlternateColorCodes('&' ,DisplayEntityEditor.messageManager.getString("item_display_gui_name")))) { 448 | ItemDisplay itemDisplay = (ItemDisplay) entity; 449 | Bukkit.getScheduler().scheduleSyncDelayedTask(DisplayEntityEditor.getPlugin(), () -> itemDisplay.setItemStack(player.getOpenInventory().getItem(10)),1L); 450 | } 451 | } 452 | } 453 | } 454 | --------------------------------------------------------------------------------