v3.6.4
This commit is contained in:
parent
daa3e40c65
commit
9d7c98cddb
@ -108,6 +108,7 @@ public class ExcellentEnchants extends NexPlugin<ExcellentEnchants> {
|
||||
public void loadLang() {
|
||||
this.getLangManager().loadMissing(Lang.class);
|
||||
this.getLangManager().loadEnum(FitItemType.class);
|
||||
this.getLangManager().loadEnum(ObtainType.class);
|
||||
this.getLang().saveChanges();
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ public class Placeholders extends su.nexmedia.engine.utils.Placeholders {
|
||||
public static final String URL_ENGINE_ITEMS = "https://github.com/nulli0n/NexEngine-spigot/wiki/Configuration-Tips#item-sections";
|
||||
|
||||
public static final String GENERIC_TYPE = "%type%";
|
||||
public static final String GENERIC_NAME = "%name%";
|
||||
public static final String GENERIC_ITEM = "%item%";
|
||||
public static final String GENERIC_LEVEL = "%level%";
|
||||
public static final String GENERIC_AMOUNT = "%amount%";
|
||||
|
@ -9,7 +9,6 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import su.nexmedia.engine.api.command.AbstractCommand;
|
||||
import su.nexmedia.engine.api.command.CommandResult;
|
||||
import su.nexmedia.engine.lang.LangManager;
|
||||
import su.nexmedia.engine.utils.*;
|
||||
import su.nexmedia.engine.utils.random.Rnd;
|
||||
import su.nightexpress.excellentenchants.ExcellentEnchants;
|
||||
@ -90,7 +89,7 @@ public class EnchantCommand extends AbstractCommand<ExcellentEnchants> {
|
||||
plugin.getMessage(sender == player ? Lang.COMMAND_ENCHANT_DONE_SELF : Lang.COMMAND_ENCHANT_DONE_OTHERS)
|
||||
.replace(Placeholders.forPlayer(player))
|
||||
.replace(Placeholders.GENERIC_ITEM, ItemUtil.getItemName(item))
|
||||
.replace(Placeholders.GENERIC_ENCHANT, LangManager.getEnchantment(enchantment))
|
||||
.replace(Placeholders.GENERIC_ENCHANT, EnchantUtils.getLocalized(enchantment))
|
||||
.replace(Placeholders.GENERIC_LEVEL, NumberUtil.toRoman(level))
|
||||
.send(sender);
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ import java.util.stream.Stream;
|
||||
|
||||
public class Config {
|
||||
|
||||
public static final String DIR_MENU = "/menu/";
|
||||
|
||||
public static final JOption<Long> TASKS_ARROW_TRAIL_TICKS_INTERVAL = JOption.create("Tasks.Arrow_Trail.Tick_Interval",
|
||||
1L,
|
||||
"Sets how often (in ticks) arrow trail particle effects will be spawned behind the arrow."
|
||||
|
@ -69,10 +69,7 @@ public class EnchantPopulator {
|
||||
Set<ExcellentEnchant> enchants = EnchantRegistry.getOfTier(tier);
|
||||
|
||||
enchants.removeIf(enchant -> {
|
||||
if (enchant.getObtainChance(this.getObtainType()) <= 0D) return true;
|
||||
if (!enchant.canEnchantItem(this.getItem())) return true;
|
||||
|
||||
return this.getObtainType() == ObtainType.ENCHANTING && (enchant.isTreasure() || enchant.isCursed());
|
||||
return !enchant.isObtainable(this.getObtainType()) || !enchant.canEnchantItem(this.getItem());
|
||||
});
|
||||
|
||||
this.candidates.put(tier, enchants);
|
||||
|
@ -195,6 +195,13 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
|
||||
return description;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> formatDescription() {
|
||||
return new ArrayList<>(this.getDescription().stream()
|
||||
.map(line -> Config.ENCHANTMENTS_DESCRIPTION_FORMAT.get().replace(Placeholders.GENERIC_DESCRIPTION, line))
|
||||
.toList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> formatDescription(int level) {
|
||||
return new ArrayList<>(this.getDescription(level).stream()
|
||||
@ -202,6 +209,10 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
|
||||
.toList());
|
||||
}
|
||||
|
||||
public boolean hasConflicts() {
|
||||
return !this.getConflicts().isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<String> getConflicts() {
|
||||
return this.getDefaults().getConflicts();
|
||||
@ -234,6 +245,12 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
|
||||
return get != 0 ? this.fineLevel(get, ObtainType.ENCHANTING) : 0;
|
||||
}
|
||||
|
||||
public boolean isObtainable(@NotNull ObtainType obtainType) {
|
||||
if (obtainType == ObtainType.ENCHANTING && (this.isTreasure() || this.isCursed())) return false;
|
||||
|
||||
return this.getObtainChance(obtainType) > 0D;
|
||||
}
|
||||
|
||||
public double getObtainChance(@NotNull ObtainType obtainType) {
|
||||
return this.getDefaults().getObtainChance().getOrDefault(obtainType, 0D);
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package su.nightexpress.excellentenchants.enchantment.menu;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import su.nexmedia.engine.api.config.JOption;
|
||||
import su.nexmedia.engine.api.config.JYML;
|
||||
import su.nexmedia.engine.api.menu.AutoPaged;
|
||||
import su.nexmedia.engine.api.menu.MenuItemType;
|
||||
@ -12,49 +15,50 @@ import su.nexmedia.engine.api.menu.click.ItemClick;
|
||||
import su.nexmedia.engine.api.menu.impl.ConfigMenu;
|
||||
import su.nexmedia.engine.api.menu.impl.MenuOptions;
|
||||
import su.nexmedia.engine.api.menu.impl.MenuViewer;
|
||||
import su.nexmedia.engine.api.menu.item.MenuItem;
|
||||
import su.nexmedia.engine.utils.Colorizer;
|
||||
import su.nexmedia.engine.utils.ItemReplacer;
|
||||
import su.nexmedia.engine.utils.ItemUtil;
|
||||
import su.nexmedia.engine.utils.PDCUtil;
|
||||
import su.nexmedia.engine.utils.StringUtil;
|
||||
import su.nightexpress.excellentenchants.ExcellentEnchants;
|
||||
import su.nightexpress.excellentenchants.Placeholders;
|
||||
import su.nightexpress.excellentenchants.config.Config;
|
||||
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
|
||||
import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry;
|
||||
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;
|
||||
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static su.nexmedia.engine.utils.Colors2.*;
|
||||
import static su.nightexpress.excellentenchants.Placeholders.*;
|
||||
|
||||
public class EnchantmentsListMenu extends ConfigMenu<ExcellentEnchants> implements AutoPaged<ExcellentEnchant> {
|
||||
|
||||
private static final String PATH = "/menu/enchants_list.yml";
|
||||
private static final String FILE = "enchants.yml";
|
||||
|
||||
private static final String PLACEHOLDER_CONFLICTS = "%conflicts%";
|
||||
private static final String PLACEHOLDER_CHARGES = "%charges%";
|
||||
private static final String PLACEHOLDER_OBTAINING = "%obtaining%";
|
||||
|
||||
private final ItemStack enchantIcon;
|
||||
private final List<String> enchantLoreConflicts;
|
||||
private final List<String> enchantLoreCharges;
|
||||
private final List<String> enchantLoreObtaining;
|
||||
private final int[] enchantSlots;
|
||||
|
||||
private final NamespacedKey keyLevel;
|
||||
private final Map<String, Map<Integer, ItemStack>> iconCache;
|
||||
|
||||
private String enchantName;
|
||||
private List<String> enchantLoreMain;
|
||||
private List<String> enchantLoreConflicts;
|
||||
private List<String> enchantLoreCharges;
|
||||
private List<String> enchantLoreObtaining;
|
||||
private int[] enchantSlots;
|
||||
|
||||
public EnchantmentsListMenu(@NotNull ExcellentEnchants plugin) {
|
||||
super(plugin, JYML.loadOrExtract(plugin, PATH));
|
||||
super(plugin, new JYML(plugin.getDataFolder() + Config.DIR_MENU, FILE));
|
||||
this.keyLevel = new NamespacedKey(plugin, "list_display_level");
|
||||
this.iconCache = new HashMap<>();
|
||||
|
||||
this.enchantIcon = cfg.getItem("Enchantments.Icon");
|
||||
this.enchantLoreConflicts = Colorizer.apply(cfg.getStringList("Enchantments.Lore.Conflicts"));
|
||||
this.enchantLoreCharges = Colorizer.apply(cfg.getStringList("Enchantments.Lore.Charges"));
|
||||
this.enchantLoreObtaining = Colorizer.apply(cfg.getStringList("Enchantments.Lore.Obtaining"));
|
||||
this.enchantSlots = cfg.getIntArray("Enchantments.Slots");
|
||||
|
||||
this.registerHandler(MenuItemType.class)
|
||||
.addClick(MenuItemType.CLOSE, (viewer, event) -> plugin.runTask(task -> viewer.getPlayer().closeInventory()))
|
||||
.addClick(MenuItemType.CLOSE, ClickHandler.forClose(this))
|
||||
.addClick(MenuItemType.PAGE_NEXT, ClickHandler.forNextPage(this))
|
||||
.addClick(MenuItemType.PAGE_PREVIOUS, ClickHandler.forPreviousPage(this));
|
||||
|
||||
@ -67,6 +71,85 @@ public class EnchantmentsListMenu extends ConfigMenu<ExcellentEnchants> implemen
|
||||
this.iconCache.clear();
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
@Override
|
||||
public boolean isCodeCreation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional() {
|
||||
this.enchantName = JOption.create("Enchantment.Name", ENCHANTMENT_NAME_FORMATTED).read(cfg);
|
||||
|
||||
this.enchantLoreMain = JOption.create("Enchantment.Lore.Main",
|
||||
Arrays.asList(
|
||||
ENCHANTMENT_DESCRIPTION,
|
||||
DARK_GRAY + "(click to switch level)",
|
||||
"",
|
||||
LIGHT_YELLOW + BOLD + "Info:",
|
||||
LIGHT_YELLOW + "▪ " + LIGHT_GRAY + "Tier: " + LIGHT_YELLOW + ENCHANTMENT_TIER,
|
||||
LIGHT_YELLOW + "▪ " + LIGHT_GRAY + "Applies to: " + LIGHT_YELLOW + ENCHANTMENT_FIT_ITEM_TYPES,
|
||||
LIGHT_YELLOW + "▪ " + LIGHT_GRAY + "Levels: " + LIGHT_YELLOW + ENCHANTMENT_LEVEL_MIN + GRAY + " - " + LIGHT_YELLOW + ENCHANTMENT_LEVEL_MAX,
|
||||
PLACEHOLDER_CHARGES,
|
||||
PLACEHOLDER_CONFLICTS,
|
||||
PLACEHOLDER_OBTAINING
|
||||
)).read(cfg);
|
||||
|
||||
this.enchantLoreConflicts = JOption.create("Enchantment.Lore.Conflicts",
|
||||
Arrays.asList(
|
||||
"",
|
||||
LIGHT_RED + BOLD + "Conflicts:",
|
||||
LIGHT_RED + "✘ " + LIGHT_GRAY + GENERIC_NAME
|
||||
)).read(cfg);
|
||||
|
||||
this.enchantLoreCharges = JOption.create("Enchantment.Lore.Charges",
|
||||
Arrays.asList(
|
||||
LIGHT_YELLOW + "▪ " + LIGHT_GRAY + "Charges: " + LIGHT_YELLOW + ENCHANTMENT_CHARGES_MAX_AMOUNT + "⚡" + LIGHT_GRAY + " (" + WHITE + ENCHANTMENT_CHARGES_FUEL_ITEM + LIGHT_GRAY + ")"
|
||||
)).read(cfg);
|
||||
|
||||
this.enchantLoreObtaining = JOption.create("Enchantment.Lore.Obtaining",
|
||||
Arrays.asList(
|
||||
"",
|
||||
LIGHT_GREEN + BOLD + "Obtaining:",
|
||||
LIGHT_GREEN + "✔ " + LIGHT_GRAY + GENERIC_TYPE
|
||||
)).read(cfg);
|
||||
|
||||
this.enchantSlots = new JOption<int[]>("Enchantment.Slots",
|
||||
(cfg, path, def) -> cfg.getIntArray(path),
|
||||
() -> IntStream.range(0, 27).toArray()
|
||||
).setWriter(JYML::setIntArray).read(cfg);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected MenuOptions createDefaultOptions() {
|
||||
return new MenuOptions(DARK_GRAY + BOLD + "Custom Enchants", 36, InventoryType.CHEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected List<MenuItem> createDefaultItems() {
|
||||
List<MenuItem> list = new ArrayList<>();
|
||||
|
||||
ItemStack nextPageStack = ItemUtil.createCustomHead("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMyY2E2NjA1NmI3Mjg2M2U5OGY3ZjMyYmQ3ZDk0YzdhMGQ3OTZhZjY5MWM5YWMzYTkxMzYzMzEzNTIyODhmOSJ9fX0=");
|
||||
ItemUtil.mapMeta(nextPageStack, meta -> {
|
||||
meta.setDisplayName(WHITE + "Next Page" + LIGHT_GRAY + " (→)");
|
||||
});
|
||||
|
||||
ItemStack prevPageStack = ItemUtil.createCustomHead("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY5NzFkZDg4MWRiYWY0ZmQ2YmNhYTkzNjE0NDkzYzYxMmY4Njk2NDFlZDU5ZDFjOTM2M2EzNjY2YTVmYTYifX19");
|
||||
ItemUtil.mapMeta(prevPageStack, meta -> {
|
||||
meta.setDisplayName(LIGHT_GRAY + "(←) " + WHITE + "Previous Page");
|
||||
});
|
||||
|
||||
list.add(new MenuItem(nextPageStack).setSlots(35).setType(MenuItemType.PAGE_NEXT).setPriority(5));
|
||||
list.add(new MenuItem(prevPageStack).setSlots(27).setType(MenuItemType.PAGE_PREVIOUS).setPriority(5));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
// -----------
|
||||
|
||||
@Override
|
||||
public void onPrepare(@NotNull MenuViewer viewer, @NotNull MenuOptions options) {
|
||||
super.onPrepare(viewer, options);
|
||||
@ -118,26 +201,42 @@ public class EnchantmentsListMenu extends ConfigMenu<ExcellentEnchants> implemen
|
||||
|
||||
@NotNull
|
||||
private ItemStack buildEnchantIcon(@NotNull ExcellentEnchant enchant, int level) {
|
||||
ItemStack icon = new ItemStack(this.enchantIcon);
|
||||
ItemUtil.mapMeta(icon, meta -> {
|
||||
List<String> lore = meta.getLore();
|
||||
if (lore == null) lore = new ArrayList<>();
|
||||
ItemStack icon = new ItemStack(Material.ENCHANTED_BOOK);
|
||||
|
||||
List<String> conflicts = enchant.getConflicts().isEmpty() ? Collections.emptyList() : new ArrayList<>(this.enchantLoreConflicts);
|
||||
List<String> conflictNames = enchant.getConflicts().stream().map(EnchantUtils::getLocalized).filter(Objects::nonNull).toList();
|
||||
conflicts = StringUtil.replace(conflicts, Placeholders.ENCHANTMENT_NAME, true, conflictNames);
|
||||
List<String> conflicts = new ArrayList<>();
|
||||
if (enchant.hasConflicts()) {
|
||||
for (String line : this.enchantLoreConflicts) {
|
||||
if (line.contains(GENERIC_NAME)) {
|
||||
enchant.getConflicts().stream().map(EnchantUtils::getLocalized).filter(Objects::nonNull).forEach(conf -> {
|
||||
conflicts.add(line.replace(GENERIC_NAME, conf));
|
||||
});
|
||||
}
|
||||
else conflicts.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> charges = enchant.isChargesEnabled() ? new ArrayList<>(this.enchantLoreCharges) : Collections.emptyList();
|
||||
List<String> obtaining = new ArrayList<>(this.enchantLoreObtaining);
|
||||
List<String> obtaining = new ArrayList<>();
|
||||
for (String line : this.enchantLoreObtaining) {
|
||||
if (line.contains(GENERIC_TYPE)) {
|
||||
for (ObtainType obtainType : ObtainType.values()) {
|
||||
if (enchant.isObtainable(obtainType)) {
|
||||
obtaining.add(line.replace(GENERIC_TYPE, plugin.getLangManager().getEnum(obtainType)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else obtaining.add(line);
|
||||
}
|
||||
|
||||
lore = StringUtil.replaceInList(lore, PLACEHOLDER_CONFLICTS, conflicts);
|
||||
lore = StringUtil.replaceInList(lore, PLACEHOLDER_CHARGES, charges);
|
||||
lore = StringUtil.replaceInList(lore, PLACEHOLDER_OBTAINING, obtaining);
|
||||
lore = StringUtil.replace(lore, Placeholders.ENCHANTMENT_DESCRIPTION, true, enchant.getDescription());
|
||||
|
||||
meta.setLore(lore);
|
||||
ItemUtil.replace(meta, enchant.getPlaceholders(level).replacer());
|
||||
});
|
||||
ItemReplacer.create(icon).hideFlags().trimmed()
|
||||
.setDisplayName(this.enchantName)
|
||||
.setLore(this.enchantLoreMain)
|
||||
.replaceLoreExact(PLACEHOLDER_CHARGES, enchant.isChargesEnabled() ? new ArrayList<>(this.enchantLoreCharges) : Collections.emptyList())
|
||||
.replaceLoreExact(PLACEHOLDER_CONFLICTS, conflicts)
|
||||
.replaceLoreExact(PLACEHOLDER_OBTAINING, obtaining)
|
||||
.replaceLoreExact(ENCHANTMENT_DESCRIPTION, enchant.formatDescription())
|
||||
.replace(enchant.getPlaceholders(level))
|
||||
.replace(Colorizer::apply)
|
||||
.writeMeta();
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
@ -1,72 +0,0 @@
|
||||
Title: ' #a267f3&lCustom Enchants'
|
||||
Size: 36
|
||||
Inventory_Type: CHEST
|
||||
Use_Mini_Message: false
|
||||
|
||||
Enchantments:
|
||||
Icon:
|
||||
Material: ENCHANTED_BOOK
|
||||
Name: '%enchantment_name_formatted%'
|
||||
Lore:
|
||||
- '#aeb6bf%enchantment_description%'
|
||||
- ''
|
||||
- '#bcff9a&lInfo:'
|
||||
- '#bcff9a▪ #ddeceeTier: #bcff9a%enchantment_tier%'
|
||||
- '#bcff9a▪ #ddeceeApplies to: #bcff9a%enchantment_fit_item_types%'
|
||||
- '#bcff9a▪ #ddeceeLevels: #bcff9a%enchantment_level_min% #ddecee- #bcff9a%enchantment_level_max%'
|
||||
- '%conflicts%'
|
||||
- '%charges%'
|
||||
- '%obtaining%'
|
||||
- ''
|
||||
- '#a5ff9a&lActions:'
|
||||
- '#a5ff9a▪ #ddeceeLeft-Click: #a5ff9aSwitch Level'
|
||||
Lore:
|
||||
Conflicts:
|
||||
- ''
|
||||
- '#ff9a9a[!] #ddeceeCan not be used together with:'
|
||||
- '#ff9a9a▸ %enchantment_name%'
|
||||
Charges:
|
||||
- ''
|
||||
- '#d39aff&lCharges:'
|
||||
- '#d39aff◈ #ddeceeMaximum: #d39aff%enchantment_charges_max_amount%⚡'
|
||||
- '#d39aff◈ #ddeceePer Use: #d39aff-%enchantment_charges_consume_amount%⚡'
|
||||
- '#d39aff◈ #ddeceePer Recharge: #d39aff+%enchantment_charges_recharge_amount%⚡'
|
||||
- '#d39aff◈ #ddeceeFuel Item: #d39aff%enchantment_charges_fuel_item%'
|
||||
Obtaining:
|
||||
- ''
|
||||
- '#9af7ff&lObtain Chance:'
|
||||
- '#9af7ff┃ #ddeceeEnchanting Table: #9af7ff%enchantment_obtain_chance_enchanting%%'
|
||||
- '#9af7ff┃ #ddeceeVillager Trade: #9af7ff%enchantment_obtain_chance_villager%%'
|
||||
- '#9af7ff┃ #ddeceeLoot Generation: #9af7ff%enchantment_obtain_chance_loot_generation%%'
|
||||
- '#9af7ff┃ #ddeceeFishing: #9af7ff%enchantment_obtain_chance_fishing%%'
|
||||
- '#9af7ff┃ #ddeceeMob Spawning: #9af7ff%enchantment_obtain_chance_mob_spawning%%'
|
||||
Slots: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
|
||||
|
||||
Content:
|
||||
return:
|
||||
Priority: 5
|
||||
Item:
|
||||
Material: PLAYER_HEAD
|
||||
Head_Texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmU5YWU3YTRiZTY1ZmNiYWVlNjUxODEzODlhMmY3ZDQ3ZTJlMzI2ZGI1OWVhM2ViNzg5YTkyYzg1ZWE0NiJ9fX0=
|
||||
Name: '#ffee9a(↓) &fClose Menu'
|
||||
Lore: []
|
||||
Slots: 31
|
||||
Type: CLOSE
|
||||
|
||||
page_next:
|
||||
Slots: 35
|
||||
Type: PAGE_NEXT
|
||||
Item:
|
||||
Material: PLAYER_HEAD
|
||||
Head_Texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMyY2E2NjA1NmI3Mjg2M2U5OGY3ZjMyYmQ3ZDk0YzdhMGQ3OTZhZjY5MWM5YWMzYTkxMzYzMzEzNTIyODhmOSJ9fX0=
|
||||
Name: '#ffee9a(→) &fNext Page'
|
||||
Priority: 5
|
||||
|
||||
page_previous:
|
||||
Slots: 27
|
||||
Type: PAGE_PREVIOUS
|
||||
Item:
|
||||
Material: PLAYER_HEAD
|
||||
Head_Texture: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY5NzFkZDg4MWRiYWY0ZmQ2YmNhYTkzNjE0NDkzYzYxMmY4Njk2NDFlZDU5ZDFjOTM2M2EzNjY2YTVmYTYifX19
|
||||
Name: '#ffee9a(←) &fPrevious Page'
|
||||
Priority: 5
|
Loading…
Reference in New Issue
Block a user