Solved Find a specific lore line

Discussion in 'Spigot Plugin Development' started by MasterWolfx, Apr 2, 2020.

  1. Hi guys, im making a plugin that keeps track of the level of an item.
    Every upgraded item, has his level stored in a lore line, like this:
    "Power: +2"

    The upgrade-level string can be modified in the config.yml, like this:
    power-lore-line: "Power: +{level}"

    I need to find the power-lore-line to change the level every time the item gets upgraded.
    Any ideas on how can i do that?
  2. Code (Java):
    List<String> stringList = item.getLore();
    for (String element: stringList) {
        if (element.startsWith("Power: +")) {
            System.out.println("element found: " + element);
            System.out.println("level: " + Integer.parseInt(element.substring("Power: +".length())));
    Note that I would consider this to be a somewhat bad solution since the String has to be hardcoded. If you want to do any change to your format (for example, add another line after the level-integer, add support for multiple languages), you should consider another approach. Namely, you should look into the PersistentDataHolder-API to store your power-level. The lore should only be "cosmetic" in the sense that it should display the level, but you shouldn't rely on it.
    • Creative Creative x 1
  3. The level is saved inside an NBT Tag, so the logic part works perfectly. The only prolem is to display on the lore the right level. You think it is better to store level inside PersistentDataHolder-API.
  4. Anyway if the user changes the lore line to:
    power-lore-line: "[{level}]"

    How can i find the lore line?
  5. Oh, I misunderstood your question. Well, just apply the method I presented. Loop over the entries of the lore and search for the entry that starts with "Power: +".
    Also, you should switch to the PersistentDataHolder-API since it's independent from version changes and does not rely on external API's
  6. If you want to be 100% sure that it's your line, you could get the configured line and split it by your defined placeholder, in your case {level}.
    Then, check if the lore line starts with the first index of the split array and if the array is longer than 1 index, check if it ends with the second index of the split array.

    Pseudo code:
    Code (Text):
    String[] split = getConfiguredLine().split("\\{level}");
    for each lore line
      if line starts with split[0] and (split shorter than 2 or line ends with split[1])
        //do what you need to do
  7. yes but i cant split {level}, because inside the lore there is the real level (1,2,3,4,5...), so there is the number and not the placeholder.
  8. Use
    Code (Java):
    Note that you can't replace the 9 by a value higher than 9 (due to the properties of regexes). In order to do that, you'd need to change the regex to
    Code (Text):
    and so forth for more than 2 digits.
  9. I dont understand that, what should that thing do?
    #9 MasterWolfx, Apr 2, 2020
    Last edited: Apr 2, 2020
  10. That just splits at any number inside the String. If your string consists of only one number, it will split right there
  11. If you're using a regular expression to split the string, you should consider instead just matching the line. Since you know level is a number, you can replace "{level}" with "[0-9]+"
    However, if users use special characters, this can cause issues. To circumvent this, you can escape the rest:
    Code (Java):
    String lorePattern = // configured string
    lorePattern = "\\Q" + lorePattern + "\\E"; // Quote entire string for regex
    lorePattern = lorePattern.replace("{level}", "\\E[0-9]+\\Q"); // Replace {level} with end quote, accept any number, and then quote
    Pattern pattern = Pattern.compile(lorePattern);
    Then check each line against your compiled pattern until you find a match.
    • Like Like x 1
    • Informative Informative x 1
  12. That's why I told you to split the configured line by the placeholder, and check that against the actual line on the item.
    But Jikoo's approach is smarter, you should go with that.
  13. I dont understand your solution. Can you give me an example using that code?
  14. Which part do you not understand? I feel like I commented the regex assembly pretty well. You then apply it in your loop like any other pattern - get a Matcher for the string (the line of lore) and check if it matches.

    Edit: in case you're just unclear on Patterns and Matchers in general,
  15. Im not very familiar with regex but it works perfectly, thank you so much man!