Merge remote-tracking branch 'origin/master'

This commit is contained in:
Indyuce 2022-02-25 22:51:59 +01:00
commit be31ba92e8
27 changed files with 328 additions and 270 deletions

View File

@ -44,8 +44,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>9</source>
<target>9</target>
<source>10</source>
<target>10</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

View File

@ -172,7 +172,7 @@ public class ItemStats {
UPGRADE = new UpgradeStat(),
DOWNGRADE_ON_BREAK = new BooleanStat("BREAK_DOWNGRADE", Material.DAMAGED_ANVIL, "Downgrade when Broken", new String[]{"If this item's durability reaches 0,", "it will be fully repaired but also", "downgraded by one level.", "", "&cIt will only break if it cannot be", "&cdowngraded further", "", "Requires to define an &6Upgrade Template", "Required to define &6Custom Durability"}, new String[] { "piercing", "slashing", "blunt", "offhand", "range", "tool", "armor", "consumable", "accessory" }),
DOWNGRADE_ON_DEATH = new BooleanStat("DEATH_DOWNGRADE", Material.DAMAGED_ANVIL, "Downgrade on Death", new String[]{"If the wearer of this item dies, it may", "downgrade (based on &6Death Downgrade", "&6Chance &7stat)", "", "Required to define an &6Upgrade Template", "Requires keep-inventory gamerule. "}, new String[] { "piercing", "slashing", "blunt", "offhand", "range", "tool", "armor", "consumable", "accessory" }),
DOWNGRADE_ON_DEATH_CHANCE = new EvilDoubleStat("DEATH_DOWNGRADE_CHANCE", Material.SKELETON_SKULL, "Death Downgrade Chance", new String[]{"Probability that an item with &cDowngrade ", "&con Death&7 will be downgraded when the", "player dies. ", "", "Exceeding 100% will for sure downgrade", "one item, and roll again to downgrade", "another (with the excess probability).", "&6The same item wont be downgraded twice."}, new String[]{"!miscellaneous", "!block", "all"}),
DOWNGRADE_ON_DEATH_CHANCE = new DoubleStat("DEATH_DOWNGRADE_CHANCE", Material.SKELETON_SKULL, "Death Downgrade Chance", new String[]{"Probability that an item with &cDowngrade ", "&con Death&7 will be downgraded when the", "player dies. ", "", "Exceeding 100% will for sure downgrade", "one item, and roll again to downgrade", "another (with the excess probability).", "&6The same item wont be downgraded twice."}, new String[]{"!miscellaneous", "!block", "all"}, false),
// Unique Item Stats
SKULL_TEXTURE = new SkullTextureStat(),

View File

@ -90,7 +90,6 @@ public class MMOItems extends LuminePlugin {
private TierManager tierManager;
private StatManager statManager;
private SetManager setManager;
private EquipListener equipListener;
private PlaceholderParser placeholderParser = new DefaultPlaceholderParser();
private VaultSupport vaultSupport;
@ -190,7 +189,6 @@ public class MMOItems extends LuminePlugin {
dropTableManager = new DropTableManager();
worldGenManager = new WorldGenManager();
blockManager = new BlockManager();
equipListener = new EquipListener();
if (Bukkit.getPluginManager().getPlugin("Vault") != null) vaultSupport = new VaultSupport();
@ -512,10 +510,6 @@ public class MMOItems extends LuminePlugin {
return placeholderParser;
}
public EquipListener getEquipListener() {
return equipListener;
}
public TemplateManager getTemplates() {
return templateManager;
}

View File

@ -10,19 +10,15 @@ public class ConditionalDisplay {
this.negative = negative;
}
/*
* used when loading translations
/**
* Used when loading translations
*/
public ConditionalDisplay(ConfigurationSection config) {
this(config.getString("positive"), config.getString("negative"));
}
public String getPositive() {
return positive;
}
public String getNegative() {
return negative;
public String format(boolean positive) {
return positive ? this.positive : negative;
}
public void setup(ConfigurationSection config) {

View File

@ -17,6 +17,7 @@ public class LoadedCraftingObject<C> {
private final String id;
private final Function<MMOLineConfig, C> function;
// Configurable parameters
private ConditionalDisplay display;
public LoadedCraftingObject(String id, Function<MMOLineConfig, C> function, ConditionalDisplay display) {

View File

@ -26,6 +26,6 @@ public class CheckedCondition {
}
public String format() {
return condition.formatDisplay(isMet() ? condition.getDisplay().getPositive() : condition.getDisplay().getNegative());
return condition.formatDisplay(condition.getDisplay().format(met));
}
}

View File

@ -8,8 +8,8 @@ public abstract class Condition {
private final String id;
/**
* Instanciated for every condition in a crafting recipe when loading a
* crafting station from the config file.
* Instanciated for every condition in a crafting recipe
* when loading a crafting station from the config file.
*
* @param id The condition id
*/
@ -21,12 +21,8 @@ public abstract class Condition {
return id;
}
/*
* Shortcut to RecipeManager map lookup, may throw a stream lookup error if
* the condition has not been registered.
*/
public ConditionalDisplay getDisplay() {
return MMOItems.plugin.getCrafting().getConditions().stream().filter(type -> type.getId().equals(id)).findAny().orElse(null).getDisplay();
return MMOItems.plugin.getCrafting().getConditionInfo(id).getDisplay();
}
/**

View File

@ -0,0 +1,26 @@
package net.Indyuce.mmoitems.api.crafting.condition;
import io.lumine.mythic.lib.api.MMOLineConfig;
public abstract class GenericCondition extends Condition {
/**
* Permissions are super ugly to display so MI uses a string instead.
* This way 'Only for Mages' is used instead of 'class.mage'
* <p>
* One string can also replace multiple permissions.
* 'Magic Classes Only' instead of 'class.mage' and 'class.apprentice'
*/
public final String display;
public GenericCondition(String id, MMOLineConfig config) {
super(id);
this.display = config.getString("display", "<No display chosen>");
}
@Override
public String formatDisplay(String string) {
return string.replace("#display#", display);
}
}

View File

@ -6,41 +6,25 @@ import java.util.List;
import net.Indyuce.mmoitems.api.player.PlayerData;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class PermissionCondition extends Condition {
private final List<String> permissions;
public class PermissionCondition extends GenericCondition {
private final List<String> permissions;
/**
* Permissions are super ugly to display so MI uses a string instead.
* This way 'Only for Mages' is used instead of 'class.mage'
*
* One string can also replace multiple permissions.
* 'Magic Classes Only' instead of 'class.mage' and 'class.apprentice'
*/
private final String display;
public PermissionCondition(MMOLineConfig config) {
super("permission", config);
public PermissionCondition(MMOLineConfig config) {
super("permission");
config.validate("list");
permissions = Arrays.asList(config.getString("list").split(","));
}
config.validate("list");
permissions = Arrays.asList(config.getString("list").split(","));
display = config.contains("display") ? config.getString("display") : "?";
}
@Override
public boolean isMet(PlayerData data) {
for (String permission : permissions)
if (!data.getPlayer().hasPermission(permission))
return false;
return true;
}
@Override
public boolean isMet(PlayerData data) {
if(!data.isOnline()) return false;
for (String permission : permissions)
if (!data.getPlayer().hasPermission(permission))
return false;
return true;
}
@Override
public String formatDisplay(String string) {
return string.replace("#perms#", String.join(", ", permissions)).replace("#display#", display);
}
@Override
public void whenCrafting(PlayerData data) {
}
@Override
public void whenCrafting(PlayerData data) {
}
}

View File

@ -4,52 +4,44 @@ import io.lumine.mythic.lib.api.MMOLineConfig;
import me.clip.placeholderapi.PlaceholderAPI;
import net.Indyuce.mmoitems.api.player.PlayerData;
public class PlaceholderCondition extends Condition {
private final String value;
private final String placeholder;
private final String comparator;
private final String compareTo;
public class PlaceholderCondition extends GenericCondition {
private final String value, placeholder, comparator, compareTo;
public PlaceholderCondition(MMOLineConfig config) {
super("placeholder");
public PlaceholderCondition(MMOLineConfig config) {
super("placeholder", config);
config.validate("placeholder");
value = config.getString("placeholder");
String[] array = value.split("~");
placeholder = array[0];
comparator = array[1];
compareTo = array[2];
}
config.validate("placeholder");
value = config.getString("placeholder");
String[] array = value.split("~");
placeholder = array[0];
comparator = array[1];
compareTo = array[2];
}
@Override
public boolean isMet(PlayerData data) {
String placeholders = PlaceholderAPI.setPlaceholders(data.getPlayer(), placeholder);
switch (comparator) {
case "<":
return Double.valueOf(placeholders) < Double.valueOf(compareTo);
case "<+":
return Double.valueOf(placeholders) <= Double.valueOf(compareTo);
case ">":
return Double.valueOf(placeholders) > Double.valueOf(compareTo);
case ">+":
return Double.valueOf(placeholders) >= Double.valueOf(compareTo);
case "++":
case "+":
return Double.valueOf(placeholders) == Double.valueOf(compareTo);
case "!+":
return Double.valueOf(placeholders) != Double.valueOf(compareTo);
case "equals":
return placeholders.equals(compareTo);
}
return false;
}
@Override
public boolean isMet(PlayerData data) {
String placeholders = PlaceholderAPI.setPlaceholders(data.getPlayer(), placeholder);
switch (comparator) {
case "<":
return Double.valueOf(placeholders) < Double.valueOf(compareTo);
case "<+":
return Double.valueOf(placeholders) <= Double.valueOf(compareTo);
case ">":
return Double.valueOf(placeholders) > Double.valueOf(compareTo);
case ">+":
return Double.valueOf(placeholders) >= Double.valueOf(compareTo);
case "++":
case "+":
return Double.valueOf(placeholders) == Double.valueOf(compareTo);
case "!+":
return Double.valueOf(placeholders) != Double.valueOf(compareTo);
case "equals":
return placeholders.equals(compareTo);
}
return false;
}
@Override
public String formatDisplay(String string) {
return string.replace("#placeholder#", "" + placeholder);
}
@Override
public void whenCrafting(PlayerData data) {
}
@Override
public void whenCrafting(PlayerData data) {
}
}

View File

@ -90,6 +90,6 @@ public class CheckedIngredient {
@NotNull
public String format() {
return ingredient.formatDisplay(isHad() ? ingredient.getDisplay().getPositive() : ingredient.getDisplay().getNegative());
return ingredient.formatDisplay(ingredient.getDisplay().format(isHad));
}
}

View File

@ -40,12 +40,12 @@ public abstract class Ingredient<C extends PlayerIngredient> {
return amount;
}
/*
* shortcut to RecipeManager map lookup, may throw a stream lookup error if
* the condition has not been registered.
/**
* Shortcut to RecipeManager map lookup, may throw a stream
* lookup error if the ingredient has not been registered.
*/
public ConditionalDisplay getDisplay() {
return MMOItems.plugin.getCrafting().getIngredients().stream().filter(type -> type.getId().equals(id)).findAny().orElse(null).getDisplay();
return MMOItems.plugin.getCrafting().getIngredients().stream().filter(type -> type.getId().equals(id)).findAny().orElseThrow().getDisplay();
}
/**

View File

@ -74,8 +74,8 @@ public class PlayerStats {
Type type = item.getItem().getType();
ModifierSource source = type == null ? ModifierSource.OTHER : type.getItemSet().getModifierSource();
// Apply main hand weapon stat offset
if (item.getSlot() == EquipmentSlot.MAIN_HAND && stat instanceof AttackWeaponStat)
// Apply hand weapon stat offset
if (item.getSlot().isHand() && stat instanceof AttackWeaponStat)
value -= ((AttackWeaponStat) stat).getOffset(playerData);
packet.addModifier(new StatModifier("MMOItem-" + index++, stat.getId(), value, ModifierType.FLAT, item.getSlot(), source));

View File

@ -53,7 +53,6 @@ public class ReloadCommandTreeNode extends CommandTreeNode {
}
public void reloadMain(CommandSender sender) {
MMOItems.plugin.getEquipListener().reload();
MMOItems.plugin.getLanguage().reload();
MMOItems.plugin.getDropTables().reload();
MMOItems.plugin.getTypes().reload();

View File

@ -63,9 +63,7 @@ public class MMOCoreMMOLoader extends MMOLoader {
MMOItems.plugin.getStats().register(MAX_STELLIUM);
MMOItems.plugin.getStats().register(ADDITIONAL_EXPERIENCE);
/*
* register extra conditions for MMOItems crafting.
*/
// Register extra conditions for MMOItems crafting.
MMOItems.plugin.getCrafting().registerCondition("profession", ProfessionCondition::new,
new ConditionalDisplay(
"&a" + AltChar.check + " Requires #level# in #profession#",

View File

@ -1,79 +0,0 @@
package net.Indyuce.mmoitems.listener;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.utils.Events;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.manager.Reloadable;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
public class EquipListener implements Reloadable, Listener {
public EquipListener(){
this.reload();
}
@Override
public void reload() {
if(MMOItems.plugin.getConfig().getBoolean("auto-equip-feature", true)) {
Events.subscribe(PlayerInteractEvent.class).handler(event -> {
/*
* We only care about listening for right click and shift right clicks.
*/
if (!(event.getAction().equals(Action.RIGHT_CLICK_AIR))) {
return;
}
if (event.getItem() == null || event.getPlayer() == null) {
return;
}
if (event.getItem().getType().toString().toLowerCase().contains("boots")
|| event.getItem().getType().toString().toLowerCase().contains("leggings")
|| event.getItem().getType().toString().toLowerCase().contains("chestplate")
|| event.getItem().getType().toString().toLowerCase().contains("helmet")) {
NBTItem nbtItem = NBTItem.get(event.getItem());
Integer priority = nbtItem.getInteger("MMOITEMS_EQUIP_PRIORITY");
if (event.getItem().getType().toString().toLowerCase().contains("helmet")) {
NBTItem helmet = NBTItem.get(event.getPlayer().getInventory().getHelmet());
Integer helmPriority = helmet.getInteger("MMOITEMS_EQUIP_PRIORITY");
if (priority >= helmPriority) {
ItemStack h = event.getPlayer().getInventory().getHelmet();
//event.getPlayer().getInventory().setHelmet(event.getItem());
//event.getPlayer().getInventory().setItemInMainHand(h);
}
} else if (event.getItem().getType().toString().toLowerCase().contains("chestplate")) {
NBTItem chestplate = NBTItem.get(event.getPlayer().getInventory().getChestplate());
Integer chestPriority = chestplate.getInteger("MMOITEMS_EQUIP_PRIORITY");
if (priority >= chestPriority) {
ItemStack c = event.getPlayer().getInventory().getChestplate();
//event.getPlayer().getInventory().setChestplate(event.getItem());
//event.getPlayer().getInventory().setItemInMainHand(c);
}
} else if (event.getItem().getType().toString().toLowerCase().contains("leggings")) {
NBTItem leggings = NBTItem.get(event.getPlayer().getInventory().getLeggings());
Integer legPriority = leggings.getInteger("MMOITEMS_EQUIP_PRIORITY");
if (priority >= legPriority) {
ItemStack l = event.getPlayer().getInventory().getLeggings();
//event.getPlayer().getInventory().setLeggings(event.getItem());
//event.getPlayer().getInventory().setItemInMainHand(l);
}
} else {
NBTItem boots = NBTItem.get(event.getPlayer().getInventory().getBoots());
Integer bootsPriority = boots.getInteger("MMOITEMS_EQUIP_PRIORITY");
if (priority >= bootsPriority) {
ItemStack b = event.getPlayer().getInventory().getBoots();
//event.getPlayer().getInventory().setBoots(event.getItem());
//event.getPlayer().getInventory().setItemInMainHand(b);
}
}
}
});
}
}
}

View File

@ -10,12 +10,15 @@ import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -116,7 +119,7 @@ public class ItemListener implements Listener {
// Drop all those items
for (ItemStack drop : player.getInventory().addItem(
mod.getReforgingOutput().toArray(A)).values()) {
mod.getReforgingOutput().toArray(new ItemStack[0])).values()) {
// Not air right
if (SilentNumbers.isAir(drop)) { continue; }
@ -128,5 +131,57 @@ public class ItemListener implements Listener {
return mod.getResult();
}
public static final ItemStack[] A = new ItemStack[0];
@EventHandler
public void autoEquip(PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK)
return;
if (event.getItem() == null)
return;
ArmorSlot slot = ArmorSlot.getArmorSlot(event.getItem());
if (slot == null)
return;
Player player = event.getPlayer();
NBTItem equipping = NBTItem.get(event.getItem()),
equipped = NBTItem.get(slot.getEquipped(player));
int equippingPriority = equipping.getInteger("MMOITEMS_EQUIP_PRIORITY"),
equippedPriority = equipped.getInteger("MMOITEMS_EQUIP_PRIORITY");
if (equippingPriority >= equippedPriority) {
player.getInventory().setItem(slot.equipmentSlot, event.getItem());
player.getInventory().setItem(event.getHand(), equipped.getItem());
}
}
private enum ArmorSlot {
HELMET(EquipmentSlot.HEAD),
CHESTPLATE(EquipmentSlot.CHEST),
LEGGINGS(EquipmentSlot.LEGS),
BOOTS(EquipmentSlot.FEET);
final EquipmentSlot equipmentSlot;
ArmorSlot(EquipmentSlot equipmentSlot) {
this.equipmentSlot = equipmentSlot;
}
ItemStack getEquipped(Player player) {
return player.getInventory().getItem(equipmentSlot);
}
boolean isItem(@Nullable ItemStack item) {
return item != null && item.getType().name().contains(name());
}
@Nullable
public static ArmorSlot getArmorSlot(ItemStack item) {
for (ArmorSlot slot : ArmorSlot.values())
if (slot.isItem(item))
return slot;
return null;
}
}
}

View File

@ -36,8 +36,8 @@ public class CraftingManager implements Reloadable {
* ingredient matches, the item is considered as a vanilla item.
*/
private final List<IngredientType> ingredients = new ArrayList<>();
private final Set<LoadedCraftingObject<Condition>> conditions = new HashSet<>();
private final Set<LoadedCraftingObject<Trigger>> triggers = new HashSet<>();
private final Map<String, LoadedCraftingObject<Condition>> conditions = new HashMap<>();
private final Map<String, LoadedCraftingObject<Trigger>> triggers = new HashMap<>();
private final Map<String, CraftingStation> stations = new HashMap<>();
@ -46,7 +46,7 @@ public class CraftingManager implements Reloadable {
// Conditions
registerCondition("level", LevelCondition::new, new ConditionalDisplay("&a" + AltChar.check + " Requires Level #level#", "&c" + AltChar.cross + " Requires Level #level#"));
registerCondition("permission", PermissionCondition::new, new ConditionalDisplay("&a" + AltChar.check + " #display#", "&c" + AltChar.cross + " #display#"));
registerCondition("placeholder", PlaceholderCondition::new, null);
registerCondition("placeholder", PlaceholderCondition::new, new ConditionalDisplay("&a" + AltChar.check + " #display#", "&c" + AltChar.cross + " #display#"));
registerCondition("mana", ManaCondition::new, new ConditionalDisplay("&a" + AltChar.check + " Requires #mana# Mana", "&c" + AltChar.cross + " Requires #mana# Mana"));
registerCondition("stamina", StaminaCondition::new, new ConditionalDisplay("&a" + AltChar.check + " Requires #stamina# Stamina", "&c" + AltChar.cross + " Requires #stamina# Stamina"));
registerCondition("food", FoodCondition::new, new ConditionalDisplay("&a" + AltChar.check + " Requires #food# Food", "&c" + AltChar.cross + " Requires #food# Food"));
@ -77,17 +77,16 @@ public class CraftingManager implements Reloadable {
ConfigFile language = new ConfigFile("/language", "crafting-stations");
for (LoadedCraftingObject<Condition> condition : getConditions())
if (condition.hasDisplay()) {
String path = "condition." + condition.getId();
if (!language.getConfig().contains(path)) {
language.getConfig().createSection(path);
condition.getDisplay().setup(language.getConfig().getConfigurationSection(path));
}
condition.setDisplay(new ConditionalDisplay(language.getConfig().getConfigurationSection(path)));
for (LoadedCraftingObject<Condition> condition : getConditions()) {
String path = "condition." + condition.getId();
if (!language.getConfig().contains(path)) {
language.getConfig().createSection(path);
condition.getDisplay().setup(language.getConfig().getConfigurationSection(path));
}
condition.setDisplay(new ConditionalDisplay(language.getConfig().getConfigurationSection(path)));
}
for (IngredientType ingredient : getIngredients()) {
String path = "ingredient." + ingredient.getId();
if (!language.getConfig().contains(path)) {
@ -107,7 +106,7 @@ public class CraftingManager implements Reloadable {
} catch (IllegalArgumentException|NullPointerException exception) {
MMOItems.plugin.getLogger().log(Level.WARNING, "Could not load station '" + file.getName() + "': " + exception.getMessage());
}
for (CraftingStation station : stations.values())
try {
station.postLoad();
@ -151,46 +150,48 @@ public class CraftingManager implements Reloadable {
throw new IllegalArgumentException("Could not match ingredient");
}
/**
* Finds the corresponding condition type, and from there
* load the corresponding condition from the line config
*/
@NotNull
public Condition getCondition(MMOLineConfig config) {
String key = config.getKey();
/**
* Finds the corresponding condition type, and from there
* load the corresponding condition from the line config
*
* @throws NullPointerException If not found
*/
@NotNull
public Condition getCondition(MMOLineConfig config) {
return getConditionInfo(config.getKey()).load(config);
}
for (LoadedCraftingObject<Condition> condition : conditions)
if (condition.getId().equalsIgnoreCase(key))
return condition.load(config);
@NotNull
public LoadedCraftingObject<Condition> getConditionInfo(String key) {
return Objects.requireNonNull(conditions.get(key), "Could not match condition");
}
throw new IllegalArgumentException("Could not match condition");
}
/**
* Finds the corresponding trigger type, and from there
* load the corresponding trigger from the line config
*
* @throws NullPointerException If not found
*/
@NotNull
public Trigger getTrigger(MMOLineConfig config) {
return getTriggerInfo(config.getKey()).load(config);
}
/**
* Finds the corresponding trigger type, and from there
* load the corresponding trigger from the line config
*/
@NotNull
public Trigger getTrigger(MMOLineConfig config) {
String key = config.getKey();
for (LoadedCraftingObject<Trigger> trigger : triggers)
if (trigger.getId().equalsIgnoreCase(key))
return trigger.load(config);
throw new IllegalArgumentException("Could not match trigger");
}
@NotNull
public LoadedCraftingObject<Trigger> getTriggerInfo(String key) {
return Objects.requireNonNull(triggers.get(key), "Could not match trigger");
}
public List<IngredientType> getIngredients() {
return ingredients;
}
public Set<LoadedCraftingObject<Condition>> getConditions() {
return conditions;
public Collection<LoadedCraftingObject<Condition>> getConditions() {
return conditions.values();
}
public Set<LoadedCraftingObject<Trigger>> getTriggers() {
return triggers;
public Collection<LoadedCraftingObject<Trigger>> getTriggers() {
return triggers.values();
}
/**
@ -215,9 +216,11 @@ public class CraftingManager implements Reloadable {
* @param id Condition ID
* @param function Function that loads a condition from a line conf
* @param display How it displays in the item lore, null if it should not
* @since 6.7 A conditional display is required for all conditions
*/
public void registerCondition(String id, Function<MMOLineConfig, Condition> function, @Nullable ConditionalDisplay display) {
conditions.add(new LoadedCraftingObject<>(id, function, display));
public void registerCondition(String id, Function<MMOLineConfig, Condition> function, @NotNull ConditionalDisplay display) {
LoadedCraftingObject<Condition> obj = new LoadedCraftingObject<>(id, function, Objects.requireNonNull(display, "Conditional display cannot be null"));
conditions.put(obj.getId(), obj);
}
/**
@ -229,7 +232,8 @@ public class CraftingManager implements Reloadable {
* @param function Function that loads that type of trigger from a line configuration
*/
public void registerTrigger(String id, Function<MMOLineConfig, Trigger> function) {
triggers.add(new LoadedCraftingObject<Trigger>(id, function, null));
LoadedCraftingObject<Trigger> obj = new LoadedCraftingObject<>(id, function, null);
triggers.put(obj.getId(), obj);
}
public Collection<CraftingStation> getAll() {

View File

@ -0,0 +1,6 @@
package net.Indyuce.mmoitems.stat.component;
public interface Mergeable<T extends StatComponent> {
public void merge(T t);
}

View File

@ -0,0 +1,13 @@
package net.Indyuce.mmoitems.stat.component;
public abstract class StatComponent {
private final String path;
public StatComponent(String path) {
this.path = path;
}
public String getPath() {
return path;
}
}

View File

@ -0,0 +1,4 @@
package net.Indyuce.mmoitems.stat.component;
public interface Upgradable {
}

View File

@ -0,0 +1,32 @@
package net.Indyuce.mmoitems.stat.component.type;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import org.jetbrains.annotations.Nullable;
public abstract class AbstractObjectComponent extends StatComponent {
public AbstractObjectComponent(String path) {
super(path);
}
@Nullable
public StatComponent findComponent(String path) {
String[] split = path.split("\\.");
AbstractObjectComponent current = this;
int n = split.length - 1;
for (int i = 0; i < n; i++) {
StatComponent next = getComponent(split[i]);
if (next == null || !(next instanceof AbstractObjectComponent))
return null;
current = (AbstractObjectComponent) next;
}
return current.getComponent(split[n]);
}
@Nullable
public abstract StatComponent getComponent(String path);
}

View File

@ -0,0 +1,17 @@
package net.Indyuce.mmoitems.stat.component.type;
import net.Indyuce.mmoitems.stat.component.Mergeable;
import net.Indyuce.mmoitems.stat.component.StatComponent;
public class DoubleComponent extends StatComponent implements Mergeable<DoubleComponent> {
private double value;
public DoubleComponent(String path) {
super(path);
}
@Override
public void merge(DoubleComponent component) {
value += component.value;
}
}

View File

@ -0,0 +1,33 @@
package net.Indyuce.mmoitems.stat.component.type;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.Upgradable;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
public class ObjectComponent extends AbstractObjectComponent implements Upgradable {
private final Map<String, StatComponent> components = new HashMap<>();
public ObjectComponent(String path) {
super(path);
}
@Override
@Nullable
public StatComponent getComponent(String path) {
return components.get(path);
}
public void forEachComponent(Consumer<StatComponent> action) {
for (StatComponent component : components.values())
action.accept(component);
}
public Set<String> getComponentKeys() {
return components.keySet();
}
}

View File

@ -39,15 +39,23 @@ import java.util.regex.Pattern;
public class DoubleStat extends ItemStat implements Upgradable, Previewable {
private static final DecimalFormat digit = new DecimalFormat("0.####");
private final boolean moreIsBetter;
public DoubleStat(String id, Material mat, String name, String[] lore) {
super(id, mat, name, lore, new String[] { "!miscellaneous", "!block", "all" });
}
private static final DecimalFormat digit = new DecimalFormat("0.####");
public DoubleStat(String id, Material mat, String name, String[] lore, String[] types, Material... materials) {
super(id, mat, name, lore, types, materials);
}
public DoubleStat(String id, Material mat, String name, String[] lore) {
this(id, mat, name, lore, new String[]{"!miscellaneous", "!block", "all"}, true);
}
public DoubleStat(String id, Material mat, String name, String[] lore, String[] types, Material... materials) {
this(id, mat, name, lore, types, true, materials);
}
public DoubleStat(String id, Material mat, String name, String[] lore, String[] types, boolean moreIsBetter, Material... materials) {
super(id, mat, name, lore, types, materials);
this.moreIsBetter = moreIsBetter;
}
/**
* @return If this stat supports negatives stat values
@ -67,7 +75,7 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
* Usually, a greater magnitude of stat benefits the player (more health, more attack damage).
* <p>However, its not impossible for a stat to be evil instead, who knows?
*/
public boolean moreIsBetter() { return true; }
public boolean moreIsBetter() { return moreIsBetter; }
@Override
public RandomStatData whenInitialized(Object object) {
@ -109,7 +117,7 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
// Display in lore
if (value != 0 || upgradeShift != 0) {
String loreInsert = formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), value * multiplyWhenDisplaying());
String loreInsert = formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter, value * multiplyWhenDisplaying());
if (upgradeShift != 0)
loreInsert += MythicLib.plugin.parseColors(UpgradeTemplate.getUpgradeChangeSuffix(plus(upgradeShift * multiplyWhenDisplaying()) + (MythicLib.plugin.getMMOConfig().decimals.format(upgradeShift * multiplyWhenDisplaying())), !isGood(upgradeShift * multiplyWhenDisplaying())));
item.getLore().insert(getPath(), loreInsert);

View File

@ -1,11 +0,0 @@
package net.Indyuce.mmoitems.stat.type;
import org.bukkit.Material;
public class EvilDoubleStat extends DoubleStat {
public EvilDoubleStat(String id, Material mat, String name, String[] lore) { super(id, mat, name, lore); }
public EvilDoubleStat(String id, Material mat, String name, String[] lore, String[] types, Material... materials) { super(id, mat, name, lore, types, materials); }
@Override public boolean moreIsBetter() { return false; }
}

View File

@ -22,16 +22,6 @@ locked-skins: true
# off-hand like tomes!
disable-abilities-in-offhand: false
# Enable/disable the automatic equip feature.
# By right clicking with a piece of armor, the plugin will
# check if your currently equipped armor's "Equip Priority" stat
# is lower/higher than the one you're currently right clicking with, if
# the one in your hand is higher it will auto equip that and put the
# old piece back into your hand. Used to hot swap armor.
#
# Warning: Could be resource intensive if abused?
auto-equip-feature: true
# By default, all player inventories will be updated every
# 10 ticks which corresponds to 2 inventory updates a second.
inventory-update-delay: 10