This commit is contained in:
The_Creeper_Cow 2018-10-27 12:50:11 +02:00
parent ef2ed38246
commit a0da2bbbf8
9 changed files with 604 additions and 30 deletions

View File

@ -1,6 +1,7 @@
package com.songoda.epicfarming;
import com.google.common.base.Preconditions;
import com.songoda.arconix.api.methods.serialize.Serialize;
import com.songoda.arconix.api.utils.ConfigWrapper;
import com.songoda.arconix.plugin.Arconix;
import com.songoda.epicfarming.api.EpicFarming;
@ -20,6 +21,11 @@ import com.songoda.epicfarming.listeners.InteractListeners;
import com.songoda.epicfarming.listeners.InventoryListeners;
import com.songoda.epicfarming.player.PlayerActionManager;
import com.songoda.epicfarming.player.PlayerData;
import com.songoda.epicfarming.storage.Storage;
import com.songoda.epicfarming.storage.StorageItem;
import com.songoda.epicfarming.storage.StorageRow;
import com.songoda.epicfarming.storage.types.StorageMysql;
import com.songoda.epicfarming.storage.types.StorageYaml;
import com.songoda.epicfarming.tasks.EntityTask;
import com.songoda.epicfarming.tasks.FarmTask;
import com.songoda.epicfarming.tasks.GrowthTask;
@ -77,6 +83,8 @@ public class EpicFarmingPlugin extends JavaPlugin implements EpicFarming {
private FarmTask farmTask;
private EntityTask entityTask;
private Storage storage;
public static EpicFarmingPlugin getInstance() {
return INSTANCE;
}
@ -101,7 +109,7 @@ public class EpicFarmingPlugin extends JavaPlugin implements EpicFarming {
public void onEnable() {
// Check to make sure the Bukkit version is compatible.
if (!checkVersion()) return;
checkStorage();
INSTANCE = this;
Arconix.pl().hook(this);
@ -136,37 +144,68 @@ public class EpicFarmingPlugin extends JavaPlugin implements EpicFarming {
* Register Farms into FarmManger from configuration
*/
Bukkit.getScheduler().runTaskLater(this, () -> {
if (dataFile.getConfig().contains("Farms")) {
for (String locationStr : dataFile.getConfig().getConfigurationSection("Farms").getKeys(false)) {
Location location = Arconix.pl().getApi().serialize().unserializeLocation(locationStr);
if (location == null || location.getWorld() == null) continue;
int level = dataFile.getConfig().getInt("Farms." + locationStr + ".level");
// if (dataFile.getConfig().contains("Farms")) {
// for (String locationStr : dataFile.getConfig().getConfigurationSection("Farms").getKeys(false)) {
// Location location = Arconix.pl().getApi().serialize().unserializeLocation(locationStr);
// if (location == null || location.getWorld() == null) continue;
// int level = dataFile.getConfig().getInt("Farms." + locationStr + ".level");
//
// List<ItemStack> items = (List<ItemStack>) dataFile.getConfig().getList("Farms." + locationStr + ".Contents");
//
// String placedByStr = dataFile.getConfig().getString("Farms." + locationStr + ".placedBy");
//
// UUID placedBy = placedByStr == null ? null : UUID.fromString(placedByStr);
//
// EFarm farm = new EFarm(location, levelManager.getLevel(level), placedBy);
// farm.loadInventory(items);
//
// farmManager.addFarm(location, farm);
// }
// }
//
// // Adding in Boosts
// if (dataFile.getConfig().contains("data.boosts")) {
// for (String key : dataFile.getConfig().getConfigurationSection("data.boosts").getKeys(false)) {
// if (!dataFile.getConfig().contains("data.boosts." + key + ".Player")) continue;
// BoostData boostData = new BoostData(
// dataFile.getConfig().getInt("data.boosts." + key + ".Amount"),
// Long.parseLong(key),
// UUID.fromString(dataFile.getConfig().getString("data.boosts." + key + ".Player")));
//
// this.boostManager.addBoostToPlayer(boostData);
// }
// }
if (storage.containsGroup("farms")) {
for (StorageRow row : storage.getRowsByGroup("farms")) {
Location location = Serialize.getInstance().unserializeLocation(row.getKey());
if (location == null || location.getBlock() == null) return;
List<ItemStack> items = (List<ItemStack>) dataFile.getConfig().getList("Farms." + locationStr + ".Contents");
String placedByStr = dataFile.getConfig().getString("Farms." + locationStr + ".placedBy");
UUID placedBy = placedByStr == null ? null : UUID.fromString(placedByStr);
EFarm farm = new EFarm(location, levelManager.getLevel(level), placedBy);
int level = row.get("level").asInt();
Location loc = Arconix.pl().getApi().serialize().unserializeLocation(row.get("location").asString());
List<ItemStack> items =row.get("contents").asItemStackList();
UUID placedBY = UUID.fromString(row.get("placedby").asString());
EFarm farm = new EFarm(location,levelManager.getLevel(level),placedBY);
farm.loadInventory(items);
farmManager.addFarm(location, farm);
farmManager.addFarm(location,farm);
}
}
// Adding in Boosts
if (dataFile.getConfig().contains("data.boosts")) {
for (String key : dataFile.getConfig().getConfigurationSection("data.boosts").getKeys(false)) {
if (!dataFile.getConfig().contains("data.boosts." + key + ".Player")) continue;
if (storage.containsGroup("boosts")) {
for (StorageRow row : storage.getRowsByGroup("boosts")) {
if (row.getItems().get("uuid").asObject() != null)
continue;
BoostData boostData = new BoostData(
dataFile.getConfig().getInt("data.boosts." + key + ".Amount"),
Long.parseLong(key),
UUID.fromString(dataFile.getConfig().getString("data.boosts." + key + ".Player")));
row.get("amount").asInt(),
Long.parseLong(row.getKey()),
UUID.fromString(row.get("player").asString()));
this.boostManager.addBoostToPlayer(boostData);
}
}
}, 10);
this.references = new References();
@ -200,6 +239,14 @@ public class EpicFarmingPlugin extends JavaPlugin implements EpicFarming {
console.sendMessage(Arconix.pl().getApi().format().formatText("&a============================="));
}
private void checkStorage() {
if (getConfig().getBoolean("Database.Activate Mysql Support")) {
this.storage = new StorageMysql(this);
} else {
this.storage = new StorageYaml(this);
}
}
public void onDisable() {
saveToFile();
for (PlayerData playerData : playerActionManager.getRegisteredPlayers()) {
@ -239,20 +286,25 @@ public class EpicFarmingPlugin extends JavaPlugin implements EpicFarming {
* Saves registered farms to file.
*/
private void saveToFile() {
this.storage.closeConnection();
checkStorage();
// Wipe old kit information
dataFile.getConfig().set("Farms", null);
storage.clearFile();
/*
* Dump FarmManager to file.
*/
for (Farm farm : farmManager.getFarms().values()) {
if (farm.getLocation() == null
|| farm.getLocation().getWorld() == null) continue;
String locationStr = Arconix.pl().getApi().serialize().serializeLocation(farm.getLocation());
dataFile.getConfig().set("Farms." + locationStr + ".level", farm.getLevel().getLevel());
dataFile.getConfig().set("Farms." + locationStr + ".placedBy", farm.getPlacedBy() == null ? null : farm.getPlacedBy().toString());
dataFile.getConfig().set("Farms." + locationStr + ".Contents", ((EFarm) farm).dumpInventory());
// String locationStr = Arconix.pl().getApi().serialize().serializeLocation(farm.getLocation());
// dataFile.getConfig().set("Farms." + locationStr + ".level", farm.getLevel().getLevel());
// dataFile.getConfig().set("Farms." + locationStr + ".placedBy", farm.getPlacedBy() == null ? null : farm.getPlacedBy().toString());
// dataFile.getConfig().set("Farms." + locationStr + ".Contents", ((EFarm) farm).dumpInventory());
String locstr = Arconix.pl().getApi().serialize().serializeLocation(farm.getLocation());
storage.saveItem("farms",new StorageItem("location",locstr),
new StorageItem("level",farm.getLevel().getLevel()),
new StorageItem("placedby",farm.getPlacedBy().toString()),
new StorageItem("contents",((EFarm)farm).dumpInventory()));
}
/*
@ -260,8 +312,11 @@ public class EpicFarmingPlugin extends JavaPlugin implements EpicFarming {
*/
for (BoostData boostData : boostManager.getBoosts()) {
String endTime = String.valueOf(boostData.getEndTime());
dataFile.getConfig().set("data.boosts." + endTime + ".Player", boostData.getPlayer().toString());
dataFile.getConfig().set("data.boosts." + endTime + ".Amount", boostData.getMultiplier());
// dataFile.getConfig().set("data.boosts." + endTime + ".Player", boostData.getPlayer().toString());
// dataFile.getConfig().set("data.boosts." + endTime + ".Amount", boostData.getMultiplier());
storage.saveItem("boosts",new StorageItem("endtime",endTime),
new StorageItem("amount",boostData.getMultiplier()),
new StorageItem("player",boostData.getPlayer()));
}
//Save to file

View File

@ -0,0 +1,32 @@
package com.songoda.epicfarming.storage;
import com.songoda.arconix.api.utils.ConfigWrapper;
import com.songoda.epicfarming.EpicFarmingPlugin;
import com.songoda.epicfarming.api.EpicFarming;
import java.util.List;
public abstract class Storage {
protected final EpicFarmingPlugin instance;
protected final ConfigWrapper dataFile;
public Storage(EpicFarmingPlugin instance) {
this.instance = instance;
this.dataFile = new ConfigWrapper(instance, "", "data.yml");
this.dataFile.createNewFile(null, "EpicHoppers Data File");
this.dataFile.getConfig().options().copyDefaults(true);
this.dataFile.saveConfig();
}
public abstract boolean containsGroup(String group);
public abstract List<StorageRow> getRowsByGroup(String group);
public abstract void clearFile();
public abstract void saveItem(String group, StorageItem... items);
public abstract void closeConnection();
}

View File

@ -0,0 +1,68 @@
package com.songoda.epicfarming.storage;
import com.songoda.epicfarming.utils.Serializers;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.*;
public class StorageItem {
private String key = null;
private final Object object;
public StorageItem(Object object) {
this.object = object;
}
public StorageItem(String key, Object object) {
this.key = key;
this.object = object;
}
public StorageItem(String key, List<ItemStack> material) {
StringBuilder object = new StringBuilder();
for (ItemStack m : material) {
object.append(Serializers.serialize(m));
object.append(";;");
}
this.key = key;
this.object = object.toString();
}
public String getKey() {
return key;
}
public String asString() {
if (object == null) return null;
return (String)object;
}
public boolean asBoolean() {
if (object == null) return false;
return (boolean)object;
}
public int asInt() {
if (object == null) return 0;
return (int)object;
}
public Object asObject() {
return object;
}
public List<ItemStack> asItemStackList() {
List<ItemStack> list = new ArrayList<>();
if (object == null) return list;
String obj = (String) object;
if (obj.equals("[]"))return list;
List<String> sers = new ArrayList<>(Arrays.asList(obj.split(";;")));
for (String ser : sers) {
list.add(Serializers.deserialize(ser));
}
return list;
}
}

View File

@ -0,0 +1,28 @@
package com.songoda.epicfarming.storage;
import java.util.Collections;
import java.util.Map;
public class StorageRow {
private final String key;
private final Map<String, StorageItem> items;
public StorageRow(String key, Map<String, StorageItem> items) {
this.key = key;
this.items = items;
}
public String getKey() {
return key;
}
public Map<String, StorageItem> getItems() {
return Collections.unmodifiableMap(items);
}
public StorageItem get(String key) {
if (!items.containsKey(key) || items.get(key).asObject().toString().equals("")) return new StorageItem(null);
return items.get(key);
}
}

View File

@ -0,0 +1,118 @@
package com.songoda.epicfarming.storage.types;
import com.songoda.epicfarming.EpicFarmingPlugin;
import com.songoda.epicfarming.storage.Storage;
import com.songoda.epicfarming.storage.StorageItem;
import com.songoda.epicfarming.storage.StorageRow;
import com.songoda.epicfarming.utils.MySQLDatabase;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StorageMysql extends Storage {
private MySQLDatabase database;
public StorageMysql(EpicFarmingPlugin instance) {
super(instance);
this.database = new MySQLDatabase(instance);
}
@Override
public boolean containsGroup(String group) {
try {
DatabaseMetaData dbm = database.getConnection().getMetaData();
ResultSet rs = dbm.getTables(null, null, instance.getConfig().getString("Database.Prefix")+group, null);
if (rs.next()) {
return true;
}
} catch (SQLException e) {
e.printStackTrace();
instance.getServer().getPluginManager().disablePlugin(instance);
}
return false;
}
@Override
public List<StorageRow> getRowsByGroup(String group) {
List<StorageRow> rows = new ArrayList<>();
try {
ResultSet set = database.getConnection().createStatement().executeQuery(String.format("SELECT * FROM `" + instance.getConfig().getString("Database.Prefix") + "%s`", group));
while (set.next()) {
Map<String, StorageItem> items = new HashMap<>();
String key = set.getString(1);
for (int i = 2; i <= set.getMetaData().getColumnCount(); i++) {
if (set.getObject(i) == null || set.getObject(i) == "") continue;
StorageItem item = new StorageItem(set.getObject(i));
items.put(set.getMetaData().getColumnName(i), item);
}
StorageRow row = new StorageRow(key, items);
rows.add(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
return rows;
}
@Override
public void clearFile() {
try {
database.getConnection().createStatement().execute("TRUNCATE `" + instance.getConfig().getString("Database.Prefix") + "sync`");
database.getConnection().createStatement().execute("TRUNCATE `" + instance.getConfig().getString("Database.Prefix") + "boosts`");
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void saveItem(String group, StorageItem... items) {
try {
StringBuilder sql = new StringBuilder(String.format("INSERT INTO `" + instance.getConfig().getString("Database.Prefix") + "%s`", group));
sql.append(" (");
for (StorageItem item : items) {
if (item == null || item.asObject() == null) continue;
sql.append(String.format("`%s`, ", item.getKey()));
}
sql = new StringBuilder(sql.substring(0, sql.length() - 2));
sql.append(")");
sql.append(" VALUES (");
for (StorageItem item : items) {
if (item == null || item.asObject() == null) continue;
sql.append(String.format("'%s', ", item.asObject().toString()));
}
sql = new StringBuilder(sql.substring(0, sql.length() - 2));
sql.append(");");
database.getConnection().createStatement().execute(sql.toString());
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void closeConnection() {
try {
database.getConnection().close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,71 @@
package com.songoda.epicfarming.storage.types;
import com.songoda.epicfarming.EpicFarmingPlugin;
import com.songoda.epicfarming.storage.Storage;
import com.songoda.epicfarming.storage.StorageItem;
import com.songoda.epicfarming.storage.StorageRow;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.MemorySection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StorageYaml extends Storage {
public StorageYaml(EpicFarmingPlugin instance) {
super(instance);
}
@Override
public boolean containsGroup(String group) {
return dataFile.getConfig().contains("data." + group);
}
@Override
public List<StorageRow> getRowsByGroup(String group) {
List<StorageRow> rows = new ArrayList<>();
ConfigurationSection currentSection = dataFile.getConfig().getConfigurationSection("data." + group);
for (String key : currentSection.getKeys(false)) {
Map<String, StorageItem> items = new HashMap<>();
ConfigurationSection currentSection2 = dataFile.getConfig().getConfigurationSection("data." + group + "." + key);
for (String key2 : currentSection2.getKeys(false)) {
String path = "data." + group + "." + key + "." + key2;
items.put(key2, new StorageItem(dataFile.getConfig().get(path) instanceof MemorySection
? convertToInLineList(path) : dataFile.getConfig().get(path)));
}
if (items.isEmpty()) continue;
StorageRow row = new StorageRow(key, items);
rows.add(row);
}
return rows;
}
private String convertToInLineList(String path) {
String converted = "";
for (String key : dataFile.getConfig().getConfigurationSection(path).getKeys(false)) {
converted += key + ":" + dataFile.getConfig().getInt(path + "." + key) + ";";
}
return converted;
}
@Override
public void clearFile() {
dataFile.getConfig().set("data", null);
}
@Override
public void saveItem(String group, StorageItem... items) {
for (int i = 0; i < items.length; i++) {
if (items[i] == null || items[i].asObject() == null) continue;
dataFile.getConfig().set("data." + group + "." + items[0].asString() + "." + items[i].getKey(), items[i].asObject());
}
}
@Override
public void closeConnection() {
dataFile.saveConfig();
}
}

View File

@ -0,0 +1,47 @@
package com.songoda.epicfarming.utils;
import com.songoda.epicfarming.EpicFarmingPlugin;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class MySQLDatabase {
private final EpicFarmingPlugin instance;
private Connection connection;
public MySQLDatabase(EpicFarmingPlugin instance) {
this.instance = instance;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://" + instance.getConfig().getString("Database.IP") + ":" + instance.getConfig().getString("Database.Port") + "/" + instance.getConfig().getString("Database.Database Name") + "?autoReconnect=true&useSSL=false";
this.connection = DriverManager.getConnection(url, instance.getConfig().getString("Database.Username"), instance.getConfig().getString("Database.Password"));
//ToDo: This is sloppy
connection.createStatement().execute(
"CREATE TABLE IF NOT EXISTS `" + instance.getConfig().getString("Database.Prefix") + "farms` (\n" +
"\t`location` TEXT NULL,\n" +
"\t`level` INT NULL,\n" +
"\t`placedby` TEXT NULL,\n" +
"\t`contents` TEXT NULL, \n"+
")");
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS `" + instance.getConfig().getString("Database.Prefix") + "boosts` (\n" +
"\t`endtime` TEXT NULL,\n" +
"\t`amount` INT NULL,\n" +
"\t`player` TEXT NULL\n" +
")");
} catch (ClassNotFoundException | SQLException e) {
System.out.println("Database connection failed.");
}
}
public Connection getConnection() {
return connection;
}
}

View File

@ -0,0 +1,148 @@
package com.songoda.epicfarming.utils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.SkullMeta;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Serializers {
public static String serialize(ItemStack item){
StringBuilder builder = new StringBuilder();
builder.append(item.getType().toString());
if(item.getDurability() != 0) builder.append(":" + item.getDurability());
builder.append(" " + item.getAmount());
for(Enchantment enchant:item.getEnchantments().keySet())
builder.append(" " + enchant.getName() + ":" + item.getEnchantments().get(enchant));
String name = getName(item);
if(name != null) builder.append(" name:" + name);
String lore = getLore(item);
if(lore != null) builder.append(" lore:" + lore);
Color color = getArmorColor(item);
if(color != null) builder.append(" rgb:" + color.getRed() + "|" + color.getGreen() + "|" + color.getBlue());
String owner = getOwner(item);
if(owner != null) builder.append(" owner:" + owner);
return builder.toString();
}
public static ItemStack deserialize(String serializedItem){
String[] strings = serializedItem.split(" ");
Map<Enchantment, Integer> enchants = new HashMap<Enchantment, Integer>();
String[] args;
ItemStack item = new ItemStack(Material.AIR);
for (String str: strings) {
args = str.split(":");
if(Material.matchMaterial(args[0]) != null && item.getType() == Material.AIR){
item.setType(Material.matchMaterial(args[0]));
if(args.length == 2) item.setDurability(Short.parseShort(args[1]));
break;
}
}
if (item.getType() == Material.AIR) {
Bukkit.getLogger().info("Could not find a valid material for the item in \"" + serializedItem + "\"");
return null;
}
for(String str:strings){
args = str.split(":", 2);
if(isNumber(args[0])) item.setAmount(Integer.parseInt(args[0]));
if(args.length == 1) continue;
if(args[0].equalsIgnoreCase("name:")){
setName(item, ChatColor.translateAlternateColorCodes('&', args[1]));
continue;
}
if(args[0].equalsIgnoreCase("lore:")){
setLore(item, ChatColor.translateAlternateColorCodes('&', args[1]));
continue;
}
if(args[0].equalsIgnoreCase("rgb:")){
setArmorColor(item, args[1]);
continue;
}
if(args[0].equalsIgnoreCase("owner:")){
setOwner(item, args[1]);
continue;
}
if(Enchantment.getByName(args[0].toUpperCase()) != null){
enchants.put(Enchantment.getByName(args[0].toUpperCase()), Integer.parseInt(args[1]));
continue;
}
}
item.addUnsafeEnchantments(enchants);
return item.getType().equals(Material.AIR) ? null : item;
}
private static String getOwner(ItemStack item){
if(!(item.getItemMeta() instanceof SkullMeta)) return null;
return ((SkullMeta)item.getItemMeta()).getOwner();
}
private static void setOwner(ItemStack item, String owner){
try{
SkullMeta meta = (SkullMeta) item.getItemMeta();
meta.setOwner(owner);
item.setItemMeta(meta);
}catch(Exception exception){
return;
}
}
private static String getName(ItemStack item){
if(!item.hasItemMeta()) return null;
if(!item.getItemMeta().hasDisplayName()) return null;
return item.getItemMeta().getDisplayName().replace(" ", "_").replace(ChatColor.COLOR_CHAR, '&');
}
private static void setName(ItemStack item, String name){
name = name.replace("_", " ");
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(name);
item.setItemMeta(meta);
}
private static String getLore(ItemStack item){
if(!item.hasItemMeta()) return null;
if(!item.getItemMeta().hasLore()) return null;
StringBuilder builder = new StringBuilder();
List<String> lore = item.getItemMeta().getLore();
for(int ind = 0;ind<lore.size();ind++){
builder.append((ind > 0 ? "|" : "") + lore.get(ind).replace(" ", "_").replace(ChatColor.COLOR_CHAR, '&'));
}
return builder.toString();
}
private static void setLore(ItemStack item, String lore){
lore = lore.replace("_", " ");
ItemMeta meta = item.getItemMeta();
meta.setLore(Arrays.asList(lore.split("\\|")));
item.setItemMeta(meta);
}
private static Color getArmorColor(ItemStack item){
if(!(item.getItemMeta() instanceof LeatherArmorMeta)) return null;
return ((LeatherArmorMeta)item.getItemMeta()).getColor();
}
private static void setArmorColor(ItemStack item, String str){
try{
String[] colors = str.split("\\|");
int red = Integer.parseInt(colors[0]);
int green = Integer.parseInt(colors[1]);
int blue = Integer.parseInt(colors[2]);
LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta();
meta.setColor(Color.fromRGB(red, green, blue));
item.setItemMeta(meta);
}catch(Exception exception){
return;
}
}
private static boolean isNumber(String str){
try{
Integer.parseInt(str);
}catch(NumberFormatException exception){
return false;
}
return true;
}
}

View File

@ -201,6 +201,13 @@ public class SettingsManager implements Listener {
o10("Main.Auto Breeding Cap", 15),
o11("Main.Animate", true),
o123("Main.Disable Auto Til Land", false),
d1("Database.Activate Mysql Support",false),
d6("Database.IP","127.0.0.1"),
d7("Database.Port",3306),
d2("Database.Username","root"),
d3("Database.Password","password"),
d4("Database.Database Name","EpicFarming"),
d5("Database.Prefix","EF-"),
o12("Interfaces.Economy Icon", "SUNFLOWER"),
o13("Interfaces.XP Icon", "EXPERIENCE_BOTTLE"),