I am currently developing a minecraft plugin that contains many items with many placeholders.
I have a method that has two parameters: an ItemStack and an array of Strings.
in the array, on the odd positions are the variables, and on the even positions are the values with which they must be replaced.
I would like to know what is the most efficient method to replace those variables.
My code:
public static ItemStack replace(ItemStack item, String... placeholders) {
ItemMeta meta = item.getItemMeta();
List<String> lore1 = meta.getLore();
String lore = serializeLore(lore1);
String name = meta.getDisplayName();
for(int i = 0; i < placeholders.length; i+=2) {
lore = lore.replace((String)placeholders[i], (String)placeholders[i + 1]);
name = name.replace((String)placeholders[i], (String)placeholders[i + 1]);
}
meta.setLore(Arrays.asList(lore.split("\n")));
meta.setDisplayName(name);
item.setItemMeta(meta);
return item;
}
private static String serializeLore(List<String> lore) {
String result = "";
for(int i = 0; i < lore.size(); i++) {
result += lore.get(i) + (i + 1 < lore.size() ? "\n" : "");
}
return result;
}
For example:
replace(item, "%player%", "John", "%coins%", "2000", "%score%", "80");
Edit: A example of item lore:
"&7Welcome Back &a%player%!"
""
"&7Crazy fun minigames to play with friends:"
"&f - %minigame1%"
"&f - %minigame2%"
"&f - %minigame3%"
"&f - %minigame4%"
"&f - %minigame5%"
"&f - %minigame6%"
"&f - %minigame7%"
"&f - %minigame8%"
""
"&7Coins: &6%coins%"
"&7Score: &2%score%"
"&7Games Played: &9%gamesPlayed%"
""
"&aClick to play!"
"&7%currentPlaying% Currently playing!"
I think the performance could be improved by reducing the number calls to replace. I thought it would be faster to loop through the lore, find each replacement site in each lore by finding strings surrounded by % characters, use that key to look up the display value (placeholders could be a Dictionary instead of array of even/odd pairs), then use a more performant StringBuilder to do your string modifications.
Consider the following pseudo-code:
public static ItemStack replace(ItemStack item, Dictionary<String, String> placeholders) {
ItemMeta meta = item.getItemMeta();
String lore = String.join("\n", meta.getLore();
String name = meta.getDisplayName();
String modifiedLore = fillInReplacementValues(lore, placeholders);
String modifiedName = fillInReplacementValues(name, placeholders);
meta.setLore(modifiedLore.split('\n');
meta.setDisplayName(name);
item.setItemMeta(meta);
return item;
}
public static String fillInReplacementValues(String stringToModify, Dictionary<String, String> placeholders) {
StringBuilder stringBuilder = new StringBuilder(stringToModify);
String replacementMarker = "%";
Boolean replacementMarkerFound = false;
int replacementEndIndex = 0;
// Start from the end of the lore string and look back
for(int i = stringBuilder.length() - 1; i >= 0; i--) {
// Did we find a marker end?
if (replacementMarker == stringBuilder.charAt(i)) {
if (replacementMarkerFound) {
// We found the start and end indexes of %
// Pull the name of the key field (coin, player etc)
String replacementName = stringBuilder.substring(i + 1, replacementEndIndex - 1);
// replace the placeholder with value (ie %coin% with 1000)
stringBuilder.replace(i, replacementEndIndex, placeholders[replacementName]);
replacementMarkerFound = false;
} else {
replacementMarkerFound = true;
replacementEndIndex = i;
}
}
}
return stringBuilder.toString();
}