-
Notifications
You must be signed in to change notification settings - Fork 1
/
BestiaryArea.java
159 lines (138 loc) · 6.07 KB
/
BestiaryArea.java
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package com.playmonumenta.libraryofsouls.bestiary;
import com.goncalomb.bukkit.mylib.reflect.NBTTagCompound;
import com.goncalomb.bukkit.mylib.reflect.NBTUtils;
import com.playmonumenta.libraryofsouls.LibraryOfSouls;
import com.playmonumenta.libraryofsouls.SoulEntry;
import com.playmonumenta.libraryofsouls.SoulsDatabase;
import com.playmonumenta.libraryofsouls.utils.Utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.Nullable;
public class BestiaryArea implements BestiaryEntryInterface {
private final @Nullable BestiaryArea mParent;
private final Component mName;
private final @Nullable String mLocation;
private final @Nullable NamespacedKey mAdvancementKey;
private final ItemStack mItem;
private final List<BestiaryEntryInterface> mChildren;
private static final ItemStack NOT_FOUND_ITEM = new ItemStack(Material.PAPER);
static {
ItemMeta meta = NOT_FOUND_ITEM.getItemMeta();
meta.displayName(Component.text("Area not discovered!", NamedTextColor.DARK_RED, TextDecoration.ITALIC));
NOT_FOUND_ITEM.setItemMeta(meta);
}
public BestiaryArea(@Nullable BestiaryArea parent, String name, ConfigurationSection config) throws Exception {
mParent = parent;
mName = Utils.parseMiniMessage(name);
if (config.contains("location_tag") && config.contains("children")) {
throw new Exception("Bestiary entry " + Utils.plainText(mName) + " should contain only location_tag OR children, not both");
} else if (config.contains("location_tag")) {
mLocation = config.getString("location_tag");
List<SoulEntry> souls = SoulsDatabase.getInstance().getSoulsByLocation(mLocation);
if (souls == null || souls.isEmpty()) {
throw new Exception("Bestiary entry " + Utils.plainText(mName) + " specifies nonexistent location " + mLocation);
}
mChildren = new ArrayList<BestiaryEntryInterface>(souls);
} else if (config.contains("children")) {
mLocation = null;
ConfigurationSection children = config.getConfigurationSection("children");
Set<String> childKeys = children.getKeys(false);
mChildren = new ArrayList<>(childKeys.size());
for (String childKey : childKeys) {
try {
mChildren.add(new BestiaryArea(this, childKey, children.getConfigurationSection(childKey)));
} catch (Exception ex) {
LibraryOfSouls.getInstance().getLogger().warning("Failed to load bestiary area " + childKey + ": " + ex.getMessage());
}
}
} else {
throw new Exception("Bestiary entry " + Utils.plainText(mName) + " must contain location_tag OR children");
}
if (config.contains("required_advancement")) {
mAdvancementKey = NamespacedKey.fromString(config.getString("required_advancement"));
/* Try to load the advancement */
try {
if (Bukkit.getAdvancement(mAdvancementKey) == null) {
throw new Exception("Bestiary advancement " + mAdvancementKey + " does not exist!");
}
} catch (Exception ex) {
/* This message is really ugly otherwise */
throw new Exception("Bestiary advancement " + mAdvancementKey + " does not exist!");
}
} else {
mAdvancementKey = null;
}
if (config.contains("item")) {
NBTTagCompound compound = NBTTagCompound.fromString(config.getString("item"));
compound.setByte("Count", (byte)1);
mItem = NBTUtils.itemStackFromNBTData(compound);
if (mItem == null || mItem.getType().isAir()) {
throw new Exception("Item for " + Utils.plainText(mName) + " failed to parse, was: " + config.getString("item"));
}
} else {
throw new Exception("Bestiary entry " + Utils.plainText(mName) + " is missing 'item'");
}
ItemMeta meta = mItem.getItemMeta();
meta.displayName(mName.colorIfAbsent(NamedTextColor.WHITE).decoration(TextDecoration.ITALIC, false));
if (config.contains("subtitle")) {
Component subtitle = Utils.parseMiniMessage(config.getString("subtitle"));
meta.lore(Arrays.asList(subtitle));
}
// Hide weapon damage, book enchants, and potion effects:
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
meta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
mItem.setItemMeta(meta);
}
/*--------------------------------------------------------------------------------
* BestiaryEntryInterface Interface
*/
@Override
public Component getName() {
return mName;
}
@Override
public boolean canOpenBestiary(Player player) {
return mAdvancementKey == null || player.getAdvancementProgress(Bukkit.getAdvancement(mAdvancementKey)).isDone() || player.hasPermission("los.bestiary.viewall");
}
@Override
public ItemStack getBestiaryItem(Player player) {
if (canOpenBestiary(player)) {
/* Advancement not required OR player has completed it */
return mItem;
} else {
/* Advancement is required but player doesn't have it */
return NOT_FOUND_ITEM;
}
}
@Override
public void openBestiary(Player player, @Nullable BestiaryArea parent, @Nullable List<BestiaryEntryInterface> peers, int peerIndex) {
/* Note this ignores the provided parent - the inventory will know to call getBestiaryParent() */
/* Maybe someday could use peers and peerIndex to go back and forth between areas too? */
new BestiaryAreaInventory(player, this, 0).openInventory(player, LibraryOfSouls.getInstance());
}
/*
* BestiaryEntryInterface Interface
*--------------------------------------------------------------------------------*/
/* Note that this is *not* in the interface - because there's no way for a regular mob to know what its parent is */
public @Nullable BestiaryArea getBestiaryParent() {
return mParent;
}
/* Only intermediate nodes have children */
public List<BestiaryEntryInterface> getBestiaryChildren() {
return mChildren;
}
}