mirror of
https://github.com/amalthea-mc/ShopChest.git
synced 2024-11-08 19:51:05 +00:00
Vastly extended hologram configuration
- You can now completely customize every part of the hologram - Added new placeholders "%STOCK%" and "%MAX-STACK%" => Now uses "%STOCK%" instead of "%AMOUNT%" in the in-stock message) - Armor Stands are no longer spawned with NMS and reflection - Hologram texts can dynamically change (e.g. with in-stock info) - Might contain a few issues
This commit is contained in:
parent
e85b11d274
commit
e1f076bfcd
@ -4,8 +4,8 @@ import com.palmergames.bukkit.towny.Towny;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.wasteofplastic.askyblock.ASkyBlock;
|
||||
import de.epiceric.shopchest.config.Config;
|
||||
import de.epiceric.shopchest.config.HologramFormat;
|
||||
import de.epiceric.shopchest.config.Regex;
|
||||
import de.epiceric.shopchest.event.ShopReloadEvent;
|
||||
import de.epiceric.shopchest.external.PlotSquaredShopFlag;
|
||||
import de.epiceric.shopchest.language.LanguageUtils;
|
||||
import de.epiceric.shopchest.language.LocalizedMessage;
|
||||
@ -43,7 +43,8 @@ public class ShopChest extends JavaPlugin {
|
||||
|
||||
private static ShopChest instance;
|
||||
|
||||
private Config config = null;
|
||||
private Config config;
|
||||
private HologramFormat hologramFormat;
|
||||
private ShopCommand shopCommand;
|
||||
private Economy econ = null;
|
||||
private Database database;
|
||||
@ -153,8 +154,16 @@ public class ShopChest extends JavaPlugin {
|
||||
|
||||
debug("Loading utils and extras...");
|
||||
LanguageUtils.load();
|
||||
|
||||
saveResource("item_names.txt", true);
|
||||
|
||||
File hologramFormatFile = new File(getDataFolder(), "hologram-format.yml");
|
||||
if (!hologramFormatFile.exists()) {
|
||||
saveResource("hologram-format.yml", false);
|
||||
}
|
||||
|
||||
hologramFormat = new HologramFormat(this);
|
||||
|
||||
loadMetrics();
|
||||
checkForUpdates();
|
||||
|
||||
@ -406,9 +415,10 @@ public class ShopChest extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link ShopCommand}
|
||||
*/
|
||||
public HologramFormat getHologramFormat() {
|
||||
return hologramFormat;
|
||||
}
|
||||
|
||||
public ShopCommand getShopCommand() {
|
||||
return shopCommand;
|
||||
}
|
||||
|
@ -141,9 +141,6 @@ public class Config {
|
||||
/** Whether admin shops should be excluded of the shop limits **/
|
||||
public boolean exclude_admin_shops;
|
||||
|
||||
/** Whether the buy- and sell price should be arranged below each other **/
|
||||
public boolean two_line_prices;
|
||||
|
||||
/** Whether the extension of a potion or tipped arrow (if available) should be appended to the item name. **/
|
||||
public boolean append_potion_level_to_item_name;
|
||||
|
||||
@ -177,11 +174,8 @@ public class Config {
|
||||
**/
|
||||
public boolean invert_mouse_buttons;
|
||||
|
||||
/** Amount a hologram with two price-lines should be lifted **/
|
||||
public double two_line_hologram_lift;
|
||||
|
||||
/** Amount a hologram with one price-line should be lifted **/
|
||||
public double one_line_hologram_lift;
|
||||
/** Whether the hologram's location should be fixed at the bottom **/
|
||||
public boolean hologram_fixed_bottom;
|
||||
|
||||
/** Amount every hologram should be lifted **/
|
||||
public double hologram_lift;
|
||||
@ -362,7 +356,6 @@ public class Config {
|
||||
blacklist = (plugin.getConfig().getStringList("blacklist") == null) ? new ArrayList<String>() : plugin.getConfig().getStringList("blacklist");
|
||||
buy_greater_or_equal_sell = plugin.getConfig().getBoolean("buy-greater-or-equal-sell");
|
||||
hopper_protection = plugin.getConfig().getBoolean("hopper-protection");
|
||||
two_line_prices = plugin.getConfig().getBoolean("two-line-prices");
|
||||
enable_quality_mode = plugin.getConfig().getBoolean("enable-quality-mode");
|
||||
enable_hologram_interaction = plugin.getConfig().getBoolean("enable-hologram-interaction");
|
||||
enable_debug_log = plugin.getConfig().getBoolean("enable-debug-log");
|
||||
@ -384,8 +377,7 @@ public class Config {
|
||||
show_shop_items = plugin.getConfig().getBoolean("show-shop-items");
|
||||
remove_shop_on_error = plugin.getConfig().getBoolean("remove-shop-on-error");
|
||||
invert_mouse_buttons = plugin.getConfig().getBoolean("invert-mouse-buttons");
|
||||
two_line_hologram_lift = plugin.getConfig().getDouble("two-line-hologram-lift");
|
||||
one_line_hologram_lift = plugin.getConfig().getDouble("one-line-hologram-lift");
|
||||
hologram_fixed_bottom = plugin.getConfig().getBoolean("hologram-fixed-bottom");
|
||||
hologram_lift = plugin.getConfig().getDouble("hologram-lift");
|
||||
maximal_distance = plugin.getConfig().getDouble("maximal-distance");
|
||||
maximal_item_distance = plugin.getConfig().getDouble("maximal-item-distance");
|
||||
|
124
src/main/java/de/epiceric/shopchest/config/HologramFormat.java
Normal file
124
src/main/java/de/epiceric/shopchest/config/HologramFormat.java
Normal file
@ -0,0 +1,124 @@
|
||||
package de.epiceric.shopchest.config;
|
||||
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class HologramFormat {
|
||||
|
||||
public enum Requirement {
|
||||
VENDOR, AMOUNT, ITEM_TYPE, ITEM_NAME, HAS_ENCHANTMENT, BUY_PRICE,
|
||||
SELL_PRICE, HAS_POTION_EFFECT, IS_MUSIC_DISC, IS_POTION_EXTENDED, IS_BOOK, ADMIN_SHOP,
|
||||
NORMAL_SHOP, IN_STOCK, MAX_STACK
|
||||
}
|
||||
|
||||
private ShopChest plugin;
|
||||
private YamlConfiguration config;
|
||||
|
||||
public HologramFormat(ShopChest plugin) {
|
||||
File configFile = new File(plugin.getDataFolder(), "hologram-format.yml");
|
||||
this.config = YamlConfiguration.loadConfiguration(configFile);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format for the given line of the hologram
|
||||
* @param line Line of the hologram
|
||||
* @param values Values of the requirements that might be needed by the format (contains {@code null} if not comparable)
|
||||
* @return The format of the first working option, or an empty String if no option is working
|
||||
* because of not fulfilled requirements
|
||||
*/
|
||||
public String getFormat(int line, Map<Requirement, Object> values) {
|
||||
ConfigurationSection options = config.getConfigurationSection("lines." + line + ".options");
|
||||
|
||||
optionLoop:
|
||||
for (String key : options.getKeys(false)) {
|
||||
ConfigurationSection option = options.getConfigurationSection(key);
|
||||
List<String> requirements = option.getStringList("requirements");
|
||||
|
||||
String format = option.getString("format");
|
||||
|
||||
for (String sReq : requirements) {
|
||||
for (Requirement req : values.keySet()) {
|
||||
if (sReq.contains(req.toString())) {
|
||||
if (!sReq.replace(req.toString(), "").trim().isEmpty()) {
|
||||
if (!eval(sReq, values)) {
|
||||
continue optionLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/** Returns whether the hologram text has to change dynamically without reloading */
|
||||
public boolean isDynamic() {
|
||||
int count = getLineCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
ConfigurationSection options = config.getConfigurationSection("lines." + i + ".options");
|
||||
|
||||
for (String key : options.getKeys(false)) {
|
||||
String format = options.getConfigurationSection(key).getString("format");
|
||||
if (format.contains(Regex.STOCK.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns the amount of lines in a hologram */
|
||||
public int getLineCount() {
|
||||
return config.getConfigurationSection("lines").getKeys(false).size();
|
||||
}
|
||||
|
||||
/** Returns the configuration of the "hologram-format.yml" file */
|
||||
public YamlConfiguration getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and evaluate a condition
|
||||
* @param condition Condition to evaluate
|
||||
* @param values Values of the requirements
|
||||
* @return Result of the condition
|
||||
*/
|
||||
public boolean eval(String condition, Map<Requirement, Object> values) {
|
||||
try {
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
ScriptEngine engine = manager.getEngineByName("JavaScript");
|
||||
|
||||
String c = condition;
|
||||
|
||||
for (HologramFormat.Requirement req : HologramFormat.Requirement.values()) {
|
||||
if (c.contains(req.toString()) && values.containsKey(req)) {
|
||||
String replace = String.valueOf(values.get(req));
|
||||
if (values.get(req) instanceof String) {
|
||||
replace = String.format("\"%s\"", replace);
|
||||
}
|
||||
c = c.replace(req.toString(), replace);
|
||||
}
|
||||
}
|
||||
|
||||
return (boolean) engine.eval(c);
|
||||
} catch (ScriptException e) {
|
||||
plugin.debug("Failed to eval condition: " + condition);
|
||||
plugin.debug(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -21,7 +21,9 @@ public enum Regex {
|
||||
VALUE("%VALUE%"),
|
||||
EXTENDED("%EXTENDED%"),
|
||||
REVENUE("%REVENUE%"),
|
||||
GENERATION("%GENERATION%");
|
||||
GENERATION("%GENERATION%"),
|
||||
STOCK("%STOCK%"),
|
||||
MAX_STACK("%MAX-STACK%");
|
||||
|
||||
private String name;
|
||||
|
||||
|
@ -19,6 +19,7 @@ import org.bukkit.potion.Potion;
|
||||
import org.bukkit.potion.PotionType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
public class LanguageUtils {
|
||||
|
||||
@ -1058,10 +1059,6 @@ public class LanguageUtils {
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.UPDATE_NO_UPDATE, langConfig.getString("message.update.no-update", "&6&lNo new update available.")));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.UPDATE_CHECKING, langConfig.getString("message.update.checking", "&6&lChecking for updates...")));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.UPDATE_ERROR, langConfig.getString("message.update.error", "&c&lError while checking for updates.")));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.HOLOGRAM_FORMAT, langConfig.getString("message.hologram.format", "%AMOUNT% * %ITEMNAME%"), Regex.AMOUNT, Regex.ITEM_NAME));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.HOLOGRAM_BUY_SELL, langConfig.getString("message.hologram.buy-and-sell", "Buy %BUY-PRICE% | %SELL-PRICE% Sell"), Regex.BUY_PRICE, Regex.SELL_PRICE));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.HOLOGRAM_BUY, langConfig.getString("message.hologram.only-buy", "Buy %BUY-PRICE%"), Regex.BUY_PRICE));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.HOLOGRAM_SELL, langConfig.getString("message.hologram.only-sell", "Sell %SELL-PRICE%"), Regex.SELL_PRICE));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.NO_PERMISSION_CREATE, langConfig.getString("message.noPermission.create", "&cYou don't have permission to create a shop.")));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.NO_PERMISSION_CREATE_ADMIN, langConfig.getString("message.noPermission.create-admin", "&cYou don't have permission to create an admin shop.")));
|
||||
messages.add(new LocalizedMessage(LocalizedMessage.Message.NO_PERMISSION_CREATE_PROTECTED, langConfig.getString("message.noPermission.create-protected", "&cYou don't have permission to create a shop on a protected chest.")));
|
||||
@ -1208,11 +1205,35 @@ public class LanguageUtils {
|
||||
return enchantmentString + " " + levelString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enchantmentMap Map of enchantments of an item
|
||||
* @return Comma separated list of localized enchantments
|
||||
*/
|
||||
public static String getEnchantmentString(Map<Enchantment, Integer> enchantmentMap) {
|
||||
Enchantment[] enchantments = enchantmentMap.keySet().toArray(new Enchantment[enchantmentMap.size()]);
|
||||
StringBuilder enchantmentList = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < enchantments.length; i++) {
|
||||
Enchantment enchantment = enchantments[i];
|
||||
|
||||
if (i == enchantments.length - 1) {
|
||||
enchantmentList.append(LanguageUtils.getEnchantmentName(enchantment, enchantmentMap.get(enchantment)));
|
||||
} else {
|
||||
enchantmentList.append(LanguageUtils.getEnchantmentName(enchantment, enchantmentMap.get(enchantment)));
|
||||
enchantmentList.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
return enchantmentList.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemStack Potion Item whose base effect name should be looked up
|
||||
* @return Localized Name of the Base Potion Effect
|
||||
*/
|
||||
public static String getPotionEffectName(ItemStack itemStack) {
|
||||
if (!(itemStack.getItemMeta() instanceof PotionMeta)) return "";
|
||||
|
||||
PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta();
|
||||
PotionType potionType;
|
||||
boolean upgraded;
|
||||
|
@ -104,10 +104,6 @@ public class LocalizedMessage {
|
||||
UPDATE_NO_UPDATE,
|
||||
UPDATE_CHECKING,
|
||||
UPDATE_ERROR,
|
||||
HOLOGRAM_FORMAT,
|
||||
HOLOGRAM_BUY_SELL,
|
||||
HOLOGRAM_BUY,
|
||||
HOLOGRAM_SELL,
|
||||
NO_PERMISSION_CREATE,
|
||||
NO_PERMISSION_CREATE_ADMIN,
|
||||
NO_PERMISSION_CREATE_PROTECTED,
|
||||
|
@ -26,6 +26,7 @@ import de.epiceric.shopchest.shop.Shop;
|
||||
import de.epiceric.shopchest.shop.Shop.ShopType;
|
||||
import de.epiceric.shopchest.sql.Database;
|
||||
import de.epiceric.shopchest.utils.ClickType;
|
||||
import de.epiceric.shopchest.utils.ItemUtils;
|
||||
import de.epiceric.shopchest.utils.Permissions;
|
||||
import de.epiceric.shopchest.utils.ShopUtils;
|
||||
import de.epiceric.shopchest.utils.Utils;
|
||||
@ -49,14 +50,13 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerArmorStandManipulateEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.*;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.potion.Potion;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import pl.islandworld.api.IslandWorldApi;
|
||||
import us.talabrek.ultimateskyblock.api.IslandInfo;
|
||||
|
||||
@ -81,6 +81,29 @@ public class ShopInteractListener implements Listener {
|
||||
this.worldGuard = plugin.getWorldGuard();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onInventoryClick(InventoryClickEvent e) {
|
||||
if (!plugin.getHologramFormat().isDynamic()) return;
|
||||
|
||||
Inventory chestInv = e.getInventory();
|
||||
|
||||
if (!(e.getInventory().getHolder() instanceof Chest || e.getInventory().getHolder() instanceof DoubleChest)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location loc = chestInv.getLocation();
|
||||
|
||||
final Shop shop = plugin.getShopUtils().getShop(loc);
|
||||
if (shop == null) return;
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
shop.updateHologramText();
|
||||
}
|
||||
}.runTaskLater(plugin, 1L);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerManipulateArmorStand(PlayerArmorStandManipulateEvent e) {
|
||||
// When clicking an armor stand with an armor item, the armor stand will take it.
|
||||
@ -715,39 +738,13 @@ public class ShopInteractListener implements Listener {
|
||||
LocalizedMessage.Message.SHOP_INFO_NORMAL : LocalizedMessage.Message.SHOP_INFO_ADMIN);
|
||||
|
||||
String stock = LanguageUtils.getMessage(LocalizedMessage.Message.SHOP_INFO_STOCK,
|
||||
new LocalizedMessage.ReplacedRegex(Regex.AMOUNT, String.valueOf(amount)));
|
||||
new LocalizedMessage.ReplacedRegex(Regex.STOCK, String.valueOf(amount)));
|
||||
|
||||
boolean potionExtended = false;
|
||||
|
||||
Map<Enchantment, Integer> enchantmentMap;
|
||||
|
||||
String potionEffectName = "";
|
||||
if (Utils.getMajorVersion() >= 9) {
|
||||
if (type == Material.TIPPED_ARROW || type == Material.LINGERING_POTION || type == Material.SPLASH_POTION) {
|
||||
potionEffectName = LanguageUtils.getPotionEffectName(shop.getProduct());
|
||||
PotionMeta potionMeta = (PotionMeta) shop.getProduct().getItemMeta();
|
||||
potionExtended = potionMeta.getBasePotionData().isExtended();
|
||||
|
||||
if (potionEffectName.trim().isEmpty())
|
||||
potionEffectName = LanguageUtils.getMessage(LocalizedMessage.Message.SHOP_INFO_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == Material.POTION) {
|
||||
potionEffectName = LanguageUtils.getPotionEffectName(shop.getProduct());
|
||||
if (Utils.getMajorVersion() < 9) {
|
||||
Potion potion = Potion.fromItemStack(shop.getProduct());
|
||||
potionExtended = potion.hasExtendedDuration();
|
||||
} else {
|
||||
PotionMeta potionMeta = (PotionMeta) shop.getProduct().getItemMeta();
|
||||
potionExtended = potionMeta.getBasePotionData().isExtended();
|
||||
}
|
||||
|
||||
if (potionEffectName.trim().isEmpty())
|
||||
potionEffectName = LanguageUtils.getMessage(LocalizedMessage.Message.SHOP_INFO_NONE);
|
||||
}
|
||||
String potionEffectName = LanguageUtils.getPotionEffectName(shop.getProduct());
|
||||
|
||||
if (potionEffectName.length() > 0) {
|
||||
boolean potionExtended = ItemUtils.isExtendedPotion(shop.getProduct());
|
||||
|
||||
String extended = potionExtended ? LanguageUtils.getMessage(LocalizedMessage.Message.SHOP_INFO_EXTENDED) : "";
|
||||
potionEffectString = LanguageUtils.getMessage(LocalizedMessage.Message.SHOP_INFO_POTION_EFFECT,
|
||||
new LocalizedMessage.ReplacedRegex(Regex.POTION_EFFECT, potionEffectName),
|
||||
@ -779,25 +776,8 @@ public class ShopInteractListener implements Listener {
|
||||
new LocalizedMessage.ReplacedRegex(Regex.MUSIC_TITLE, musicDiscName));
|
||||
}
|
||||
|
||||
String enchantmentList = "";
|
||||
if (shop.getProduct().getItemMeta() instanceof EnchantmentStorageMeta) {
|
||||
EnchantmentStorageMeta esm = (EnchantmentStorageMeta) shop.getProduct().getItemMeta();
|
||||
enchantmentMap = esm.getStoredEnchants();
|
||||
} else {
|
||||
enchantmentMap = shop.getProduct().getEnchantments();
|
||||
}
|
||||
|
||||
Enchantment[] enchantments = enchantmentMap.keySet().toArray(new Enchantment[enchantmentMap.size()]);
|
||||
|
||||
for (int i = 0; i < enchantments.length; i++) {
|
||||
Enchantment enchantment = enchantments[i];
|
||||
|
||||
if (i == enchantments.length - 1) {
|
||||
enchantmentList += LanguageUtils.getEnchantmentName(enchantment, enchantmentMap.get(enchantment));
|
||||
} else {
|
||||
enchantmentList += LanguageUtils.getEnchantmentName(enchantment, enchantmentMap.get(enchantment)) + ", ";
|
||||
}
|
||||
}
|
||||
Map<Enchantment, Integer> enchantmentMap = ItemUtils.getEnchantments(shop.getProduct());
|
||||
String enchantmentList = LanguageUtils.getEnchantmentString(enchantmentMap);
|
||||
|
||||
if (enchantmentList.length() > 0) {
|
||||
enchantmentString = LanguageUtils.getMessage(LocalizedMessage.Message.SHOP_INFO_ENCHANTMENTS,
|
||||
|
@ -2,47 +2,41 @@ package de.epiceric.shopchest.nms;
|
||||
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import de.epiceric.shopchest.utils.Utils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Hologram {
|
||||
|
||||
private static List<Hologram> holograms = new ArrayList<>();
|
||||
|
||||
private boolean exists = false;
|
||||
private List<Object> entityList = new ArrayList<>();
|
||||
private List<UUID> entityUuidList = new ArrayList<>();
|
||||
private String[] text;
|
||||
private List<Object> nmsArmorStands = new ArrayList<>();
|
||||
private List<ArmorStand> armorStands = new ArrayList<>();
|
||||
private ArmorStand interactArmorStand;
|
||||
private Location location;
|
||||
private List<Player> visible = new ArrayList<>();
|
||||
private ShopChest plugin;
|
||||
|
||||
private Class<?> entityArmorStandClass = Utils.getNMSClass("EntityArmorStand");
|
||||
private Class<?> worldClass = Utils.getNMSClass("World");
|
||||
private Class<?> packetPlayOutSpawnEntityLivingClass = Utils.getNMSClass("PacketPlayOutSpawnEntityLiving");
|
||||
private Class<?> packetPlayOutEntityDestroyClass = Utils.getNMSClass("PacketPlayOutEntityDestroy");
|
||||
private Class<?> entityClass = Utils.getNMSClass("Entity");
|
||||
private Class<?> entityLivingClass = Utils.getNMSClass("EntityLiving");
|
||||
private Class<?> worldServerClass = Utils.getNMSClass("WorldServer");
|
||||
|
||||
public Hologram(ShopChest plugin, String[] text, Location location) {
|
||||
public Hologram(ShopChest plugin, String[] lines, Location location) {
|
||||
this.plugin = plugin;
|
||||
this.text = text;
|
||||
this.location = location;
|
||||
|
||||
Class[] requiredClasses = new Class[] {
|
||||
worldClass, entityArmorStandClass, entityLivingClass, entityClass,
|
||||
packetPlayOutSpawnEntityLivingClass, packetPlayOutEntityDestroyClass,
|
||||
worldServerClass
|
||||
entityArmorStandClass, entityLivingClass, packetPlayOutSpawnEntityLivingClass,
|
||||
packetPlayOutEntityDestroyClass,
|
||||
};
|
||||
|
||||
for (Class c : requiredClasses) {
|
||||
@ -52,59 +46,101 @@ public class Hologram {
|
||||
}
|
||||
}
|
||||
|
||||
create();
|
||||
create(lines);
|
||||
}
|
||||
|
||||
private void create() {
|
||||
Location loc = location.clone();
|
||||
public void addLine(int line, String text) {
|
||||
if (text == null || text.isEmpty()) return;
|
||||
|
||||
for (int i = 0; i <= text.length; i++) {
|
||||
String text = null;
|
||||
text = ChatColor.translateAlternateColorCodes('&', text);
|
||||
|
||||
if (i != this.text.length) {
|
||||
text = this.text[i];
|
||||
if (text == null || text.isEmpty()) continue;
|
||||
} else {
|
||||
if (plugin.getShopChestConfig().enable_hologram_interaction) {
|
||||
loc = location.clone();
|
||||
loc.add(0, 0.4, 0);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (int i = line; i < armorStands.size(); i++) {
|
||||
ArmorStand stand = armorStands.get(i);
|
||||
stand.teleport(stand.getLocation().subtract(0, 0.25, 0));
|
||||
}
|
||||
|
||||
if (line >= armorStands.size()) {
|
||||
line = armorStands.size();
|
||||
}
|
||||
|
||||
Location location = this.location.clone().subtract(0, line * 0.25, 0);
|
||||
|
||||
try {
|
||||
ArmorStand armorStand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
|
||||
armorStand.setGravity(false);
|
||||
armorStand.setVisible(false);
|
||||
armorStand.setCustomName(text);
|
||||
armorStand.setCustomNameVisible(true);
|
||||
|
||||
Object craftArmorStand = armorStand.getClass().cast(armorStand);
|
||||
Object nmsArmorStand = craftArmorStand.getClass().getMethod("getHandle").invoke(craftArmorStand);
|
||||
|
||||
nmsArmorStands.add(line, nmsArmorStand);
|
||||
armorStands.add(line, armorStand);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
plugin.getLogger().severe("Could not create Hologram with reflection");
|
||||
plugin.debug("Could not create Hologram with reflection");
|
||||
plugin.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setLine(int line, String text) {
|
||||
if (text == null ||text.isEmpty()) {
|
||||
removeLine(line);
|
||||
return;
|
||||
}
|
||||
|
||||
text = ChatColor.translateAlternateColorCodes('&', text);
|
||||
|
||||
if (armorStands.size() <= line) {
|
||||
addLine(line, text);
|
||||
return;
|
||||
}
|
||||
|
||||
armorStands.get(line).setCustomName(text);
|
||||
}
|
||||
|
||||
public void removeLine(int line) {
|
||||
for (int i = line + 1; i < armorStands.size(); i++) {
|
||||
ArmorStand stand = armorStands.get(i);
|
||||
stand.teleport(stand.getLocation().add(0, 0.25, 0));
|
||||
}
|
||||
|
||||
if (armorStands.size() > line) {
|
||||
armorStands.get(line).remove();
|
||||
armorStands.remove(line);
|
||||
nmsArmorStands.remove(line);
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getLines() {
|
||||
List<String> lines = new ArrayList<>();
|
||||
for (ArmorStand armorStand : armorStands) {
|
||||
lines.add(armorStand.getCustomName());
|
||||
}
|
||||
|
||||
return lines.toArray(new String[lines.size()]);
|
||||
}
|
||||
|
||||
private void create(String[] lines) {
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
addLine(i, lines[i]);
|
||||
}
|
||||
|
||||
if (plugin.getShopChestConfig().enable_hologram_interaction) {
|
||||
Location loc = location.clone().add(0, 0.4, 0);
|
||||
|
||||
try {
|
||||
Object craftWorld = loc.getWorld().getClass().cast(loc.getWorld());
|
||||
Object worldServer = craftWorld.getClass().getMethod("getHandle").invoke(craftWorld);
|
||||
ArmorStand armorStand = (ArmorStand) location.getWorld().spawnEntity(loc, EntityType.ARMOR_STAND);
|
||||
armorStand.setGravity(false);
|
||||
armorStand.setVisible(false);
|
||||
|
||||
Constructor entityArmorStandConstructor = entityArmorStandClass.getConstructor(worldClass, double.class, double.class, double.class);
|
||||
Object entityArmorStand = entityArmorStandConstructor.newInstance(worldServer, loc.getX(), loc.getY(),loc.getZ());
|
||||
Object craftArmorStand = armorStand.getClass().cast(armorStand);
|
||||
Object nmsArmorStand = craftArmorStand.getClass().getMethod("getHandle").invoke(craftArmorStand);
|
||||
|
||||
if (text != null) {
|
||||
entityArmorStandClass.getMethod("setCustomName", String.class).invoke(entityArmorStand, text);
|
||||
entityArmorStandClass.getMethod("setCustomNameVisible", boolean.class).invoke(entityArmorStand, true);
|
||||
}
|
||||
|
||||
entityArmorStandClass.getMethod("setInvisible", boolean.class).invoke(entityArmorStand, true);
|
||||
|
||||
if (Utils.getMajorVersion() < 10) {
|
||||
entityArmorStandClass.getMethod("setGravity", boolean.class).invoke(entityArmorStand, false);
|
||||
} else {
|
||||
entityArmorStandClass.getMethod("setNoGravity", boolean.class).invoke(entityArmorStand, true);
|
||||
}
|
||||
|
||||
// Adds the entity to some lists so it can call interact events
|
||||
Method addEntityMethod = worldServerClass.getDeclaredMethod((Utils.getMajorVersion() == 8 ? "a" : "b"), entityClass);
|
||||
addEntityMethod.setAccessible(true);
|
||||
addEntityMethod.invoke(worldServerClass.cast(worldServer), entityArmorStand);
|
||||
|
||||
Object uuid = entityClass.getMethod("getUniqueID").invoke(entityArmorStand);
|
||||
|
||||
entityUuidList.add((UUID) uuid);
|
||||
entityList.add(entityArmorStand);
|
||||
|
||||
loc.subtract(0, 0.25, 0);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
|
||||
nmsArmorStands.add(nmsArmorStand);
|
||||
interactArmorStand = armorStand;
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
plugin.getLogger().severe("Could not create Hologram with reflection");
|
||||
plugin.debug("Could not create Hologram with reflection");
|
||||
plugin.debug(e);
|
||||
@ -119,7 +155,7 @@ public class Hologram {
|
||||
* @return Location of the hologram
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
return location.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,7 +165,7 @@ public class Hologram {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Object o : entityList) {
|
||||
for (Object o : nmsArmorStands) {
|
||||
try {
|
||||
Object entityLiving = entityLivingClass.cast(o);
|
||||
Object packet = packetPlayOutSpawnEntityLivingClass.getConstructor(entityLivingClass).newInstance(entityLiving);
|
||||
@ -166,7 +202,7 @@ public class Hologram {
|
||||
}
|
||||
|
||||
private void sendDestroyPackets(Player p) {
|
||||
for (Object o : entityList) {
|
||||
for (Object o : nmsArmorStands) {
|
||||
try {
|
||||
int id = (int) entityArmorStandClass.getMethod("getId").invoke(o);
|
||||
|
||||
@ -208,7 +244,17 @@ public class Hologram {
|
||||
* @return Whether the given armor stand is part of the hologram
|
||||
*/
|
||||
public boolean contains(ArmorStand armorStand) {
|
||||
return entityUuidList.contains(armorStand.getUniqueId());
|
||||
return armorStands.contains(armorStand);
|
||||
}
|
||||
|
||||
/** Returns the ArmorStands of this hologram */
|
||||
public List<ArmorStand> getArmorStands() {
|
||||
return armorStands;
|
||||
}
|
||||
|
||||
/** Returns the ArmorStand of this hologram that is responsible for interaction */
|
||||
public ArmorStand getInteractArmorStand() {
|
||||
return interactArmorStand;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,15 +262,10 @@ public class Hologram {
|
||||
* Hologram will be hidden from all players and will be killed
|
||||
*/
|
||||
public void remove() {
|
||||
for (Object o : entityList) {
|
||||
try {
|
||||
o.getClass().getMethod("die").invoke(o);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
plugin.getLogger().severe("Could not remove Hologram with reflection");
|
||||
plugin.debug("Could not remove Hologram with reflection");
|
||||
plugin.debug(e);
|
||||
}
|
||||
for (ArmorStand armorStand : armorStands) {
|
||||
armorStand.remove();
|
||||
}
|
||||
|
||||
exists = false;
|
||||
holograms.remove(this);
|
||||
}
|
||||
|
@ -2,12 +2,15 @@ package de.epiceric.shopchest.shop;
|
||||
|
||||
import de.epiceric.shopchest.ShopChest;
|
||||
import de.epiceric.shopchest.config.Config;
|
||||
import de.epiceric.shopchest.config.HologramFormat;
|
||||
import de.epiceric.shopchest.config.Regex;
|
||||
import de.epiceric.shopchest.exceptions.ChestNotFoundException;
|
||||
import de.epiceric.shopchest.exceptions.NotEnoughSpaceException;
|
||||
import de.epiceric.shopchest.language.LanguageUtils;
|
||||
import de.epiceric.shopchest.language.LocalizedMessage;
|
||||
import de.epiceric.shopchest.nms.CustomBookMeta;
|
||||
import de.epiceric.shopchest.nms.Hologram;
|
||||
import de.epiceric.shopchest.utils.ItemUtils;
|
||||
import de.epiceric.shopchest.utils.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -21,6 +24,11 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Shop {
|
||||
|
||||
private boolean created;
|
||||
@ -124,7 +132,7 @@ public class Shop {
|
||||
Location itemLocation;
|
||||
ItemStack itemStack;
|
||||
|
||||
itemLocation = new Location(location.getWorld(), hologram.getLocation().getX(), location.getY() + 1, hologram.getLocation().getZ());
|
||||
itemLocation = new Location(location.getWorld(), hologram.getLocation().getX(), location.getY() + 0.9, hologram.getLocation().getZ());
|
||||
itemStack = product.clone();
|
||||
itemStack.setAmount(1);
|
||||
|
||||
@ -162,44 +170,99 @@ public class Shop {
|
||||
doubleChest = false;
|
||||
}
|
||||
|
||||
boolean twoLinePrices = config.two_line_prices;
|
||||
|
||||
String[] holoText = getHologramText(twoLinePrices ? 3 : 2);
|
||||
Location holoLocation = getHologramLocation(doubleChest, chests, holoText);
|
||||
String[] holoText = getHologramText();
|
||||
Location holoLocation = getHologramLocation(doubleChest, chests);
|
||||
|
||||
hologram = new Hologram(plugin, holoText, holoLocation);
|
||||
}
|
||||
|
||||
private String[] getHologramText(int length) {
|
||||
String[] holoText = new String[length];
|
||||
public void updateHologramText() {
|
||||
String[] lines = getHologramText();
|
||||
String[] currentLines = hologram.getLines();
|
||||
|
||||
holoText[0] = LanguageUtils.getMessage(LocalizedMessage.Message.HOLOGRAM_FORMAT,
|
||||
new LocalizedMessage.ReplacedRegex(Regex.AMOUNT, String.valueOf(product.getAmount())),
|
||||
new LocalizedMessage.ReplacedRegex(Regex.ITEM_NAME, LanguageUtils.getItemName(product)));
|
||||
int max = Math.max(lines.length, currentLines.length);
|
||||
|
||||
if ((buyPrice <= 0) && (sellPrice > 0)) {
|
||||
holoText[1] = LanguageUtils.getMessage(LocalizedMessage.Message.HOLOGRAM_SELL,
|
||||
new LocalizedMessage.ReplacedRegex(Regex.SELL_PRICE, String.valueOf(sellPrice)));
|
||||
} else if ((buyPrice > 0) && (sellPrice <= 0)) {
|
||||
holoText[1] = LanguageUtils.getMessage(LocalizedMessage.Message.HOLOGRAM_BUY,
|
||||
new LocalizedMessage.ReplacedRegex(Regex.BUY_PRICE, String.valueOf(buyPrice)));
|
||||
} else {
|
||||
if (length == 2) {
|
||||
holoText[1] = LanguageUtils.getMessage(LocalizedMessage.Message.HOLOGRAM_BUY_SELL,
|
||||
new LocalizedMessage.ReplacedRegex(Regex.BUY_PRICE, String.valueOf(buyPrice)),
|
||||
new LocalizedMessage.ReplacedRegex(Regex.SELL_PRICE, String.valueOf(sellPrice)));
|
||||
for (int i = 0; i < max; i++) {
|
||||
if (i < lines.length) {
|
||||
hologram.setLine(i, lines[i]);
|
||||
} else {
|
||||
holoText[1] = LanguageUtils.getMessage(LocalizedMessage.Message.HOLOGRAM_BUY,
|
||||
new LocalizedMessage.ReplacedRegex(Regex.BUY_PRICE, String.valueOf(buyPrice)));
|
||||
holoText[2] = LanguageUtils.getMessage(LocalizedMessage.Message.HOLOGRAM_SELL,
|
||||
new LocalizedMessage.ReplacedRegex(Regex.SELL_PRICE, String.valueOf(sellPrice)));
|
||||
hologram.removeLine(i);
|
||||
}
|
||||
}
|
||||
|
||||
return holoText;
|
||||
}
|
||||
|
||||
private Location getHologramLocation(boolean doubleChest, Chest[] chests, String[] holoText) {
|
||||
private String[] getHologramText() {
|
||||
List<String> lines = new ArrayList<>();
|
||||
|
||||
Map<HologramFormat.Requirement, Object> requirements = new HashMap<>();
|
||||
|
||||
requirements.put(HologramFormat.Requirement.VENDOR, getVendor().getName());
|
||||
requirements.put(HologramFormat.Requirement.AMOUNT, getProduct().getAmount());
|
||||
requirements.put(HologramFormat.Requirement.ITEM_TYPE, getProduct().getType() + (getProduct().getDurability() > 0 ? ":" + getProduct().getDurability() : ""));
|
||||
requirements.put(HologramFormat.Requirement.ITEM_NAME, getProduct().getItemMeta().getDisplayName());
|
||||
requirements.put(HologramFormat.Requirement.HAS_ENCHANTMENT, !LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(getProduct())).isEmpty());
|
||||
requirements.put(HologramFormat.Requirement.BUY_PRICE, getBuyPrice());
|
||||
requirements.put(HologramFormat.Requirement.SELL_PRICE, getSellPrice());
|
||||
requirements.put(HologramFormat.Requirement.HAS_POTION_EFFECT, ItemUtils.getPotionEffect(getProduct()) != null);
|
||||
requirements.put(HologramFormat.Requirement.IS_MUSIC_DISC, ItemUtils.isMusicDisc(getProduct()));
|
||||
requirements.put(HologramFormat.Requirement.IS_POTION_EXTENDED, ItemUtils.isExtendedPotion(getProduct()));
|
||||
requirements.put(HologramFormat.Requirement.IS_BOOK, ItemUtils.getBookGeneration(getProduct()) != null);
|
||||
requirements.put(HologramFormat.Requirement.ADMIN_SHOP, getShopType() == ShopType.ADMIN);
|
||||
requirements.put(HologramFormat.Requirement.NORMAL_SHOP, getShopType() == ShopType.NORMAL);
|
||||
requirements.put(HologramFormat.Requirement.IN_STOCK, Utils.getAmount(getInventoryHolder().getInventory(), getProduct()));
|
||||
requirements.put(HologramFormat.Requirement.MAX_STACK, getProduct().getMaxStackSize());
|
||||
|
||||
int lineCount = plugin.getHologramFormat().getLineCount();
|
||||
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
String format = plugin.getHologramFormat().getFormat(i, requirements);
|
||||
for (Regex regex : Regex.values()) {
|
||||
String replace = "";
|
||||
|
||||
switch (regex) {
|
||||
case VENDOR:
|
||||
replace = getVendor().getName();
|
||||
break;
|
||||
case AMOUNT:
|
||||
replace = String.valueOf(getProduct().getAmount());
|
||||
break;
|
||||
case ITEM_NAME:
|
||||
replace = LanguageUtils.getItemName(getProduct());
|
||||
break;
|
||||
case ENCHANTMENT:
|
||||
replace = LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(getProduct()));
|
||||
break;
|
||||
case BUY_PRICE:
|
||||
replace = plugin.getEconomy().format(getBuyPrice());
|
||||
break;
|
||||
case SELL_PRICE:
|
||||
replace = plugin.getEconomy().format(getSellPrice());
|
||||
break;
|
||||
case POTION_EFFECT:
|
||||
replace = LanguageUtils.getPotionEffectName(getProduct());
|
||||
break;
|
||||
case MUSIC_TITLE:
|
||||
replace = LanguageUtils.getMusicDiscName(getProduct().getType());
|
||||
break;
|
||||
case GENERATION:
|
||||
CustomBookMeta.Generation gen = ItemUtils.getBookGeneration(getProduct());
|
||||
if (gen != null) replace = LanguageUtils.getBookGenerationName(gen);
|
||||
break;
|
||||
case STOCK:
|
||||
replace = String.valueOf(Utils.getAmount(getInventoryHolder().getInventory(), getProduct()));
|
||||
break;
|
||||
}
|
||||
|
||||
format = format.replace(regex.getName(), replace);
|
||||
}
|
||||
|
||||
lines.add(format);
|
||||
}
|
||||
|
||||
return lines.toArray(new String[lines.size()]);
|
||||
}
|
||||
|
||||
private Location getHologramLocation(boolean doubleChest, Chest[] chests) {
|
||||
Block b = location.getBlock();
|
||||
Location holoLocation;
|
||||
|
||||
@ -235,14 +298,6 @@ public class Shop {
|
||||
|
||||
holoLocation.add(0, config.hologram_lift, 0);
|
||||
|
||||
if (config.two_line_prices) {
|
||||
if (holoText.length == 3 && holoText[2] != null) {
|
||||
holoLocation.add(0, config.two_line_hologram_lift, 0);
|
||||
} else {
|
||||
holoLocation.add(0, config.one_line_hologram_lift, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return holoLocation;
|
||||
}
|
||||
|
||||
|
71
src/main/java/de/epiceric/shopchest/utils/ItemUtils.java
Normal file
71
src/main/java/de/epiceric/shopchest/utils/ItemUtils.java
Normal file
@ -0,0 +1,71 @@
|
||||
package de.epiceric.shopchest.utils;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import de.epiceric.shopchest.nms.CustomBookMeta;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.potion.Potion;
|
||||
import org.bukkit.potion.PotionType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemUtils {
|
||||
|
||||
public static Map<Enchantment, Integer> getEnchantments(ItemStack itemStack) {
|
||||
if (itemStack.getItemMeta() instanceof EnchantmentStorageMeta) {
|
||||
EnchantmentStorageMeta esm = (EnchantmentStorageMeta) itemStack.getItemMeta();
|
||||
return esm.getStoredEnchants();
|
||||
} else {
|
||||
return itemStack.getEnchantments();
|
||||
}
|
||||
}
|
||||
|
||||
public static PotionType getPotionEffect(ItemStack itemStack) {
|
||||
if (itemStack.getItemMeta() instanceof PotionMeta) {
|
||||
if (Utils.getMajorVersion() < 9) {
|
||||
return Potion.fromItemStack(itemStack).getType();
|
||||
} else {
|
||||
return ((PotionMeta) itemStack.getItemMeta()).getBasePotionData().getType();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isExtendedPotion(ItemStack itemStack) {
|
||||
if (itemStack.getItemMeta() instanceof PotionMeta) {
|
||||
if (Utils.getMajorVersion() >= 9) {
|
||||
PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta();
|
||||
return potionMeta.getBasePotionData().isExtended();
|
||||
} else {
|
||||
Potion potion = Potion.fromItemStack(itemStack);
|
||||
return potion.hasExtendedDuration();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isMusicDisc(ItemStack itemStack) {
|
||||
List<Material> musicDiscMaterials = Lists.newArrayList(
|
||||
Material.GOLD_RECORD, Material.GREEN_RECORD, Material.RECORD_3, Material.RECORD_4,
|
||||
Material.RECORD_5, Material.RECORD_6, Material.RECORD_7, Material.RECORD_8,
|
||||
Material.RECORD_9, Material.RECORD_10, Material.RECORD_11, Material.RECORD_12
|
||||
);
|
||||
|
||||
return musicDiscMaterials.contains(itemStack.getType());
|
||||
}
|
||||
|
||||
public static CustomBookMeta.Generation getBookGeneration(ItemStack itemStack) {
|
||||
if (itemStack.getType() == Material.WRITTEN_BOOK) {
|
||||
return CustomBookMeta.getGeneration(itemStack);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -82,26 +82,10 @@ only-show-shops-in-sight: true
|
||||
# This only has effect if 'only-show-shops-in-sight' is enabled
|
||||
only-show-first-shop-in-sight: true
|
||||
|
||||
# Set whether the buy- and sell price should be arranged below each other.
|
||||
# The first line will be the buy price with the message
|
||||
# "message.hologram.only-buy", the second line will be the sell price
|
||||
# with the message "message.hologram.only-sell".
|
||||
# If buying or selling is disabled, a line for that price will not be created.
|
||||
# (The messages can be found and modified in the specified language file)
|
||||
two-line-prices: false
|
||||
|
||||
# Set the amount (may be negative) a hologram should be lifted in the y-axis,
|
||||
# when "two-line-prices" is set to true and buying and selling is enabled
|
||||
# at the shop.
|
||||
# The higher the number, the higher will the hologram be.
|
||||
# A value of '1' equals to one block, and a value of '0.25' is equal to the
|
||||
# height of one line.
|
||||
two-line-hologram-lift: 0.25
|
||||
|
||||
# Set the amount (may be negative) a hologram should be lifted in the y-axis,
|
||||
# when "two-line-prices" is set to true and only buying or selling is
|
||||
# enabled at the shop.
|
||||
one-line-hologram-lift: 0
|
||||
# Set whether the hologram's location should be fixed at the bottom,
|
||||
# so when it gets more lines, it won't interfere with the item or chest,
|
||||
# but goes higher.
|
||||
hologram-fixed-bottom: true
|
||||
|
||||
# Set the amount (may be negative) a hologram should be lifted in the y-axis.
|
||||
# If the hologram lift is already increased by the values above,
|
||||
|
71
src/main/resources/hologram-format.yml
Normal file
71
src/main/resources/hologram-format.yml
Normal file
@ -0,0 +1,71 @@
|
||||
# ===============================================
|
||||
# === ShopChest's hologram configuration file ===
|
||||
# ===============================================
|
||||
#
|
||||
# Valid requirements are:
|
||||
# VENDOR, AMOUNT, ITEM_TYPE, ITEM_NAME, HAS_ENCHANTMENT, BUY_PRICE,
|
||||
# SELL_PRICE, HAS_POTION_EFFECT, IS_MUSIC_DISC, IS_POTION_EXTENDED,
|
||||
# IS_BOOK, ADMIN_SHOP, NORMAL_SHOP, IN_STOCK, MAX_STACK
|
||||
#
|
||||
# You can also use the requirements for conditions.
|
||||
# ITEM_TYPE will return the type of the item (-> item_names.txt),
|
||||
# ITEM_NAME can be compared against a custom named item's name (may be null).
|
||||
#
|
||||
# Examples:
|
||||
# - IN_STOCK > 0
|
||||
# - VENDOR == "EpicEric"
|
||||
# - BUY_PRICE <= SELL_PRICE
|
||||
# - ITEM_TYPE == "STONE:2"
|
||||
# - ITEM_TYPE != "IRON_INGOT"
|
||||
# - ITEM_NAME == "The Mighty Sword"
|
||||
# - (AMOUNT > 10) && (AMOUNT <= 20)
|
||||
# - (IN_STOCK > 0) || ADMIN_SHOP
|
||||
#
|
||||
# Valid placeholders are:
|
||||
# %VENDOR%, %AMOUNT%, %ITEM-NAME%, %ENCHANTMENT%, %BUY-PRICE%,
|
||||
# %SELL-PRICE%, %POTION-EFFECT%, %MUSIC-TITLE%, %GENERATION%,
|
||||
# %STOCK%, %MAX-STACK%
|
||||
#
|
||||
# Other information:
|
||||
# - Options can be called however you want.
|
||||
# - Color codes can be used in the format.
|
||||
# - Options are checked from top to bottom; the first to
|
||||
# fulfill the requirements will be taken.
|
||||
# - Lines start with 0.
|
||||
|
||||
lines:
|
||||
0:
|
||||
options:
|
||||
normal-shop:
|
||||
format: "%VENDOR%"
|
||||
requirements:
|
||||
- NORMAL_SHOP
|
||||
|
||||
admin-shop:
|
||||
format: "&cAdmin Shop"
|
||||
requirements:
|
||||
- ADMIN_SHOP
|
||||
|
||||
1:
|
||||
options:
|
||||
default:
|
||||
format: "%AMOUNT% x %ITEMNAME%"
|
||||
requirements:
|
||||
|
||||
2:
|
||||
options:
|
||||
buy-and-sell:
|
||||
format: "Buy %BUY-PRICE% | %SELL-PRICE% Sell"
|
||||
requirements:
|
||||
- BUY_PRICE > 0
|
||||
- SELL_PRICE > 0
|
||||
|
||||
only-buy:
|
||||
format: "Buy %BUY-PRICE%"
|
||||
requirements:
|
||||
- BUY_PRICE > 0
|
||||
|
||||
only-sell:
|
||||
format: "Sell %SELL-PRICE%"
|
||||
requirements:
|
||||
- SELL_PRICE > 0
|
@ -7,7 +7,7 @@ message.chest-no-shop=&cTruhe ist kein Shop.
|
||||
message.shop-create-not-enough-money=&cNicht genug Geld. Du brauchst &6%CREATION-PRICE% &cum einen Shop zu erstellen.
|
||||
message.shopInfo.vendor=&6Verkäufer: &e%VENDOR%
|
||||
message.shopInfo.product=&6Produkt: &e%AMOUNT% x %ITEMNAME%
|
||||
message.shopInfo.stock=&6Auf Lager: &e%AMOUNT%
|
||||
message.shopInfo.stock=&6Auf Lager: &e%STOCK%
|
||||
message.shopInfo.enchantments=&6Verzauberungen: &e%ENCHANTMENT%
|
||||
message.shopInfo.potion-effect=&6Trank-Effekte: &e%POTION-EFFECT% %EXTENDED%
|
||||
message.shopInfo.music-disc-title=&6Schallplattentitel: &e%MUSIC-TITLE%
|
||||
@ -60,10 +60,6 @@ message.update.click-to-download=Klicke hier zum Herunterladen
|
||||
message.update.no-update=&6&lKeine neue Aktualisierung verfügbar.
|
||||
message.update.checking=&6&lSuche nach Aktualisierungen...
|
||||
message.update.error=&c&lFehler beim Suchen nach Aktualisierungen.
|
||||
message.hologram.format=%AMOUNT% * %ITEMNAME%
|
||||
message.hologram.buy-and-sell=Kauf %BUY-PRICE% | %SELL-PRICE% Verkauf
|
||||
message.hologram.only-buy=Kauf %BUY-PRICE%
|
||||
message.hologram.only-sell=Verkauf %SELL-PRICE%
|
||||
message.noPermission.create=&cDu hast keine Berechtigung einen Shop zu erstellen.
|
||||
message.noPermission.create-admin=&cDu hast keine Berechtigung einen Admin-Shop zu erstellen.
|
||||
message.noPermission.create-protected=&cDu hast keine Berechtigung hier einen Shop zu erstellen.
|
||||
|
@ -30,8 +30,8 @@ message.shopInfo.vendor=&6Vendor: &e%VENDOR%
|
||||
message.shopInfo.product=&6Product: &e%AMOUNT% x %ITEMNAME%
|
||||
|
||||
# Set the in-stock message the player after entering '/shop info'.
|
||||
# Usable Placeholders=%AMOUNT%
|
||||
message.shopInfo.stock=&6In Stock: &e%AMOUNT%
|
||||
# Usable Placeholders=%STOCK%
|
||||
message.shopInfo.stock=&6In Stock: &e%STOCK%
|
||||
|
||||
# Set the enchantments message the player gets after entering '/shop info' if the product is enchanted
|
||||
# Usable Placeholders: %ENCHANTMENT%
|
||||
@ -215,22 +215,6 @@ message.update.checking=&6&lChecking for updates...
|
||||
# Set the message when an error occurs while checking for updates.
|
||||
message.update.error=&c&lError while checking for updates.
|
||||
|
||||
# Set the text in the first row of the shop's hologram
|
||||
# Usable Placeholders: %ITEMNAME%, %AMOUNT%
|
||||
message.hologram.format=%AMOUNT% * %ITEMNAME%
|
||||
|
||||
# Set the text in the second row of the shop's hologram when the player can buy and sell an item.
|
||||
# Usable Placeholders: %BUY-PRICE%, %SELL-PRICE%
|
||||
message.hologram.buy-and-sell=Buy %BUY-PRICE% | %SELL-PRICE% Sell
|
||||
|
||||
# Set the text in the second row of the shop's hologram when the player can only buy an item.
|
||||
# Usable Placeholders: %BUY-PRICE%
|
||||
message.hologram.only-buy=Buy %BUY-PRICE%
|
||||
|
||||
# Set the text in the second row of the shop's hologram when the player can only sell an item.
|
||||
# Usable Placeholders: %SELL-PRICE%
|
||||
message.hologram.only-sell=Sell %SELL-PRICE%
|
||||
|
||||
# Set the message when a not permitted player tries to create a shop.
|
||||
message.noPermission.create=&cYou don't have permission to create a shop.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user