Skip to content

Instantly share code, notes, and snippets.

@aikar
Created March 30, 2019 04:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aikar/766d5c3ac4afcdfdf60588da912b7747 to your computer and use it in GitHub Desktop.
Save aikar/766d5c3ac4afcdfdf60588da912b7747 to your computer and use it in GitHub Desktop.
/*
* Copyright (c) 2016. Starlis LLC / dba Empire Minecraft
*
* This source code is proprietary software and must not be redistributed without Starlis LLC's approval
*
*/
package com.empireminecraft.util;
import com.empireminecraft.api.meta.Meta;
import com.empireminecraft.api.meta.MetaKey.PersistentKey;
import com.empireminecraft.config.meta.ItemKeys;
import com.empireminecraft.features.items.FinalItems;
import com.empireminecraft.features.items.FragileItems;
import com.empireminecraft.features.items.GamesItems;
import com.empireminecraft.features.items.SoulboundItems;
import com.empireminecraft.features.items.TemporaryItems;
import com.empireminecraft.features.items.UnbreakableItems;
import com.empireminecraft.features.items.UnplaceableItem;
import com.empireminecraft.features.items.WearableItems;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class LoreBuilder {
private static final int LOREMETA_INDEX = 30;
private static final String LOREMETA_TAG = "&&::META";
private final ItemStack item;
private final ItemMeta meta;
private final List<String> lore;
private int index = 0;
/**
* Initiates a builder and sets the index to the first empty line after the lore
*
* @param item
*/
public LoreBuilder(@NotNull ItemStack item) {
if (item.getType() == Material.AIR || !item.getType().isItem()) {
throw new IllegalArgumentException("Can not pass AIR/Non-item types to LoreBuilder");
}
this.item = item;
this.meta = item.getItemMeta();
if (item.hasItemMeta() && meta.hasLore()) {
this.lore = meta.getLore();
} else {
this.lore = new ArrayList<>();
}
if (lore.size() <= LOREMETA_INDEX - 2) {
index = lore.size();
} else {
for (int i = LOREMETA_INDEX - 2; i >= 0; i--) {
if (!lore.get(i).isEmpty()) {
index = i + 1;
break;
}
}
}
}
public Map<String, String> getMeta() {
Map<String, String> meta = new HashMap<>();
if (LOREMETA_INDEX + 1 < lore.size()) {
for (int i = LOREMETA_INDEX + 1; i + 1 < lore.size(); i += 2) {
String key = lore.get(i);
String val = lore.get(i + 1);
meta.put(key, val);
}
}
return meta;
}
/**
* Clears all lore on this item, preserving metadata.
*
* @return
*/
public LoreBuilder clear() {
index = 0;
if (lore.size() <= LOREMETA_INDEX) {
lore.clear();
} else {
for (int i = 0; i < LOREMETA_INDEX; i++) {
lore.set(i, "");
}
}
return this;
}
/**
* Clears all metadata on this item, preserving lore.
*
* @return
*/
public LoreBuilder clearMeta() {
if (lore.size() > LOREMETA_INDEX) {
for (int i = LOREMETA_INDEX; i < lore.size(); i++) {
lore.set(i, "");
}
for (int i = lore.size() - 1; i >= 0; i--) {
if (lore.get(i).isEmpty()) {
lore.remove(i);
} else {
break;
}
}
}
return this;
}
public LoreBuilder setName(String name) {
meta.setDisplayName(Util.color(name));
return this;
}
public ItemStack getItemStack() {
return item;
}
public LoreBuilder makeShiny(boolean shiny) {
if (shiny) {
makeShiny();
}
return this;
}
public LoreBuilder makeShiny() {
ensure(LOREMETA_INDEX - 1);
lore.set(LOREMETA_INDEX - 1, "&&::SHINY");
return this;
}
public LoreBuilder makeWearable() {
int oldindex = index;
WearableItems.makeWearable(this);
index = oldindex + 1;
return this;
}
public LoreBuilder makeSoulbound() {
int oldindex = index;
SoulboundItems.makeSoulbound(this);
index = oldindex + 1;
return this;
}
public LoreBuilder makeFinal() {
int oldindex = index;
FinalItems.makeFinal(this);
index = oldindex + 1;
return this;
}
public LoreBuilder makeFragile() {
int oldindex = index;
FragileItems.makeFragile(this);
index = oldindex + 1;
return this;
}
public LoreBuilder makeUnplaceable() {
int oldindex = index;
UnplaceableItem.makeUnplaceable(this);
index = oldindex + 1;
return this;
}
public LoreBuilder makeUnbreakable() {
int oldindex = index;
UnbreakableItems.makeUnbreakable(this);
index = oldindex + 1;
return this;
}
public LoreBuilder makeTemporary() {
makeTemporary(0);
return this;
}
public LoreBuilder makeTemporary(int timeLimit) {
int oldindex = index;
TemporaryItems.makeTemporary(this, timeLimit);
index = oldindex + 1;
return this;
}
public LoreBuilder makeGamesItem() {
int oldindex = index;
GamesItems.makeGamesItem(this);
index = oldindex + 1;
return this;
}
public LoreBuilder makeUnclaimable() {
return this.setFlag(ItemKeys.UNCLAIMABLE);
}
public boolean hasFlag(PersistentKey key) {
return getIntMeta(key, 0) != 0;
}
public LoreBuilder setFlag(PersistentKey flag) {
return this.setMeta(flag, "1");
}
public int getRepairCost(HumanEntity entity) {
String cost = getMeta(Meta.createPersistentKey("RepairCost_" + entity.getUniqueId()));
return Util.parseInt(cost, 0);
}
public LoreBuilder setRepairCost(HumanEntity entity, int cost) {
setMeta(Meta.createPersistentKey("RepairCost_" + entity.getUniqueId()), cost == 0 ? null : String.valueOf(cost));
return this;
}
/**
* Changes the current index
*
* @param i
* @return
*/
public LoreBuilder index(int i) {
index = i;
return this;
}
/**
* Shifts to the previous index
*
* @return
*/
public LoreBuilder prev() {
index--;
return this;
}
/**
* Shifts to the next index
*
* @return
*/
public LoreBuilder next() {
index++;
return this;
}
/**
* Sets the current index to an empty line
*
* @return
*/
public LoreBuilder empty() {
return add(index, "");
}
/**
* Inserts a line of lore after the last used index, shifting up any following lines if they existed.
*
* @param line
* @return
*/
public LoreBuilder add(String line) {
return add(index, line);
}
/**
* Inserts the specified line at the index. If the line was already set, it will be shifted up 1.
*
* @param i
* @param line
* @return
*/
public LoreBuilder add(int i, String line) {
if (line == null) {
return this;
}
ensure(i - 1);
String lastColor = "";
for (String splitLine : Patterns.NEWLINE.split(Util.color(line))) {
splitLine = lastColor + splitLine;
lore.add(i, splitLine);
lastColor = ChatColor.getLastColors(splitLine);
index = ++i;
}
while (lore.size() > LOREMETA_INDEX && !lore.get(LOREMETA_INDEX).equals(LOREMETA_TAG)) {
lore.remove(LOREMETA_INDEX - 10);
}
return this;
}
/**
* Sets the line at the specified index, replacing it if already there.
*
* @param i
* @param line
* @return
*/
public LoreBuilder set(int i, String line) {
ensure(i);
lore.set(i, Util.color(line));
index = i + 1;
return this;
}
/**
* Stores meta data about this item in hidden lore fields
*
* @param key
* @param line
* @return
*/
public LoreBuilder setMeta(PersistentKey key, String line) {
return setMeta(key.key(), line);
}
public LoreBuilder setMeta(PersistentKey key, UUID line) {
return setMeta(key.key(), line.toString());
}
public LoreBuilder setMeta(PersistentKey key, Number line) {
return setMeta(key.key(), String.valueOf(line));
}
/**
* @deprecated You should use PMeta Keys
*/
@Deprecated
private LoreBuilder setMeta(String key, String line) {
ensure(LOREMETA_INDEX);
lore.set(LOREMETA_INDEX, LOREMETA_TAG);
for (int i = LOREMETA_INDEX + 1; i < lore.size(); i += 2) {
if (lore.get(i).equalsIgnoreCase(key)) {
if (i + 1 == lore.size()) { // Broken meta...
if (line == null) {
lore.remove(i);
} else {
lore.add(i + 1, line);
}
} else {
if (line == null) {
lore.remove(i+1);
lore.remove(i);
} else {
lore.set(i + 1, line);
}
}
return this;
}
}
// Add new
lore.add(key);
lore.add(line);
return this;
}
/**
* Gets the specified meta value out of the items lore, defaulting to null
*
* @param key
* @return
*/
public String getMeta(PersistentKey key) {
return getMeta(key.key(), null);
}
/**
* Gets the specified meta value out of the items lore, with supplied default
*
* @param key
* @param def
* @return
*/
public String getMeta(PersistentKey key, String def) {
return getMeta(key.key(), def);
}
/**
* @deprecated You should use PMeta Keys
*/
@Deprecated
private String getMeta(String key, String def) {
if (LOREMETA_INDEX + 1 < lore.size()) {
for (int i = LOREMETA_INDEX + 1; i + 1 < lore.size(); i += 2) {
if (lore.get(i).equalsIgnoreCase(key)) {
return lore.get(i + 1);
}
}
}
return def;
}
public Integer getIntMeta(PersistentKey key) {
return getIntMeta(key, null);
}
public Integer getIntMeta(PersistentKey key, Integer def) {
String meta = getMeta(key);
if (meta == null) {
return def;
}
return Util.parseInt(meta, def);
}
public Long getLongMeta(PersistentKey key) {
return getLongMeta(key, null);
}
public Long getLongMeta(PersistentKey key, Long def) {
String meta = getMeta(key);
if (meta == null) {
return def;
}
return Util.parseLong(meta, def);
}
public boolean hasMeta(PersistentKey key) {
return getMeta(key) != null;
}
/**
* @param idx
*/
private void ensure(int idx) {
// empty lines if they are not set.
for (int i = lore.size(); i <= idx; i++) {
lore.add(i, "");
}
}
public ItemStack save() {
meta.setLore(lore);
item.setItemMeta(meta);
return item;
}
public LoreBuilder enchant(Enchantment enchantment, int level) {
meta.addEnchant(enchantment, level, true);
return this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment