!exp source refactor

This commit is contained in:
Indyuce 2021-08-21 00:36:26 +02:00
parent a363bc6606
commit d4071f532e
74 changed files with 1536 additions and 1504 deletions

View File

@ -95,8 +95,11 @@ public class MMOCore extends LuminePlugin {
public boolean shouldDebugSQL = false; public boolean shouldDebugSQL = false;
public void load() { public MMOCore() {
plugin = this; plugin = this;
}
public void load() {
/* /*
* register extra objective, drop items... * register extra objective, drop items...

View File

@ -5,8 +5,8 @@ import javax.annotation.Nullable;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import net.Indyuce.mmocore.api.experience.EXPSource; import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
public class PlayerExperienceGainEvent extends PlayerDataEvent implements Cancellable { public class PlayerExperienceGainEvent extends PlayerDataEvent implements Cancellable {

View File

@ -2,7 +2,7 @@ package net.Indyuce.mmocore.api.event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
public class PlayerLevelUpEvent extends PlayerDataEvent { public class PlayerLevelUpEvent extends PlayerDataEvent {

View File

@ -1,188 +0,0 @@
package net.Indyuce.mmocore.api.experience;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.potion.PotionType;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.util.PostLoadObject;
public class Profession extends PostLoadObject {
private final String id, name;
private final ExpCurve expCurve;
private final int maxLevel;
private final Map<ProfessionOption, Boolean> options = new HashMap<>();
/*
* experience given to the main player level whenever he levels up this
* profession
*/
private final LinearValue experience;
public Profession(String id, FileConfiguration config) {
super(config);
this.id = id.toLowerCase().replace("_", "-").replace(" ", "-");
this.name = config.getString("name");
Validate.notNull(name, "Could not load name");
expCurve = config.contains("exp-curve")
? MMOCore.plugin.experience.getOrThrow(config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
: ExpCurve.DEFAULT;
experience = new LinearValue(config.getConfigurationSection("experience"));
if (config.contains("options"))
for (String key : config.getConfigurationSection("options").getKeys(false))
try {
ProfessionOption option = ProfessionOption.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_"));
options.put(option, config.getBoolean("options." + key));
} catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not load option '" + key + "' from profession '" + id + "': " + exception.getMessage());
}
maxLevel = config.getInt("max-level");
if (config.contains("exp-sources"))
for (String key : config.getStringList("exp-sources"))
try {
MMOCore.plugin.professionManager.registerExpSource(MMOCore.plugin.loadManager.loadExperienceSource(new MMOLineConfig(key), this));
} catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not register exp source '" + key + "' from profession '" + id + "': " + exception.getMessage());
}
}
/*
* drop tables must be loaded after professions are initialized
*/
@Override
protected void whenPostLoaded(ConfigurationSection config) {
if (config.contains("on-fish"))
MMOCore.plugin.fishingManager.loadDropTables(config.getConfigurationSection("on-fish"));
if (config.contains("on-mine"))
MMOCore.plugin.mineManager.loadDropTables(config.getConfigurationSection("on-mine"));
if (config.contains("alchemy-experience")) {
MMOCore.plugin.alchemyManager.splash = 1 + config.getDouble("alchemy-experience.special.splash") / 100;
MMOCore.plugin.alchemyManager.lingering = 1 + config.getDouble("alchemy-experience.special.lingering") / 100;
MMOCore.plugin.alchemyManager.extend = 1 + config.getDouble("alchemy-experience.special.extend") / 100;
MMOCore.plugin.alchemyManager.upgrade = 1 + config.getDouble("alchemy-experience.special.upgrade") / 100;
for (String key : config.getConfigurationSection("alchemy-experience.effects").getKeys(false))
try {
PotionType type = PotionType.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_"));
MMOCore.plugin.alchemyManager.registerBaseExperience(type, config.getDouble("alchemy-experience.effects." + key));
} catch (IllegalArgumentException exception) {
MMOCore.log(Level.WARNING, "[PlayerProfessions:" + id + "] Could not read potion type from " + key);
}
}
if (config.contains("base-enchant-exp"))
for (String key : config.getConfigurationSection("base-enchant-exp").getKeys(false))
try {
Enchantment enchant = MythicLib.plugin.getVersion().getWrapper().getEnchantmentFromString(key.toLowerCase().replace("-", "_"));
MMOCore.plugin.enchantManager.registerBaseExperience(enchant, config.getDouble("base-enchant-exp." + key));
} catch (IllegalArgumentException exception) {
MMOCore.log(Level.WARNING, "[PlayerProfessions:" + id + "] Could not read enchant from " + key);
}
if (config.contains("repair-exp"))
for (String key : config.getConfigurationSection("repair-exp").getKeys(false))
try {
Material material = Material.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_"));
MMOCore.plugin.smithingManager.registerBaseExperience(material, config.getDouble("repair-exp." + key));
} catch (IllegalArgumentException exception) {
MMOCore.log(Level.WARNING, "[PlayerProfessions:" + id + "] Could not read material from " + key);
}
// if (config.contains("effect-weight"))
// for (String key :
// config.getConfigurationSection("effect-weight").getKeys(false))
// try {
// MMOCore.plugin.alchemyManager.registerEffectWeight(PotionEffectType.getByName(key.toUpperCase().replace("-",
// "_").replace(" ", "_")), config.getDouble("effect-weight." + key));
// } catch (IllegalArgumentException exception) {
// MMOCore.log(Level.WARNING, "[PlayerProfessions:" + id + "] Could not
// read
// potion effect type from " + key);
// }
}
public boolean getOption(ProfessionOption option) {
return options.getOrDefault(option, option.getDefault());
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public ExpCurve getExpCurve() {
return expCurve;
}
public int getMaxLevel() {
return maxLevel;
}
public boolean hasMaxLevel() {
return maxLevel > 0;
}
public int calculateExperience(int x) {
return (int) experience.calculate(x);
}
public LinearValue getExperience() {
return experience;
}
public static enum ProfessionOption {
/**
* When disabled, removes exp holograms when mined
*/
EXP_HOLOGRAMS(true);
private final boolean def;
private ProfessionOption(boolean def) {
this.def = def;
}
public boolean getDefault() {
return def;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Profession that = (Profession) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}

View File

@ -1,173 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.BrewEvent;
import org.bukkit.inventory.BrewerInventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionType;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class BrewPotionExperienceSource extends ExperienceSource<PotionMeta> {
private final List<PotionType> types = new ArrayList<>();
public BrewPotionExperienceSource(Profession profession, MMOLineConfig config) {
super(profession);
if (config.contains("effect"))
for (String key : config.getString("effect").split(","))
types.add(PotionType.valueOf(key.toUpperCase().replace("-", "_")));
}
@Override
public boolean matches(PlayerData player, PotionMeta meta) {
return hasRightClass(player)
&& (types.isEmpty() || new ArrayList<>(types).stream().anyMatch(type -> meta.getBasePotionData().getType() == type));
}
@Override
public ExperienceManager<BrewPotionExperienceSource> newManager() {
return new ExperienceManager<BrewPotionExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(BrewEvent event) {
Optional<Player> playerOpt = getNearbyPlayer(event.getBlock().getLocation());
if (!playerOpt.isPresent())
return;
final ItemStack found = findPotion(event.getContents());
if (found != null)
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, () -> {
ItemStack brewn = findPotion(event.getContents());
if (brewn == null)
return;
PlayerData data = PlayerData.get(playerOpt.get());
if(!data.isOnline()) return;
for (BrewPotionExperienceSource source : getSources())
if (source.matches(data, (PotionMeta) brewn.getItemMeta()))
new PotionUpgrade(found, brewn).process(data.getPlayer());
});
}
};
}
private ItemStack findPotion(BrewerInventory inv) {
for (int j = 0; j < 3; j++) {
ItemStack item = inv.getItem(j);
if (item != null && item.hasItemMeta() && item.getItemMeta() instanceof PotionMeta)
return item;
}
return null;
}
private Optional<Player> getNearbyPlayer(Location loc) {
return loc.getWorld().getPlayers().stream().filter(player -> player.getLocation().distanceSquared(loc) < 100).findAny();
}
public class PotionUpgrade {
/*
* if the potion was extended using redstone or upgraded using
* glowstone. PREPARE corresponds to when a water bottle is prepared for
* later recipes using NETHER STALK
*/
private double exp;
// private final PotionMeta old, brewn;
public PotionUpgrade(ItemStack old, ItemStack brewn) {
this(old.getType(), (PotionMeta) old.getItemMeta(), brewn.getType(), (PotionMeta) brewn.getItemMeta());
}
public PotionUpgrade(Material oldPot, PotionMeta old, Material brewnPot, PotionMeta brewn) {
// this.old = old;
// this.brewn = brewn;
/*
* calculate base exp
*/
exp += MMOCore.plugin.alchemyManager.getBaseExperience(brewn.getBasePotionData().getType());
// !old.getBasePotionData().getType().isUpgradeable() &&
// brewn.getBasePotionData().getType().isUpgradeable(),
//
// !old.getBasePotionData().isExtended() &&
// brewn.getBasePotionData().isExtended(),
//
// !old.getBasePotionData().isUpgraded() &&
// brewn.getBasePotionData().isUpgraded());
/*
* EXP modifiers based on brewing conditions
*/
if (oldPot == Material.POTION && brewnPot == Material.SPLASH_POTION)
exp *= MMOCore.plugin.alchemyManager.splash;
if (oldPot == Material.POTION && brewnPot == Material.LINGERING_POTION)
exp *= MMOCore.plugin.alchemyManager.lingering;
if (!old.getBasePotionData().isExtended() && brewn.getBasePotionData().isExtended())
exp *= MMOCore.plugin.alchemyManager.extend;
if (!old.getBasePotionData().isUpgraded() && brewn.getBasePotionData().isUpgraded())
exp *= MMOCore.plugin.alchemyManager.upgrade;
}
// private Map<PotionEffectType, Double> mapEffectDurations() {
// Map<PotionEffectType, Double> map = new HashMap<>();
//
// /*
// * potion level, plus the potion gained duration (max 0 so it does
// * not give negative EXP), multiplied by the potion effect weight.
// */
// brewn.getCustomEffects().forEach(effect -> map.put(effect.getType(),
//
// (effect.getAmplifier() + 1 + (double) Math.max(0,
// effect.getDuration() - getPotionEffect(old,
// effect.getType()).orElseGet(() -> new
// PotionEffect(PotionEffectType.SPEED, 0, 0)).getDuration()) / 60.)
//
// * MMOCore.plugin.alchemyManager.getWeight(effect.getType())));
//
// return map;
// }
// private int getTotal(Map<?, Double> map) {
// double t = 0;
// for (double d : map.values())
// t += d;
// return (int) t;
// }
// private Optional<PotionEffect> getPotionEffect(PotionMeta meta,
// PotionEffectType type) {
// return meta.getCustomEffects().stream().filter(effect ->
// effect.getType() == type).findFirst();
// }
public void process(Player player) {
/*
* calculate extra exp due to extra effects
*/
// exp += getTotal(mapEffectDurations());
giveExperience(PlayerData.get(player), (int) exp, null);
}
}
}

View File

@ -1,45 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.CraftItemEvent;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
import org.bukkit.event.inventory.InventoryAction;
public class CraftItemExperienceSource extends SpecificExperienceSource<Material> {
public final Material material;
public CraftItemExperienceSource(Profession profession, MMOLineConfig config) {
super(profession, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceManager<CraftItemExperienceSource> newManager() {
return new ExperienceManager<CraftItemExperienceSource>() {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void a(CraftItemEvent event) {
if(event.getAction() == InventoryAction.NOTHING ||
event.getInventory().getResult() == null) return;
PlayerData data = PlayerData.get((Player) event.getWhoClicked());
for (CraftItemExperienceSource source : getSources())
if (source.matches(data, event.getInventory().getResult().getType()))
source.giveExperience(data, event.getInventory().getResult().getAmount(), event.getInventory().getLocation());
}
};
}
@Override
public boolean matches(PlayerData player, Material obj) {
return material == obj && hasRightClass(player);
}
}

View File

@ -1,63 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.enchantment.EnchantItemEvent;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.MythicLib;
public class EnchantItemExperienceSource extends ExperienceSource<Void> {
private final List<Enchantment> enchants = new ArrayList<>();
public EnchantItemExperienceSource(Profession profession, MMOLineConfig config) {
super(profession);
if (config.contains("enchant"))
for (String key : config.getString("enchant").split(","))
enchants.add(MythicLib.plugin.getVersion().getWrapper().getEnchantmentFromString(key.toLowerCase().replace("-", "_")));
}
@Override
public boolean matches(PlayerData player, Void v) {
return hasRightClass(player);
}
@Override
public ExperienceManager<EnchantItemExperienceSource> newManager() {
return new ExperienceManager<EnchantItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(EnchantItemEvent event) {
PlayerData player = PlayerData.get(event.getEnchanter());
for (EnchantItemExperienceSource source : getSources())
if (source.matches(player, null)) {
Map<Enchantment, Integer> ench = new HashMap<>(event.getEnchantsToAdd());
if (!source.enchants.isEmpty())
ench.keySet().removeIf(enchantment -> !source.enchants.contains(enchantment));
if (ench.isEmpty())
continue;
double exp = 0;
for (Entry<Enchantment, Integer> entry : ench.entrySet())
exp += MMOCore.plugin.enchantManager.getBaseExperience(entry.getKey()) * entry.getValue();
giveExperience(player, (int) exp, event.getEnchantBlock().getLocation());
}
}
};
}
}

View File

@ -1,51 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import org.bukkit.Material;
import org.bukkit.entity.Item;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerFishEvent.State;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class FishItemExperienceSource extends SpecificExperienceSource<ItemStack> {
private final Material material;
public FishItemExperienceSource(Profession profession, MMOLineConfig config) {
super(profession, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceManager<FishItemExperienceSource> newManager() {
return new ExperienceManager<FishItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(PlayerFishEvent event) {
if (event.getState() == State.CAUGHT_FISH) {
ItemStack caught = ((Item) event.getCaught()).getItemStack();
if (caught.hasItemMeta())
return;
PlayerData data = PlayerData.get(event.getPlayer());
for (FishItemExperienceSource source : getSources())
if (source.matches(data, caught))
source.giveExperience(data, caught.getAmount(), event.getHook().getLocation().add(0, 1.0f, 0));
}
}
};
}
@Override
public boolean matches(PlayerData player, ItemStack obj) {
return hasRightClass(player) && obj.getType() == material;
}
}

View File

@ -1,51 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.event.EntityKillEntityEvent;
public class KillMobExperienceSource extends SpecificExperienceSource<Entity> {
public final EntityType type;
public KillMobExperienceSource(Profession profession, MMOLineConfig config) {
super(profession, config);
config.validate("type");
type = EntityType.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceManager<KillMobExperienceSource> newManager() {
return new ExperienceManager<KillMobExperienceSource>() {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void a(EntityKillEntityEvent event) {
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> {
if (event.getTarget().isDead() && event.getEntity() instanceof Player && !event.getEntity().hasMetadata("NPC")
&& !event.getTarget().hasMetadata("spawner_spawned")) {
PlayerData data = PlayerData.get((Player) event.getEntity());
for (KillMobExperienceSource source : getSources())
if (source.matches(data, event.getTarget()))
source.giveExperience(data, 1, event.getTarget().getLocation());
}
}, 2);
}
};
}
@Override
public boolean matches(PlayerData player, Entity obj) {
return hasRightClass(player) && obj.getType() == type;
}
}

View File

@ -1,67 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class MineBlockExperienceSource extends SpecificExperienceSource<Material> {
public final Material material;
private final boolean silkTouch;
private final boolean crop;
private final boolean playerPlaced;
public MineBlockExperienceSource(Profession profession, MMOLineConfig config) {
super(profession, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
silkTouch = config.getBoolean("silk-touch", true);
crop = config.getBoolean("crop", false);
playerPlaced = config.getBoolean("player-placed", false);
}
@Override
public ExperienceManager<MineBlockExperienceSource> newManager() {
return new ExperienceManager<MineBlockExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(BlockBreakEvent event) {
if (event.getPlayer().getGameMode() != GameMode.SURVIVAL)
return;
PlayerData data = PlayerData.get(event.getPlayer());
for (MineBlockExperienceSource source : getSources()) {
if (source.silkTouch && hasSilkTouch(event.getPlayer().getInventory().getItemInMainHand()))
continue;
if (source.crop && !MythicLib.plugin.getVersion().getWrapper().isCropFullyGrown(event.getBlock()))
continue;
if ((!source.playerPlaced) && event.getBlock().hasMetadata("player_placed"))
continue;
if (source.matches(data, event.getBlock().getType()))
source.giveExperience(data, 1, event.getBlock().getLocation());
}
}
};
}
private boolean hasSilkTouch(ItemStack item) {
return item != null && item.hasItemMeta() && item.getItemMeta().hasEnchant(Enchantment.SILK_TOUCH);
}
@Override
public boolean matches(PlayerData player, Material obj) {
return material == obj && hasRightClass(player);
}
}

View File

@ -1,47 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPlaceEvent;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class PlaceBlockExperienceSource extends SpecificExperienceSource<Material> {
public final Material material;
public PlaceBlockExperienceSource(Profession profession, MMOLineConfig config) {
super(profession, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceManager<PlaceBlockExperienceSource> newManager() {
return new ExperienceManager<PlaceBlockExperienceSource>() {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void a(BlockPlaceEvent event) {
if (event.getPlayer().getGameMode() != GameMode.SURVIVAL)
return;
PlayerData data = PlayerData.get(event.getPlayer());
for (PlaceBlockExperienceSource source : getSources())
if (source.matches(data, event.getBlock().getType()))
source.giveExperience(data, 1, event.getBlock().getLocation());
}
};
}
@Override
public boolean matches(PlayerData player, Material obj) {
return material == obj && hasRightClass(player);
}
}

View File

@ -1,84 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class RepairItemExperienceSource extends ExperienceSource<ItemStack> {
private final Material material;
public RepairItemExperienceSource(Profession profession, MMOLineConfig config) {
super(profession);
/*
* if material is null, the player can repair ANY material in order to
* get experience.
*/
material = config.contains("type") ? Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_")) : null;
}
@Override
public boolean matches(PlayerData player, ItemStack item) {
return (material == null || item.getType() == material) && hasRightClass(player);
}
@Override
public ExperienceManager<RepairItemExperienceSource> newManager() {
return new ExperienceManager<RepairItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(InventoryClickEvent event) {
if (event.getInventory() != null && event.getInventory().getType() == InventoryType.ANVIL && event.getSlot() == 2) {
ItemStack item = event.getCurrentItem();
PlayerData data = PlayerData.get((Player) event.getWhoClicked());
for (RepairItemExperienceSource source : getSources())
if (source.matches(data, item)) {
if (!(event.getInventory() instanceof AnvilInventory))
return;
if (((AnvilInventory) event.getInventory()).getRepairCost() > ((Player) event.getWhoClicked()).getLevel())
return;
/*
* make sure the items can actually be repaired
* before getting the amount of durability repaired
*/
ItemStack old = event.getInventory().getItem(0);
if (old == null || old.getType() == Material.AIR)
return;
if (old.getType().getMaxDurability() < 30 || item.getType().getMaxDurability() < 10)
return;
if (!MMOCore.plugin.smithingManager.hasExperience(item.getType()))
continue;
/*
* calculate exp based on amount of durability which
* was repaired, substract damage from old item
* durability.
*/
double exp = MMOCore.plugin.smithingManager.getBaseExperience(item.getType())
* Math.max(0, ((Damageable) old.getItemMeta()).getDamage() - ((Damageable) item.getItemMeta()).getDamage()) / 100;
giveExperience(data, (int) exp, null);
}
}
}
};
}
}

View File

@ -1,70 +0,0 @@
package net.Indyuce.mmocore.api.experience.source;
import java.util.Optional;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockCookEvent;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class SmeltItemExperienceSource extends SpecificExperienceSource<ItemStack> {
private final Material material;
public SmeltItemExperienceSource(Profession profession, MMOLineConfig config) {
super(profession, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceManager<SmeltItemExperienceSource> newManager() {
return new ExperienceManager<SmeltItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(BlockCookEvent event) {
Optional<Player> player = getNearestPlayer(event.getBlock().getLocation());
if (!player.isPresent())
return;
ItemStack caught = event.getResult();
if (caught.hasItemMeta())
return;
PlayerData data = PlayerData.get(player.get());
for (SmeltItemExperienceSource source : getSources())
if (source.matches(data, caught))
source.giveExperience(data, 1, event.getBlock().getLocation());
}
};
}
private Optional<Player> getNearestPlayer(Location loc) {
final Player[] nearby = loc.getWorld().getPlayers().stream().filter(player -> player.getLocation().distanceSquared(loc) < 100)
.toArray(Player[]::new);
Player selected = null;
double lastDist = 100;
for (Player p : nearby) {
double currDist = p.getLocation().distance(loc);
if (currDist < lastDist) {
lastDist = currDist;
selected = p;
}
}
return Optional.ofNullable(selected);
}
@Override
public boolean matches(PlayerData player, ItemStack obj) {
return obj.getType() == material && hasRightClass(player);
}
}

View File

@ -1,81 +0,0 @@
package net.Indyuce.mmocore.api.experience.source.type;
import javax.annotation.Nullable;
import org.bukkit.Location;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.EXPSource;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.Profession.ProfessionOption;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
/**
* Atrocious API that really needs rewriting
*
* @author cympe
*/
public abstract class ExperienceSource<T> {
private final Profession profession;
private PlayerClass profess;
public ExperienceSource(Profession profession) {
this(profession, null);
}
public ExperienceSource(PlayerClass profess) {
this(null, profess);
}
public ExperienceSource(Profession profession, PlayerClass profess) {
this.profession = profession;
this.profess = profess;
}
// TODO remove setter
public void setClass(PlayerClass profess) {
this.profess = profess;
}
public boolean hasRightClass(PlayerData data) {
return profess == null || profess.equals(data.getProfess());
}
public boolean hasProfession() {
return profession != null;
}
public boolean hasClass() {
return profess != null;
}
public abstract ExperienceManager<?> newManager();
public abstract boolean matches(PlayerData player, T obj);
/**
* Gives experience to the right profession/class
*
* @param player Player to give exp to
* @param amount Amount of experience given
* @param hologramLocation If location is null the default location will be
* the player's torso
*/
public void giveExperience(PlayerData player, int amount, @Nullable Location hologramLocation) {
if (hasProfession()) {
hologramLocation = !profession.getOption(ProfessionOption.EXP_HOLOGRAMS) ? null
: hologramLocation == null ? getPlayerLocation(player) : hologramLocation;
player.getCollectionSkills().giveExperience(profession, amount, EXPSource.SOURCE, hologramLocation);
} else {
hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null
: hologramLocation == null ? getPlayerLocation(player) : hologramLocation;
player.giveExperience(amount, EXPSource.SOURCE, hologramLocation);
}
}
private Location getPlayerLocation(PlayerData player) {
return player.isOnline() ? player.getPlayer().getLocation() : null;
}
}

View File

@ -1,47 +0,0 @@
package net.Indyuce.mmocore.api.experience.source.type;
import org.bukkit.Location;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
import io.lumine.mythic.lib.api.MMOLineConfig;
public abstract class SpecificExperienceSource<T> extends ExperienceSource<T> {
private final RandomAmount amount;
/**
* Used to register experience sources with SPECIFIC experience outputs.
* Other experience sources like ENCHANT have their exp output depend on the
* enchanted item. ALCHEMY exp outputs depend on the potion crafted
*/
public SpecificExperienceSource(Profession profession, MMOLineConfig config) {
super(profession);
config.validate("amount");
amount = new RandomAmount(config.getString("amount"));
}
public RandomAmount getAmount() {
return amount;
}
public int rollAmount() {
return amount.calculateInt();
}
/**
* Used when a player needs to gain experience after performing the action
* corresponding to this exp source
*
* @param multiplier
* Used by the CraftItem experience source, multiplies the exp
* earned by a certain factor. When crafting an item, the
* multiplier is equal to the amount of items crafted
* @param loc
* Location used to display the exp hologram
*/
public void giveExperience(PlayerData player, int multiplier, Location loc) {
super.giveExperience(player, rollAmount() * multiplier, loc);
}
}

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.api.load; package net.Indyuce.mmocore.api.load;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import net.Indyuce.mmocore.api.block.BlockType; import net.Indyuce.mmocore.api.block.BlockType;
@ -16,17 +17,16 @@ import net.Indyuce.mmocore.api.droptable.dropitem.GoldDropItem;
import net.Indyuce.mmocore.api.droptable.dropitem.MMDropTableDropItem; import net.Indyuce.mmocore.api.droptable.dropitem.MMDropTableDropItem;
import net.Indyuce.mmocore.api.droptable.dropitem.NoteDropItem; import net.Indyuce.mmocore.api.droptable.dropitem.NoteDropItem;
import net.Indyuce.mmocore.api.droptable.dropitem.VanillaDropItem; import net.Indyuce.mmocore.api.droptable.dropitem.VanillaDropItem;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.source.BrewPotionExperienceSource;
import net.Indyuce.mmocore.api.experience.source.BrewPotionExperienceSource; import net.Indyuce.mmocore.experience.source.CraftItemExperienceSource;
import net.Indyuce.mmocore.api.experience.source.CraftItemExperienceSource; import net.Indyuce.mmocore.experience.source.EnchantItemExperienceSource;
import net.Indyuce.mmocore.api.experience.source.EnchantItemExperienceSource; import net.Indyuce.mmocore.experience.source.FishItemExperienceSource;
import net.Indyuce.mmocore.api.experience.source.FishItemExperienceSource; import net.Indyuce.mmocore.experience.source.KillMobExperienceSource;
import net.Indyuce.mmocore.api.experience.source.KillMobExperienceSource; import net.Indyuce.mmocore.experience.source.MineBlockExperienceSource;
import net.Indyuce.mmocore.api.experience.source.MineBlockExperienceSource; import net.Indyuce.mmocore.experience.source.PlaceBlockExperienceSource;
import net.Indyuce.mmocore.api.experience.source.PlaceBlockExperienceSource; import net.Indyuce.mmocore.experience.source.RepairItemExperienceSource;
import net.Indyuce.mmocore.api.experience.source.RepairItemExperienceSource; import net.Indyuce.mmocore.experience.source.SmeltItemExperienceSource;
import net.Indyuce.mmocore.api.experience.source.SmeltItemExperienceSource; import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.quest.objective.ClickonObjective; import net.Indyuce.mmocore.api.quest.objective.ClickonObjective;
import net.Indyuce.mmocore.api.quest.objective.GoToObjective; import net.Indyuce.mmocore.api.quest.objective.GoToObjective;
import net.Indyuce.mmocore.api.quest.objective.KillMobObjective; import net.Indyuce.mmocore.api.quest.objective.KillMobObjective;
@ -129,33 +129,33 @@ public class DefaultMMOLoader extends MMOLoader {
} }
@Override @Override
public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, Profession profession) { public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, ExperienceDispenser dispenser) {
if (config.getKey().equals("fishitem")) if (config.getKey().equals("fishitem"))
return new FishItemExperienceSource(profession, config); return new FishItemExperienceSource(dispenser, config);
if (config.getKey().equals("killmob")) if (config.getKey().equals("killmob"))
return new KillMobExperienceSource(profession, config); return new KillMobExperienceSource(dispenser, config);
if (config.getKey().equals("mineblock")) if (config.getKey().equals("mineblock"))
return new MineBlockExperienceSource(profession, config); return new MineBlockExperienceSource(dispenser, config);
if (config.getKey().equals("placeblock")) if (config.getKey().equals("placeblock"))
return new PlaceBlockExperienceSource(profession, config); return new PlaceBlockExperienceSource(dispenser, config);
if (config.getKey().equals("brewpotion")) if (config.getKey().equals("brewpotion"))
return new BrewPotionExperienceSource(profession, config); return new BrewPotionExperienceSource(dispenser, config);
if (config.getKey().equals("smeltitem")) if (config.getKey().equals("smeltitem"))
return new SmeltItemExperienceSource(profession, config); return new SmeltItemExperienceSource(dispenser, config);
if (config.getKey().equals("enchantitem")) if (config.getKey().equals("enchantitem"))
return new EnchantItemExperienceSource(profession, config); return new EnchantItemExperienceSource(dispenser, config);
if (config.getKey().equals("repairitem")) if (config.getKey().equals("repairitem"))
return new RepairItemExperienceSource(profession, config); return new RepairItemExperienceSource(dispenser, config);
if (config.getKey().equals("craftitem")) if (config.getKey().equals("craftitem"))
return new CraftItemExperienceSource(profession, config); return new CraftItemExperienceSource(dispenser, config);
return null; return null;
} }

View File

@ -1,43 +1,43 @@
package net.Indyuce.mmocore.api.load; package net.Indyuce.mmocore.api.load;
import org.bukkit.configuration.ConfigurationSection; import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.api.block.BlockType; import net.Indyuce.mmocore.api.block.BlockType;
import net.Indyuce.mmocore.api.droptable.condition.Condition; import net.Indyuce.mmocore.api.droptable.condition.Condition;
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem; import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource; import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.quest.objective.Objective; import net.Indyuce.mmocore.api.quest.objective.Objective;
import net.Indyuce.mmocore.api.quest.trigger.Trigger; import net.Indyuce.mmocore.api.quest.trigger.Trigger;
import io.lumine.mythic.lib.api.MMOLineConfig; import org.bukkit.configuration.ConfigurationSection;
/**
* MMOLoader was initially an interface but it is now a
* class so devs do not have to add a new method
* everytime the class is updated.
*/
public class MMOLoader { public class MMOLoader {
/* public Condition loadCondition(MMOLineConfig config) {
* MMOLoader was initially an interface but it is now a class so devs do not return null;
* have to add a new method everytime the class is updated. }
*/
public Condition loadCondition(MMOLineConfig config) {
return null;
}
public Trigger loadTrigger(MMOLineConfig config) { public Trigger loadTrigger(MMOLineConfig config) {
return null; return null;
} }
public DropItem loadDropItem(MMOLineConfig config) { public DropItem loadDropItem(MMOLineConfig config) {
return null; return null;
} }
public Objective loadObjective(MMOLineConfig config, ConfigurationSection section) { public Objective loadObjective(MMOLineConfig config, ConfigurationSection section) {
return null; return null;
} }
public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, Profession profession) { public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, ExperienceDispenser dispenser) {
return null; return null;
} }
public BlockType loadBlockType(MMOLineConfig config) { public BlockType loadBlockType(MMOLineConfig config) {
return null; return null;
} }
} }

View File

@ -5,8 +5,6 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.Waypoint; import net.Indyuce.mmocore.api.Waypoint;
import net.Indyuce.mmocore.api.event.*; import net.Indyuce.mmocore.api.event.*;
import net.Indyuce.mmocore.api.experience.EXPSource;
import net.Indyuce.mmocore.api.experience.PlayerProfessions;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes; import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes;
import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.api.player.profess.PlayerClass;
@ -21,6 +19,8 @@ import net.Indyuce.mmocore.api.player.stats.StatType;
import net.Indyuce.mmocore.api.quest.PlayerQuests; import net.Indyuce.mmocore.api.quest.PlayerQuests;
import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect; import net.Indyuce.mmocore.api.util.math.particle.SmallParticleEffect;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.listener.SpellCast.SkillCasting; import net.Indyuce.mmocore.listener.SpellCast.SkillCasting;
import net.Indyuce.mmocore.manager.SoundManager; import net.Indyuce.mmocore.manager.SoundManager;
import net.Indyuce.mmocore.skill.CasterMetadata; import net.Indyuce.mmocore.skill.CasterMetadata;
@ -465,7 +465,7 @@ public class PlayerData extends OfflinePlayerData {
* @param hologramLocation Location used to display the hologram. If it's null, no * @param hologramLocation Location used to display the hologram. If it's null, no
* hologram will be displayed * hologram will be displayed
*/ */
public void giveExperience(int value, EXPSource source, @Nullable Location hologramLocation) { public void giveExperience(double value, EXPSource source, @Nullable Location hologramLocation) {
if (hasReachedMaxLevel()) { if (hasReachedMaxLevel()) {
setExperience(0); setExperience(0);
return; return;
@ -478,7 +478,7 @@ public class PlayerData extends OfflinePlayerData {
value = MMOCore.plugin.boosterManager.calculateExp(null, value); value = MMOCore.plugin.boosterManager.calculateExp(null, value);
value *= 1 + getStats().getStat(StatType.ADDITIONAL_EXPERIENCE) / 100; value *= 1 + getStats().getStat(StatType.ADDITIONAL_EXPERIENCE) / 100;
PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(this, value, source); PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(this, (int) value, source);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) if (event.isCancelled())
return; return;

View File

@ -7,18 +7,20 @@ import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.util.PostLoadObject; import io.lumine.mythic.lib.api.util.PostLoadObject;
import io.lumine.mythic.lib.version.VersionMaterial; import io.lumine.mythic.lib.version.VersionMaterial;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.ExpCurve;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.player.profess.event.EventTrigger; import net.Indyuce.mmocore.api.player.profess.event.EventTrigger;
import net.Indyuce.mmocore.api.player.profess.resource.ManaDisplayOptions; import net.Indyuce.mmocore.api.player.profess.resource.ManaDisplayOptions;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.api.player.profess.resource.ResourceHandler; import net.Indyuce.mmocore.api.player.profess.resource.ResourceHandler;
import net.Indyuce.mmocore.api.player.stats.StatType; import net.Indyuce.mmocore.api.player.stats.StatType;
import net.Indyuce.mmocore.skill.Skill;
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.api.util.MMOCoreUtils;
import net.Indyuce.mmocore.api.util.math.formula.LinearValue; import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
import net.Indyuce.mmocore.api.util.math.particle.CastingParticle; import net.Indyuce.mmocore.api.util.math.particle.CastingParticle;
import net.Indyuce.mmocore.experience.ExpCurve;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.provider.MainExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.skill.Skill;
import net.Indyuce.mmocore.skill.Skill.SkillInfo;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.Material; import org.bukkit.Material;
@ -33,292 +35,292 @@ import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
public class PlayerClass extends PostLoadObject { public class PlayerClass extends PostLoadObject {
private final String name, id, actionBarFormat; private final String name, id, actionBarFormat;
private final List<String> description = new ArrayList<>(), attrDescription = new ArrayList<>(); private final List<String> description = new ArrayList<>(), attrDescription = new ArrayList<>();
private final ItemStack icon; private final ItemStack icon;
private final Map<ClassOption, Boolean> options = new HashMap<>(); private final Map<ClassOption, Boolean> options = new HashMap<>();
private final ManaDisplayOptions manaDisplay; private final ManaDisplayOptions manaDisplay;
private final int maxLevel, displayOrder; private final int maxLevel, displayOrder;
private final ExpCurve expCurve; private final ExpCurve expCurve;
private final Map<StatType, LinearValue> stats = new HashMap<>(); private final Map<StatType, LinearValue> stats = new HashMap<>();
private final Map<String, SkillInfo> skills = new LinkedHashMap<>(); private final Map<String, SkillInfo> skills = new LinkedHashMap<>();
private final List<Subclass> subclasses = new ArrayList<>(); private final List<Subclass> subclasses = new ArrayList<>();
private final Map<PlayerResource, ResourceHandler> resourceHandlers = new HashMap<>(); private final Map<PlayerResource, ResourceHandler> resourceHandlers = new HashMap<>();
private final Map<String, EventTrigger> eventTriggers = new HashMap<>(); private final Map<String, EventTrigger> eventTriggers = new HashMap<>();
private final CastingParticle castParticle; private final CastingParticle castParticle;
public PlayerClass(String id, FileConfiguration config) { public PlayerClass(String id, FileConfiguration config) {
super(config); super(config);
this.id = id.toUpperCase().replace("-", "_").replace(" ", "_"); this.id = id.toUpperCase().replace("-", "_").replace(" ", "_");
name = MythicLib.plugin.parseColors(config.getString("display.name", "INVALID DISPLAY NAME")); name = MythicLib.plugin.parseColors(config.getString("display.name", "INVALID DISPLAY NAME"));
icon = MMOCoreUtils.readIcon(config.getString("display.item", "BARRIER")); icon = MMOCoreUtils.readIcon(config.getString("display.item", "BARRIER"));
if (config.contains("display.texture") && icon.getType() == VersionMaterial.PLAYER_HEAD.toMaterial()) if (config.contains("display.texture") && icon.getType() == VersionMaterial.PLAYER_HEAD.toMaterial())
try { try {
ItemMeta meta = icon.getItemMeta(); ItemMeta meta = icon.getItemMeta();
Field profileField = meta.getClass().getDeclaredField("profile"); Field profileField = meta.getClass().getDeclaredField("profile");
profileField.setAccessible(true); profileField.setAccessible(true);
GameProfile gp = new GameProfile(UUID.randomUUID(), null); GameProfile gp = new GameProfile(UUID.randomUUID(), null);
gp.getProperties().put("textures", new Property("textures", config.getString("display.texture"))); gp.getProperties().put("textures", new Property("textures", config.getString("display.texture")));
profileField.set(meta, gp); profileField.set(meta, gp);
icon.setItemMeta(meta); icon.setItemMeta(meta);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException
| SecurityException exception) { | SecurityException exception) {
throw new IllegalArgumentException("Could not apply playerhead texture: " + exception.getMessage()); throw new IllegalArgumentException("Could not apply playerhead texture: " + exception.getMessage());
} }
for (String string : config.getStringList("display.lore")) for (String string : config.getStringList("display.lore"))
description.add(ChatColor.GRAY + MythicLib.plugin.parseColors(string)); description.add(ChatColor.GRAY + MythicLib.plugin.parseColors(string));
for (String string : config.getStringList("display.attribute-lore")) for (String string : config.getStringList("display.attribute-lore"))
attrDescription.add(ChatColor.GRAY + MythicLib.plugin.parseColors(string)); attrDescription.add(ChatColor.GRAY + MythicLib.plugin.parseColors(string));
manaDisplay = config.contains("mana") ? new ManaDisplayOptions(config.getConfigurationSection("mana")) manaDisplay = config.contains("mana") ? new ManaDisplayOptions(config.getConfigurationSection("mana"))
: ManaDisplayOptions.DEFAULT; : ManaDisplayOptions.DEFAULT;
maxLevel = config.getInt("max-level"); maxLevel = config.getInt("max-level");
displayOrder = config.getInt("display.order"); displayOrder = config.getInt("display.order");
actionBarFormat = config.contains("action-bar", true) ? config.getString("action-bar") : null; actionBarFormat = config.contains("action-bar", true) ? config.getString("action-bar") : null;
expCurve = config.contains("exp-curve") expCurve = config.contains("exp-curve")
? MMOCore.plugin.experience.getOrThrow( ? MMOCore.plugin.experience.getOrThrow(
config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-")) config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
: ExpCurve.DEFAULT; : ExpCurve.DEFAULT;
if (config.contains("attributes")) if (config.contains("attributes"))
for (String key : config.getConfigurationSection("attributes").getKeys(false)) for (String key : config.getConfigurationSection("attributes").getKeys(false))
try { try {
stats.put(StatType.valueOf(key.toUpperCase().replace("-", "_")), stats.put(StatType.valueOf(key.toUpperCase().replace("-", "_")),
new LinearValue(config.getConfigurationSection("attributes." + key))); new LinearValue(config.getConfigurationSection("attributes." + key)));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load stat info '" + key + "' from class '" MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load stat info '" + key + "' from class '"
+ id + "': " + exception.getMessage()); + id + "': " + exception.getMessage());
} }
if (config.contains("skills")) if (config.contains("skills"))
for (String key : config.getConfigurationSection("skills").getKeys(false)) for (String key : config.getConfigurationSection("skills").getKeys(false))
try { try {
Validate.isTrue(MMOCore.plugin.skillManager.has(key), "Could not find skill " + key); Validate.isTrue(MMOCore.plugin.skillManager.has(key), "Could not find skill " + key);
skills.put(key.toUpperCase(), MMOCore.plugin.skillManager.get(key) skills.put(key.toUpperCase(), MMOCore.plugin.skillManager.get(key)
.newSkillInfo(config.getConfigurationSection("skills." + key))); .newSkillInfo(config.getConfigurationSection("skills." + key)));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load skill info '" + key + "' from class '" MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load skill info '" + key + "' from class '"
+ id + "': " + exception.getMessage()); + id + "': " + exception.getMessage());
} }
castParticle = config.contains("cast-particle") castParticle = config.contains("cast-particle")
? new CastingParticle(config.getConfigurationSection("cast-particle")) ? new CastingParticle(config.getConfigurationSection("cast-particle"))
: new CastingParticle(Particle.SPELL_INSTANT); : new CastingParticle(Particle.SPELL_INSTANT);
if (config.contains("options")) if (config.contains("options"))
for (String key : config.getConfigurationSection("options").getKeys(false)) for (String key : config.getConfigurationSection("options").getKeys(false))
try { try {
setOption(ClassOption.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_")), setOption(ClassOption.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_")),
config.getBoolean("options." + key)); config.getBoolean("options." + key));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not load option '" + key + "' from class '" + key + "': " + exception.getMessage()); "Could not load option '" + key + "' from class '" + key + "': " + exception.getMessage());
} }
if (config.contains("main-exp-sources")) if (config.contains("main-exp-sources")) {
for (String key : config.getStringList("main-exp-sources")) ExperienceDispenser dispenser = new MainExperienceDispenser(this);
try { for (String key : config.getStringList("main-exp-sources"))
ExperienceSource<?> source = MMOCore.plugin.loadManager.loadExperienceSource(new MMOLineConfig(key), try {
null); ExperienceSource<?> source = MMOCore.plugin.loadManager.loadExperienceSource(new MMOLineConfig(key), dispenser);
source.setClass(this); MMOCore.plugin.professionManager.registerExpSource(source);
MMOCore.plugin.professionManager.registerExpSource(source); } catch (IllegalArgumentException exception) {
} catch (IllegalArgumentException exception) { MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load exp source '" + key + "' from class '"
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load exp source '" + key + "' from class '" + id + "': " + exception.getMessage());
+ id + "': " + exception.getMessage()); }
} }
if (config.contains("triggers")) if (config.contains("triggers"))
for (String key : config.getConfigurationSection("triggers").getKeys(false)) { for (String key : config.getConfigurationSection("triggers").getKeys(false)) {
try { try {
String format = key.toLowerCase().replace("_", "-").replace(" ", "-"); String format = key.toLowerCase().replace("_", "-").replace(" ", "-");
eventTriggers.put(format, new EventTrigger(format, config.getStringList("triggers." + key))); eventTriggers.put(format, new EventTrigger(format, config.getStringList("triggers." + key)));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
MMOCore.log(Level.WARNING, "[PlayerClasses:" + id + "] " + exception.getMessage()); MMOCore.log(Level.WARNING, "[PlayerClasses:" + id + "] " + exception.getMessage());
} }
} }
/* /*
* must make sure all the resourceHandlers are registered when the placer class * must make sure all the resourceHandlers are registered when the placer class
* is initialized. * is initialized.
*/ */
for (PlayerResource resource : PlayerResource.values()) { for (PlayerResource resource : PlayerResource.values()) {
if (config.isConfigurationSection("resource." + resource.name().toLowerCase())) if (config.isConfigurationSection("resource." + resource.name().toLowerCase()))
try { try {
resourceHandlers.put(resource, new ResourceHandler(resource, resourceHandlers.put(resource, new ResourceHandler(resource,
config.getConfigurationSection("resource." + resource.name().toLowerCase()))); config.getConfigurationSection("resource." + resource.name().toLowerCase())));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
MMOCore.log(Level.WARNING, "[PlayerClasses:" + id + "] Could not load special resource regen for " MMOCore.log(Level.WARNING, "[PlayerClasses:" + id + "] Could not load special resource regen for "
+ resource.name() + ": " + exception.getMessage()); + resource.name() + ": " + exception.getMessage());
resourceHandlers.put(resource, new ResourceHandler(resource)); resourceHandlers.put(resource, new ResourceHandler(resource));
} }
else else
resourceHandlers.put(resource, new ResourceHandler(resource)); resourceHandlers.put(resource, new ResourceHandler(resource));
} }
} }
/* /*
* used to generate display class * used to generate display class
*/ */
public PlayerClass(String id, String name, Material material) { public PlayerClass(String id, String name, Material material) {
super(null); super(null);
this.id = id; this.id = id;
this.name = name; this.name = name;
manaDisplay = ManaDisplayOptions.DEFAULT; manaDisplay = ManaDisplayOptions.DEFAULT;
maxLevel = 0; maxLevel = 0;
displayOrder = 0; displayOrder = 0;
expCurve = ExpCurve.DEFAULT; expCurve = ExpCurve.DEFAULT;
castParticle = new CastingParticle(Particle.SPELL_INSTANT); castParticle = new CastingParticle(Particle.SPELL_INSTANT);
actionBarFormat = ""; actionBarFormat = "";
this.icon = new ItemStack(material); this.icon = new ItemStack(material);
setOption(ClassOption.DISPLAY, false); setOption(ClassOption.DISPLAY, false);
setOption(ClassOption.DEFAULT, false); setOption(ClassOption.DEFAULT, false);
for (PlayerResource resource : PlayerResource.values()) for (PlayerResource resource : PlayerResource.values())
resourceHandlers.put(resource, new ResourceHandler(resource)); resourceHandlers.put(resource, new ResourceHandler(resource));
} }
@Override @Override
protected void whenPostLoaded(ConfigurationSection config) { protected void whenPostLoaded(ConfigurationSection config) {
if (config.contains("subclasses")) if (config.contains("subclasses"))
for (String key : config.getConfigurationSection("subclasses").getKeys(false)) for (String key : config.getConfigurationSection("subclasses").getKeys(false))
try { try {
subclasses.add(new Subclass( subclasses.add(new Subclass(
MMOCore.plugin.classManager MMOCore.plugin.classManager
.getOrThrow(key.toUpperCase().replace("-", "_").replace(" ", "_")), .getOrThrow(key.toUpperCase().replace("-", "_").replace(" ", "_")),
config.getInt("subclasses." + key))); config.getInt("subclasses." + key)));
} catch (IllegalArgumentException exception) { } catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load subclass '" + key + "' from class '" MMOCore.plugin.getLogger().log(Level.WARNING, "Could not load subclass '" + key + "' from class '"
+ getId() + "': " + exception.getMessage()); + getId() + "': " + exception.getMessage());
} }
} }
public String getId() { public String getId() {
return id; return id;
} }
public String getName() { public String getName() {
return name; return name;
} }
public ManaDisplayOptions getManaDisplay() { public ManaDisplayOptions getManaDisplay() {
return manaDisplay; return manaDisplay;
} }
public ResourceHandler getHandler(PlayerResource resource) { public ResourceHandler getHandler(PlayerResource resource) {
return resourceHandlers.get(resource); return resourceHandlers.get(resource);
} }
public int getMaxLevel() { public int getMaxLevel() {
return maxLevel; return maxLevel;
} }
public int getDisplayOrder() { public int getDisplayOrder() {
return displayOrder; return displayOrder;
} }
public ExpCurve getExpCurve() { public ExpCurve getExpCurve() {
return expCurve; return expCurve;
} }
public ItemStack getIcon() { public ItemStack getIcon() {
return icon.clone(); return icon.clone();
} }
public CastingParticle getCastParticle() { public CastingParticle getCastParticle() {
return castParticle; return castParticle;
} }
public List<String> getDescription() { public List<String> getDescription() {
return description; return description;
} }
public List<String> getAttributeDescription() { public List<String> getAttributeDescription() {
return attrDescription; return attrDescription;
} }
public void setOption(ClassOption option, boolean value) { public void setOption(ClassOption option, boolean value) {
options.put(option, value); options.put(option, value);
} }
public boolean hasOption(ClassOption option) { public boolean hasOption(ClassOption option) {
return options.containsKey(option) ? options.get(option) : option.getDefault(); return options.containsKey(option) ? options.get(option) : option.getDefault();
} }
public void setStat(StatType type, double base, double perLevel) { public void setStat(StatType type, double base, double perLevel) {
stats.put(type, new LinearValue(base, perLevel)); stats.put(type, new LinearValue(base, perLevel));
} }
public double calculateStat(StatType stat, int level) { public double calculateStat(StatType stat, int level) {
return getStatInfo(stat).calculate(level); return getStatInfo(stat).calculate(level);
} }
public List<Subclass> getSubclasses() { public List<Subclass> getSubclasses() {
return subclasses; return subclasses;
} }
public boolean hasSkill(Skill skill) { public boolean hasSkill(Skill skill) {
return hasSkill(skill.getId()); return hasSkill(skill.getId());
} }
public boolean hasSkill(String id) { public boolean hasSkill(String id) {
return skills.containsKey(id); return skills.containsKey(id);
} }
public SkillInfo getSkill(Skill skill) { public SkillInfo getSkill(Skill skill) {
return getSkill(skill.getId()); return getSkill(skill.getId());
} }
/* /*
* reduces map checkups when skills are being checked on events that are * reduces map checkups when skills are being checked on events that are
* commonly called like EntityDamageEvent or regen events. * commonly called like EntityDamageEvent or regen events.
*/ */
public Optional<SkillInfo> findSkill(Skill skill) { public Optional<SkillInfo> findSkill(Skill skill) {
return skills.containsKey(skill.getId()) ? Optional.of(skills.get(skill.getId())) : Optional.empty(); return skills.containsKey(skill.getId()) ? Optional.of(skills.get(skill.getId())) : Optional.empty();
} }
public SkillInfo getSkill(String id) { public SkillInfo getSkill(String id) {
return skills.get(id); return skills.get(id);
} }
public Set<String> getEventTriggers() { public Set<String> getEventTriggers() {
return eventTriggers.keySet(); return eventTriggers.keySet();
} }
public boolean hasEventTriggers(String name) { public boolean hasEventTriggers(String name) {
return eventTriggers.containsKey(name); return eventTriggers.containsKey(name);
} }
public EventTrigger getEventTriggers(String name) { public EventTrigger getEventTriggers(String name) {
return eventTriggers.get(name); return eventTriggers.get(name);
} }
public Collection<SkillInfo> getSkills() { public Collection<SkillInfo> getSkills() {
return skills.values(); return skills.values();
} }
private LinearValue getStatInfo(StatType type) { private LinearValue getStatInfo(StatType type) {
return stats.containsKey(type) ? stats.get(type) : type.getDefault(); return stats.containsKey(type) ? stats.get(type) : type.getDefault();
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return obj instanceof PlayerClass && ((PlayerClass) obj).id.equals(id); return obj instanceof PlayerClass && ((PlayerClass) obj).id.equals(id);
} }
public String getActionBar() { public String getActionBar() {
return actionBarFormat; return actionBarFormat;
} }
public boolean hasActionBar() { public boolean hasActionBar() {
return actionBarFormat != null; return actionBarFormat != null;
} }
} }

View File

@ -2,7 +2,7 @@ package net.Indyuce.mmocore.api.player.stats;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigFile; import net.Indyuce.mmocore.api.ConfigFile;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.util.math.formula.LinearValue; import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.MythicLib;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;

View File

@ -12,7 +12,7 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.objective.Objective; import net.Indyuce.mmocore.api.quest.objective.Objective;
import io.lumine.mythic.lib.api.MMOLineConfig; import io.lumine.mythic.lib.api.MMOLineConfig;

View File

@ -3,9 +3,9 @@ package net.Indyuce.mmocore.api.quest.trigger;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.EXPSource; import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.api.experience.ExperienceInfo; import net.Indyuce.mmocore.experience.ExperienceInfo;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount; import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
import io.lumine.mythic.lib.api.MMOLineConfig; import io.lumine.mythic.lib.api.MMOLineConfig;

View File

@ -8,9 +8,9 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.EXPSource; import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.api.experience.PlayerProfessions; import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.CommandVerbose; import net.Indyuce.mmocore.command.CommandVerbose;
import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot; import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot;

View File

@ -6,7 +6,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode; import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode;
import io.lumine.mythic.lib.mmolibcommands.api.Parameter; import io.lumine.mythic.lib.mmolibcommands.api.Parameter;

View File

@ -9,9 +9,9 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.EXPSource; import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.api.experience.PlayerProfessions; import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot; import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot;
import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode; import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode;

View File

@ -6,7 +6,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes.AttributeInstance; import net.Indyuce.mmocore.api.player.attribute.PlayerAttributes.AttributeInstance;
import net.Indyuce.mmocore.command.CommandVerbose; import net.Indyuce.mmocore.command.CommandVerbose;

View File

@ -9,8 +9,8 @@ import org.bukkit.command.CommandSender;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.ConfigMessage;
import net.Indyuce.mmocore.api.experience.Booster; import net.Indyuce.mmocore.experience.Booster;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot; import net.Indyuce.mmocore.command.MMOCoreCommandTreeRoot;
import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode; import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode;
import io.lumine.mythic.lib.mmolibcommands.api.Parameter; import io.lumine.mythic.lib.mmolibcommands.api.Parameter;

View File

@ -5,7 +5,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Booster; import net.Indyuce.mmocore.experience.Booster;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat; import net.Indyuce.mmocore.api.util.math.format.DelayFormat;
import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode; import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode;

View File

@ -7,7 +7,7 @@ import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Booster; import net.Indyuce.mmocore.experience.Booster;
import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode; import io.lumine.mythic.lib.mmolibcommands.api.CommandTreeNode;
import io.lumine.mythic.lib.mmolibcommands.api.Parameter; import io.lumine.mythic.lib.mmolibcommands.api.Parameter;

View File

@ -1,9 +1,10 @@
package net.Indyuce.mmocore.comp.mythicmobs; package net.Indyuce.mmocore.comp.mythicmobs;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource; import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.load.MMOLoader; import net.Indyuce.mmocore.api.load.MMOLoader;
import net.Indyuce.mmocore.api.quest.objective.Objective; import net.Indyuce.mmocore.api.quest.objective.Objective;
import net.Indyuce.mmocore.api.quest.trigger.Trigger; import net.Indyuce.mmocore.api.quest.trigger.Trigger;
@ -37,12 +38,12 @@ public class MythicMobsMMOLoader extends MMOLoader {
} }
@Override @Override
public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, Profession profession) { public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, ExperienceDispenser dispenser) {
if (config.getKey().equalsIgnoreCase("killmythicmob")) if (config.getKey().equalsIgnoreCase("killmythicmob"))
return new KillMythicMobExperienceSource(profession, config); return new KillMythicMobExperienceSource(dispenser, config);
if (config.getKey().equalsIgnoreCase("killmythicfaction")) if (config.getKey().equalsIgnoreCase("killmythicfaction"))
return new KillMythicFactionExperienceSource(profession, config); return new KillMythicFactionExperienceSource(dispenser, config);
return null; return null;
} }

View File

@ -1,48 +1,47 @@
package net.Indyuce.mmocore.comp.mythicmobs.load; package net.Indyuce.mmocore.comp.mythicmobs.load;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class KillMythicFactionExperienceSource extends SpecificExperienceSource<String> { public class KillMythicFactionExperienceSource extends SpecificExperienceSource<String> {
private final String factionName; private final String factionName;
public KillMythicFactionExperienceSource(Profession profession, MMOLineConfig config) { public KillMythicFactionExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(profession, config); super(dispenser, config);
config.validate("name"); config.validate("name");
factionName = config.getString("name"); factionName = config.getString("name");
} }
@Override @Override
public ExperienceManager<KillMythicFactionExperienceSource> newManager() { public ExperienceSourceManager<KillMythicFactionExperienceSource> newManager() {
return new ExperienceManager<KillMythicFactionExperienceSource>() { return new ExperienceSourceManager<KillMythicFactionExperienceSource>() {
@EventHandler @EventHandler
public void a(MythicMobDeathEvent event) { public void a(MythicMobDeathEvent event) {
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> { Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> {
if (!event.getEntity().isDead()) return; if (!event.getEntity().isDead()) return;
if (!event.getMob().hasFaction()) return; if (!event.getMob().hasFaction()) return;
if (!(event.getKiller() instanceof Player) || event.getKiller().hasMetadata("NPC")) return; if (!(event.getKiller() instanceof Player) || event.getKiller().hasMetadata("NPC")) return;
PlayerData data = PlayerData.get((Player) event.getKiller()); PlayerData data = PlayerData.get((Player) event.getKiller());
for (KillMythicFactionExperienceSource source : getSources()) for (KillMythicFactionExperienceSource source : getSources())
if (source.matches(data, event.getMob().getFaction())) if (source.matches(data, event.getMob().getFaction()))
source.giveExperience(data, 1, event.getEntity().getLocation()); source.giveExperience(data, 1, event.getEntity().getLocation());
}, 2); }, 2);
} }
}; };
} }
@Override @Override
public boolean matches(PlayerData player, String name) { public boolean matchesParameter(PlayerData player, String name) {
return hasRightClass(player) && name.equals(factionName); return name.equals(factionName);
} }
} }

View File

@ -1,47 +1,46 @@
package net.Indyuce.mmocore.comp.mythicmobs.load; package net.Indyuce.mmocore.comp.mythicmobs.load;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceManager;
import io.lumine.mythic.lib.api.MMOLineConfig;
public class KillMythicMobExperienceSource extends SpecificExperienceSource<String> { public class KillMythicMobExperienceSource extends SpecificExperienceSource<String> {
private final String internalName; private final String internalName;
public KillMythicMobExperienceSource(Profession profession, MMOLineConfig config) { public KillMythicMobExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(profession, config); super(dispenser, config);
config.validate("type"); config.validate("type");
internalName = config.getString("type"); internalName = config.getString("type");
} }
@Override @Override
public ExperienceManager<KillMythicMobExperienceSource> newManager() { public ExperienceSourceManager<KillMythicMobExperienceSource> newManager() {
return new ExperienceManager<KillMythicMobExperienceSource>() { return new ExperienceSourceManager<KillMythicMobExperienceSource>() {
@EventHandler @EventHandler
public void a(MythicMobDeathEvent event) { public void a(MythicMobDeathEvent event) {
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> { Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> {
if (!event.getEntity().isDead()) return; if (!event.getEntity().isDead()) return;
if (!(event.getKiller() instanceof Player) || event.getKiller().hasMetadata("NPC")) return; if (!(event.getKiller() instanceof Player) || event.getKiller().hasMetadata("NPC")) return;
PlayerData data = PlayerData.get((Player) event.getKiller()); PlayerData data = PlayerData.get((Player) event.getKiller());
for (KillMythicMobExperienceSource source : getSources()) for (KillMythicMobExperienceSource source : getSources())
if (source.matches(data, event.getMobType().getInternalName())) if (source.matches(data, event.getMobType().getInternalName()))
source.giveExperience(data, 1, event.getEntity().getLocation()); source.giveExperience(data, 1, event.getEntity().getLocation());
}, 2); }, 2);
} }
}; };
} }
@Override @Override
public boolean matches(PlayerData player, String name) { public boolean matchesParameter(PlayerData player, String name) {
return hasRightClass(player) && name.equals(internalName); return name.equals(internalName);
} }
} }

View File

@ -4,8 +4,8 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.util.AltChar; import io.lumine.mythic.lib.api.util.AltChar;
import me.clip.placeholderapi.expansion.PlaceholderExpansion; import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.PlayerProfessions; import net.Indyuce.mmocore.experience.PlayerProfessions;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.StatType; import net.Indyuce.mmocore.api.player.stats.StatType;
import net.Indyuce.mmocore.api.quest.PlayerQuests; import net.Indyuce.mmocore.api.quest.PlayerQuests;

View File

@ -1,4 +1,4 @@
package net.Indyuce.mmocore.api.experience; package net.Indyuce.mmocore.experience;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;

View File

@ -1,4 +1,4 @@
package net.Indyuce.mmocore.api.experience; package net.Indyuce.mmocore.experience;
public enum EXPSource { public enum EXPSource {
SOURCE, SOURCE,

View File

@ -1,76 +1,76 @@
package net.Indyuce.mmocore.api.experience; package net.Indyuce.mmocore.experience;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
public class ExpCurve { public class ExpCurve {
private final String id; private final String id;
/** /**
* Experience needed to level up. Different professions or classes can have * Experience needed to level up. Different professions or classes can have
* different exp curves so that it is easier to balance. * different exp curves so that it is easier to balance.
*/ */
private final List<Integer> experience = new ArrayList<>(); private final List<Integer> experience = new ArrayList<>();
/** /**
* Purely arbitrary but MMOCore needs a default exp curve for everything * Purely arbitrary but MMOCore needs a default exp curve for everything
* otherwise there might be divisions by 0 when trying to update the vanilla * otherwise there might be divisions by 0 when trying to update the vanilla
* exp bar which requires a 0.0 -> 1.0 float as parameter * exp bar which requires a 0.0 -> 1.0 float as parameter
*/ */
public static final ExpCurve DEFAULT = new ExpCurve("default", 100, 200, 300, 400, 500); public static final ExpCurve DEFAULT = new ExpCurve("default", 100, 200, 300, 400, 500);
/** /**
* Reads an exp curve from a text file, one line after the other. Each exp * Reads an exp curve from a text file, one line after the other. Each exp
* value has to be the only thing written on every line * value has to be the only thing written on every line
* *
* @param file Text file to read data from * @param file Text file to read data from
* @throws IOException IO exception when reading file * @throws IOException IO exception when reading file
*/ */
public ExpCurve(File file) throws IOException { public ExpCurve(File file) throws IOException {
this.id = file.getName().replace(".txt", "").toLowerCase().replace("_", "-").replace(" ", "-"); this.id = file.getName().replace(".txt", "").toLowerCase().replace("_", "-").replace(" ", "-");
BufferedReader reader = new BufferedReader(new FileReader(file)); BufferedReader reader = new BufferedReader(new FileReader(file));
String readLine; String readLine;
while ((readLine = reader.readLine()) != null) while ((readLine = reader.readLine()) != null)
experience.add(Integer.valueOf(readLine)); experience.add(Integer.valueOf(readLine));
reader.close(); reader.close();
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve"); Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
} }
/** /**
* Public constructor for external plugins * Public constructor for external plugins
* *
* @param id Some unique identifier to let other plugin features refer * @param id Some unique identifier to let other plugin features refer
* to your exp curve. * to your exp curve.
* @param values The exp values, at to be at least one or the constructor * @param values The exp values, at to be at least one or the constructor
* will throw an error * will throw an error
*/ */
public ExpCurve(String id, int... values) { public ExpCurve(String id, int... values) {
this.id = id; this.id = id;
for (int value : values) for (int value : values)
experience.add(value); experience.add(value);
Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve"); Validate.isTrue(!experience.isEmpty(), "There must be at least one exp value in your exp curve");
} }
public String getId() { public String getId() {
return id; return id;
} }
/** /**
* @param level Level being reached by some player * @param level Level being reached by some player
* @return Experience needed to reach provided level. The level serves * @return Experience needed to reach provided level. The level serves
* an index for a list checkup. If the level is higher than * an index for a list checkup. If the level is higher than
* the list size, it just returns the last value of the list * the list size, it just returns the last value of the list
*/ */
public int getExperience(int level) { public int getExperience(int level) {
Validate.isTrue(level > 0, "Level must be stricly positive"); Validate.isTrue(level > 0, "Level must be stricly positive");
return experience.get(Math.min(level, experience.size()) - 1); return experience.get(Math.min(level, experience.size()) - 1);
} }
} }

View File

@ -1,4 +1,4 @@
package net.Indyuce.mmocore.api.experience; package net.Indyuce.mmocore.experience;
public class ExperienceInfo { public class ExperienceInfo {
private final Profession profess; private final Profession profess;

View File

@ -1,4 +1,4 @@
package net.Indyuce.mmocore.api.experience; package net.Indyuce.mmocore.experience;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
@ -128,7 +128,7 @@ public class PlayerProfessions {
return profession.hasMaxLevel() && getLevel(profession) >= profession.getMaxLevel(); return profession.hasMaxLevel() && getLevel(profession) >= profession.getMaxLevel();
} }
public void giveExperience(Profession profession, int value, EXPSource source, @Nullable Location hologramLocation) { public void giveExperience(Profession profession, double value, EXPSource source, @Nullable Location hologramLocation) {
if (hasReachedMaxLevel(profession)) { if (hasReachedMaxLevel(profession)) {
setExperience(profession, 0); setExperience(profession, 0);
return; return;
@ -140,12 +140,12 @@ public class PlayerProfessions {
if (hologramLocation != null && playerData.isOnline()) if (hologramLocation != null && playerData.isOnline())
MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), MMOCore.plugin.configManager.getSimpleMessage("exp-hologram", "exp", "" + value).message()); MMOCoreUtils.displayIndicator(hologramLocation.add(.5, 1.5, .5), MMOCore.plugin.configManager.getSimpleMessage("exp-hologram", "exp", "" + value).message());
PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(playerData, profession, value, source); PlayerExperienceGainEvent event = new PlayerExperienceGainEvent(playerData, profession, (int) value, source);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) if (event.isCancelled())
return; return;
exp.put(profession.getId(), exp.containsKey(profession.getId()) ? exp.get(profession.getId()) + value : value); exp.put(profession.getId(), exp.containsKey(profession.getId()) ? exp.get(profession.getId()) + event.getExperience() : event.getExperience());
int needed, exp, level, oldLevel = getLevel(profession); int needed, exp, level, oldLevel = getLevel(profession);
/* /*

View File

@ -0,0 +1,191 @@
package net.Indyuce.mmocore.experience;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.util.PostLoadObject;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.util.math.formula.LinearValue;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.provider.ProfessionExperienceDispenser;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.potion.PotionType;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
public class Profession extends PostLoadObject {
private final String id, name;
private final ExpCurve expCurve;
private final int maxLevel;
private final Map<ProfessionOption, Boolean> options = new HashMap<>();
/*
* experience given to the main player level whenever he levels up this
* profession
*/
private final LinearValue experience;
public Profession(String id, FileConfiguration config) {
super(config);
this.id = id.toLowerCase().replace("_", "-").replace(" ", "-");
this.name = config.getString("name");
Validate.notNull(name, "Could not load name");
expCurve = config.contains("exp-curve")
? MMOCore.plugin.experience.getOrThrow(config.get("exp-curve").toString().toLowerCase().replace("_", "-").replace(" ", "-"))
: ExpCurve.DEFAULT;
experience = new LinearValue(config.getConfigurationSection("experience"));
if (config.contains("options"))
for (String key : config.getConfigurationSection("options").getKeys(false))
try {
ProfessionOption option = ProfessionOption.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_"));
options.put(option, config.getBoolean("options." + key));
} catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not load option '" + key + "' from profession '" + id + "': " + exception.getMessage());
}
maxLevel = config.getInt("max-level");
if (config.contains("exp-sources")) {
ExperienceDispenser dispenser = new ProfessionExperienceDispenser(this);
for (String key : config.getStringList("exp-sources"))
try {
MMOCore.plugin.professionManager.registerExpSource(MMOCore.plugin.loadManager.loadExperienceSource(new MMOLineConfig(key), dispenser));
} catch (IllegalArgumentException exception) {
MMOCore.plugin.getLogger().log(Level.WARNING,
"Could not register exp source '" + key + "' from profession '" + id + "': " + exception.getMessage());
}
}
}
/*
* drop tables must be loaded after professions are initialized
*/
@Override
protected void whenPostLoaded(ConfigurationSection config) {
if (config.contains("on-fish"))
MMOCore.plugin.fishingManager.loadDropTables(config.getConfigurationSection("on-fish"));
if (config.contains("on-mine"))
MMOCore.plugin.mineManager.loadDropTables(config.getConfigurationSection("on-mine"));
if (config.contains("alchemy-experience")) {
MMOCore.plugin.alchemyManager.splash = 1 + config.getDouble("alchemy-experience.special.splash") / 100;
MMOCore.plugin.alchemyManager.lingering = 1 + config.getDouble("alchemy-experience.special.lingering") / 100;
MMOCore.plugin.alchemyManager.extend = 1 + config.getDouble("alchemy-experience.special.extend") / 100;
MMOCore.plugin.alchemyManager.upgrade = 1 + config.getDouble("alchemy-experience.special.upgrade") / 100;
for (String key : config.getConfigurationSection("alchemy-experience.effects").getKeys(false))
try {
PotionType type = PotionType.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_"));
MMOCore.plugin.alchemyManager.registerBaseExperience(type, config.getDouble("alchemy-experience.effects." + key));
} catch (IllegalArgumentException exception) {
MMOCore.log(Level.WARNING, "[PlayerProfessions:" + id + "] Could not read potion type from " + key);
}
}
if (config.contains("base-enchant-exp"))
for (String key : config.getConfigurationSection("base-enchant-exp").getKeys(false))
try {
Enchantment enchant = MythicLib.plugin.getVersion().getWrapper().getEnchantmentFromString(key.toLowerCase().replace("-", "_"));
MMOCore.plugin.enchantManager.registerBaseExperience(enchant, config.getDouble("base-enchant-exp." + key));
} catch (IllegalArgumentException exception) {
MMOCore.log(Level.WARNING, "[PlayerProfessions:" + id + "] Could not read enchant from " + key);
}
if (config.contains("repair-exp"))
for (String key : config.getConfigurationSection("repair-exp").getKeys(false))
try {
Material material = Material.valueOf(key.toUpperCase().replace("-", "_").replace(" ", "_"));
MMOCore.plugin.smithingManager.registerBaseExperience(material, config.getDouble("repair-exp." + key));
} catch (IllegalArgumentException exception) {
MMOCore.log(Level.WARNING, "[PlayerProfessions:" + id + "] Could not read material from " + key);
}
// if (config.contains("effect-weight"))
// for (String key :
// config.getConfigurationSection("effect-weight").getKeys(false))
// try {
// MMOCore.plugin.alchemyManager.registerEffectWeight(PotionEffectType.getByName(key.toUpperCase().replace("-",
// "_").replace(" ", "_")), config.getDouble("effect-weight." + key));
// } catch (IllegalArgumentException exception) {
// MMOCore.log(Level.WARNING, "[PlayerProfessions:" + id + "] Could not
// read
// potion effect type from " + key);
// }
}
public boolean getOption(ProfessionOption option) {
return options.getOrDefault(option, option.getDefault());
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public ExpCurve getExpCurve() {
return expCurve;
}
public int getMaxLevel() {
return maxLevel;
}
public boolean hasMaxLevel() {
return maxLevel > 0;
}
public int calculateExperience(int x) {
return (int) experience.calculate(x);
}
public LinearValue getExperience() {
return experience;
}
public static enum ProfessionOption {
/**
* When disabled, removes exp holograms when mined
*/
EXP_HOLOGRAMS(true);
private final boolean def;
private ProfessionOption(boolean def) {
this.def = def;
}
public boolean getDefault() {
return def;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Profession that = (Profession) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}

View File

@ -0,0 +1,30 @@
package net.Indyuce.mmocore.experience.provider;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.Location;
import org.jetbrains.annotations.Nullable;
/**
* Used to differenciate between the main class experience
* and experience given in a specific profession
*/
public interface ExperienceDispenser {
/**
* Called when experience is gained in main class/profession
*
* @param playerData Player gaining the experience
* @param experience Experience gained. Note that it is a double
* because it gets converted to an integer at
* the very last moment in MMOCore
* @param hologramLocation Location of displayed hologram, nothing
* is displayed if it's null
*/
void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation);
boolean matches(PlayerData playerData);
default Location getPlayerLocation(PlayerData player) {
return player.isOnline() ? player.getPlayer().getLocation() : null;
}
}

View File

@ -0,0 +1,29 @@
package net.Indyuce.mmocore.experience.provider;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.PlayerClass;
import net.Indyuce.mmocore.experience.EXPSource;
import org.bukkit.Location;
import org.jetbrains.annotations.Nullable;
public class MainExperienceDispenser implements ExperienceDispenser {
private final PlayerClass profess;
public MainExperienceDispenser(PlayerClass profess) {
this.profess = profess;
}
@Override
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation) {
hologramLocation = !MMOCore.plugin.getConfig().getBoolean("display-main-class-exp-holograms") ? null
: hologramLocation == null ? getPlayerLocation(playerData) : hologramLocation;
playerData.giveExperience(experience, EXPSource.SOURCE, hologramLocation);
}
@Override
public boolean matches(PlayerData playerData) {
return playerData.getProfess().equals(profess);
}
}

View File

@ -0,0 +1,27 @@
package net.Indyuce.mmocore.experience.provider;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData;
import org.bukkit.Location;
import org.jetbrains.annotations.Nullable;
public class ProfessionExperienceDispenser implements ExperienceDispenser {
private final Profession profession;
public ProfessionExperienceDispenser(Profession profession) {
this.profession = profession;
}
@Override
public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation) {
hologramLocation = !profession.getOption(Profession.ProfessionOption.EXP_HOLOGRAMS) ? null
: hologramLocation == null ? getPlayerLocation(playerData) : hologramLocation;
playerData.getCollectionSkills().giveExperience(profession, experience, EXPSource.SOURCE, hologramLocation);
}
@Override
public boolean matches(PlayerData playerData) {
return true;
}
}

View File

@ -0,0 +1,170 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.BrewEvent;
import org.bukkit.inventory.BrewerInventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionType;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class BrewPotionExperienceSource extends ExperienceSource<PotionMeta> {
private final List<PotionType> types = new ArrayList<>();
public BrewPotionExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser);
if (config.contains("effect"))
for (String key : config.getString("effect").split(","))
types.add(PotionType.valueOf(key.toUpperCase().replace("-", "_")));
}
@Override
public boolean matchesParameter(PlayerData player, PotionMeta meta) {
return types.isEmpty() || new ArrayList<>(types).stream().anyMatch(type -> meta.getBasePotionData().getType() == type);
}
@Override
public ExperienceSourceManager<BrewPotionExperienceSource> newManager() {
return new ExperienceSourceManager<BrewPotionExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(BrewEvent event) {
Optional<Player> playerOpt = getNearbyPlayer(event.getBlock().getLocation());
if (!playerOpt.isPresent())
return;
final ItemStack found = findPotion(event.getContents());
if (found != null)
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOCore.plugin, () -> {
ItemStack brewn = findPotion(event.getContents());
if (brewn == null)
return;
PlayerData data = PlayerData.get(playerOpt.get());
for (BrewPotionExperienceSource source : getSources())
if (source.matches(data, (PotionMeta) brewn.getItemMeta()))
new PotionUpgrade(found, brewn).process(data.getPlayer());
});
}
};
}
private ItemStack findPotion(BrewerInventory inv) {
for (int j = 0; j < 3; j++) {
ItemStack item = inv.getItem(j);
if (item != null && item.hasItemMeta() && item.getItemMeta() instanceof PotionMeta)
return item;
}
return null;
}
private Optional<Player> getNearbyPlayer(Location loc) {
return loc.getWorld().getPlayers().stream().filter(player -> player.getLocation().distanceSquared(loc) < 100).findAny();
}
public class PotionUpgrade {
/*
* if the potion was extended using redstone or upgraded using
* glowstone. PREPARE corresponds to when a water bottle is prepared for
* later recipes using NETHER STALK
*/
private double exp;
// private final PotionMeta old, brewn;
public PotionUpgrade(ItemStack old, ItemStack brewn) {
this(old.getType(), (PotionMeta) old.getItemMeta(), brewn.getType(), (PotionMeta) brewn.getItemMeta());
}
public PotionUpgrade(Material oldPot, PotionMeta old, Material brewnPot, PotionMeta brewn) {
// this.old = old;
// this.brewn = brewn;
/*
* calculate base exp
*/
exp += MMOCore.plugin.alchemyManager.getBaseExperience(brewn.getBasePotionData().getType());
// !old.getBasePotionData().getType().isUpgradeable() &&
// brewn.getBasePotionData().getType().isUpgradeable(),
//
// !old.getBasePotionData().isExtended() &&
// brewn.getBasePotionData().isExtended(),
//
// !old.getBasePotionData().isUpgraded() &&
// brewn.getBasePotionData().isUpgraded());
/*
* EXP modifiers based on brewing conditions
*/
if (oldPot == Material.POTION && brewnPot == Material.SPLASH_POTION)
exp *= MMOCore.plugin.alchemyManager.splash;
if (oldPot == Material.POTION && brewnPot == Material.LINGERING_POTION)
exp *= MMOCore.plugin.alchemyManager.lingering;
if (!old.getBasePotionData().isExtended() && brewn.getBasePotionData().isExtended())
exp *= MMOCore.plugin.alchemyManager.extend;
if (!old.getBasePotionData().isUpgraded() && brewn.getBasePotionData().isUpgraded())
exp *= MMOCore.plugin.alchemyManager.upgrade;
}
// private Map<PotionEffectType, Double> mapEffectDurations() {
// Map<PotionEffectType, Double> map = new HashMap<>();
//
// /*
// * potion level, plus the potion gained duration (max 0 so it does
// * not give negative EXP), multiplied by the potion effect weight.
// */
// brewn.getCustomEffects().forEach(effect -> map.put(effect.getType(),
//
// (effect.getAmplifier() + 1 + (double) Math.max(0,
// effect.getDuration() - getPotionEffect(old,
// effect.getType()).orElseGet(() -> new
// PotionEffect(PotionEffectType.SPEED, 0, 0)).getDuration()) / 60.)
//
// * MMOCore.plugin.alchemyManager.getWeight(effect.getType())));
//
// return map;
// }
// private int getTotal(Map<?, Double> map) {
// double t = 0;
// for (double d : map.values())
// t += d;
// return (int) t;
// }
// private Optional<PotionEffect> getPotionEffect(PotionMeta meta,
// PotionEffectType type) {
// return meta.getCustomEffects().stream().filter(effect ->
// effect.getType() == type).findFirst();
// }
public void process(Player player) {
/*
* calculate extra exp due to extra effects
*/
// exp += getTotal(mapEffectDurations());
getDispenser().giveExperience(PlayerData.get(player), (int) exp, null);
}
}
}

View File

@ -0,0 +1,44 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.InventoryAction;
public class CraftItemExperienceSource extends SpecificExperienceSource<Material> {
public final Material material;
public CraftItemExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceSourceManager<CraftItemExperienceSource> newManager() {
return new ExperienceSourceManager<CraftItemExperienceSource>() {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void a(CraftItemEvent event) {
if (event.getAction() == InventoryAction.NOTHING ||
event.getInventory().getResult() == null) return;
PlayerData data = PlayerData.get((Player) event.getWhoClicked());
for (CraftItemExperienceSource source : getSources())
if (source.matches(data, event.getInventory().getResult().getType()))
source.giveExperience(data, event.getInventory().getResult().getAmount(), event.getInventory().getLocation());
}
};
}
@Override
public boolean matchesParameter(PlayerData player, Material obj) {
return material == obj;
}
}

View File

@ -0,0 +1,62 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.enchantment.EnchantItemEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class EnchantItemExperienceSource extends ExperienceSource<Void> {
private final List<Enchantment> enchants = new ArrayList<>();
public EnchantItemExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser);
if (config.contains("enchant"))
for (String key : config.getString("enchant").split(","))
enchants.add(MythicLib.plugin.getVersion().getWrapper().getEnchantmentFromString(key.toLowerCase().replace("-", "_")));
}
@Override
public boolean matchesParameter(PlayerData player, Void v) {
return true;
}
@Override
public ExperienceSourceManager<EnchantItemExperienceSource> newManager() {
return new ExperienceSourceManager<EnchantItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(EnchantItemEvent event) {
PlayerData player = PlayerData.get(event.getEnchanter());
for (EnchantItemExperienceSource source : getSources())
if (source.matches(player, null)) {
Map<Enchantment, Integer> ench = new HashMap<>(event.getEnchantsToAdd());
if (!source.enchants.isEmpty())
ench.keySet().removeIf(enchantment -> !source.enchants.contains(enchantment));
if (ench.isEmpty())
continue;
double exp = 0;
for (Entry<Enchantment, Integer> entry : ench.entrySet())
exp += MMOCore.plugin.enchantManager.getBaseExperience(entry.getKey()) * entry.getValue();
getDispenser().giveExperience(player, (int) exp, event.getEnchantBlock().getLocation());
}
}
};
}
}

View File

@ -0,0 +1,50 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Material;
import org.bukkit.entity.Item;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerFishEvent.State;
import org.bukkit.inventory.ItemStack;
public class FishItemExperienceSource extends SpecificExperienceSource<ItemStack> {
private final Material material;
public FishItemExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceSourceManager<FishItemExperienceSource> newManager() {
return new ExperienceSourceManager<FishItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(PlayerFishEvent event) {
if (event.getState() == State.CAUGHT_FISH) {
ItemStack caught = ((Item) event.getCaught()).getItemStack();
if (caught.hasItemMeta())
return;
PlayerData data = PlayerData.get(event.getPlayer());
for (FishItemExperienceSource source : getSources())
if (source.matches(data, caught))
source.giveExperience(data, caught.getAmount(), event.getHook().getLocation().add(0, 1.0f, 0));
}
}
};
}
@Override
public boolean matchesParameter(PlayerData player, ItemStack obj) {
return obj.getType() == material;
}
}

View File

@ -0,0 +1,50 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.event.EntityKillEntityEvent;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
public class KillMobExperienceSource extends SpecificExperienceSource<Entity> {
public final EntityType type;
public KillMobExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
config.validate("type");
type = EntityType.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceSourceManager<KillMobExperienceSource> newManager() {
return new ExperienceSourceManager<KillMobExperienceSource>() {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void a(EntityKillEntityEvent event) {
Bukkit.getScheduler().runTaskLater(MMOCore.plugin, () -> {
if (event.getTarget().isDead() && event.getEntity() instanceof Player && !event.getEntity().hasMetadata("NPC")
&& !event.getTarget().hasMetadata("spawner_spawned")) {
PlayerData data = PlayerData.get((Player) event.getEntity());
for (KillMobExperienceSource source : getSources())
if (source.matches(data, event.getTarget()))
source.giveExperience(data, 1, event.getTarget().getLocation());
}
}, 2);
}
};
}
@Override
public boolean matchesParameter(PlayerData player, Entity obj) {
return obj.getType() == type;
}
}

View File

@ -0,0 +1,66 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
public class MineBlockExperienceSource extends SpecificExperienceSource<Material> {
public final Material material;
private final boolean silkTouch;
private final boolean crop;
private final boolean playerPlaced;
public MineBlockExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
silkTouch = config.getBoolean("silk-touch", true);
crop = config.getBoolean("crop", false);
playerPlaced = config.getBoolean("player-placed", false);
}
@Override
public ExperienceSourceManager<MineBlockExperienceSource> newManager() {
return new ExperienceSourceManager<MineBlockExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(BlockBreakEvent event) {
if (event.getPlayer().getGameMode() != GameMode.SURVIVAL)
return;
PlayerData data = PlayerData.get(event.getPlayer());
for (MineBlockExperienceSource source : getSources()) {
if (source.silkTouch && hasSilkTouch(event.getPlayer().getInventory().getItemInMainHand()))
continue;
if (source.crop && !MythicLib.plugin.getVersion().getWrapper().isCropFullyGrown(event.getBlock()))
continue;
if ((!source.playerPlaced) && event.getBlock().hasMetadata("player_placed"))
continue;
if (source.matches(data, event.getBlock().getType()))
source.giveExperience(data, 1, event.getBlock().getLocation());
}
}
};
}
private boolean hasSilkTouch(ItemStack item) {
return item != null && item.hasItemMeta() && item.getItemMeta().hasEnchant(Enchantment.SILK_TOUCH);
}
@Override
public boolean matchesParameter(PlayerData player, Material obj) {
return material == obj;
}
}

View File

@ -0,0 +1,45 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPlaceEvent;
public class PlaceBlockExperienceSource extends SpecificExperienceSource<Material> {
public final Material material;
public PlaceBlockExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceSourceManager<PlaceBlockExperienceSource> newManager() {
return new ExperienceSourceManager<PlaceBlockExperienceSource>() {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void a(BlockPlaceEvent event) {
if (event.getPlayer().getGameMode() != GameMode.SURVIVAL)
return;
PlayerData data = PlayerData.get(event.getPlayer());
for (PlaceBlockExperienceSource source : getSources())
if (source.matches(data, event.getBlock().getType()))
source.giveExperience(data, 1, event.getBlock().getLocation());
}
};
}
@Override
public boolean matchesParameter(PlayerData player, Material obj) {
return material == obj;
}
}

View File

@ -0,0 +1,83 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
public class RepairItemExperienceSource extends ExperienceSource<ItemStack> {
private final Material material;
public RepairItemExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser);
/*
* if material is null, the player can repair ANY material in order to
* get experience.
*/
material = config.contains("type") ? Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_")) : null;
}
@Override
public boolean matchesParameter(PlayerData player, ItemStack item) {
return (material == null || item.getType() == material);
}
@Override
public ExperienceSourceManager<RepairItemExperienceSource> newManager() {
return new ExperienceSourceManager<RepairItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(InventoryClickEvent event) {
if (event.getInventory() != null && event.getInventory().getType() == InventoryType.ANVIL && event.getSlot() == 2) {
ItemStack item = event.getCurrentItem();
PlayerData data = PlayerData.get((Player) event.getWhoClicked());
for (RepairItemExperienceSource source : getSources())
if (source.matches(data, item)) {
if (!(event.getInventory() instanceof AnvilInventory))
return;
if (((AnvilInventory) event.getInventory()).getRepairCost() > ((Player) event.getWhoClicked()).getLevel())
return;
/*
* make sure the items can actually be repaired
* before getting the amount of durability repaired
*/
ItemStack old = event.getInventory().getItem(0);
if (old == null || old.getType() == Material.AIR)
return;
if (old.getType().getMaxDurability() < 30 || item.getType().getMaxDurability() < 10)
return;
if (!MMOCore.plugin.smithingManager.hasExperience(item.getType()))
continue;
/*
* calculate exp based on amount of durability which
* was repaired, substract damage from old item
* durability.
*/
double exp = MMOCore.plugin.smithingManager.getBaseExperience(item.getType())
* Math.max(0, ((Damageable) old.getItemMeta()).getDamage() - ((Damageable) item.getItemMeta()).getDamage()) / 100;
getDispenser().giveExperience(data, (int) exp, null);
}
}
}
};
}
}

View File

@ -0,0 +1,69 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockCookEvent;
import org.bukkit.inventory.ItemStack;
import java.util.Optional;
public class SmeltItemExperienceSource extends SpecificExperienceSource<ItemStack> {
private final Material material;
public SmeltItemExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
config.validate("type");
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
}
@Override
public ExperienceSourceManager<SmeltItemExperienceSource> newManager() {
return new ExperienceSourceManager<SmeltItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void a(BlockCookEvent event) {
Optional<Player> player = getNearestPlayer(event.getBlock().getLocation());
if (!player.isPresent())
return;
ItemStack caught = event.getResult();
if (caught.hasItemMeta())
return;
PlayerData data = PlayerData.get(player.get());
for (SmeltItemExperienceSource source : getSources())
if (source.matches(data, caught))
source.giveExperience(data, 1, event.getBlock().getLocation());
}
};
}
private Optional<Player> getNearestPlayer(Location loc) {
final Player[] nearby = loc.getWorld().getPlayers().stream().filter(player -> player.getLocation().distanceSquared(loc) < 100)
.toArray(Player[]::new);
Player selected = null;
double lastDist = 100;
for (Player p : nearby) {
double currDist = p.getLocation().distance(loc);
if (currDist < lastDist) {
lastDist = currDist;
selected = p;
}
}
return Optional.ofNullable(selected);
}
@Override
public boolean matchesParameter(PlayerData player, ItemStack obj) {
return obj.getType() == material;
}
}

View File

@ -0,0 +1,30 @@
package net.Indyuce.mmocore.experience.source.type;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
/**
* Atrocious API that really needs rewriting
*
* @author cympe
*/
public abstract class ExperienceSource<T> {
private final ExperienceDispenser dispenser;
public ExperienceSource(ExperienceDispenser dispenser) {
this.dispenser = dispenser;
}
public ExperienceDispenser getDispenser() {
return dispenser;
}
public abstract ExperienceSourceManager<?> newManager();
public boolean matches(PlayerData player, T obj) {
return getDispenser().matches(player) && matchesParameter(player, obj);
}
public abstract boolean matchesParameter(PlayerData player, T obj);
}

View File

@ -0,0 +1,46 @@
package net.Indyuce.mmocore.experience.source.type;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.math.formula.RandomAmount;
import org.bukkit.Location;
import org.jetbrains.annotations.Nullable;
public abstract class SpecificExperienceSource<T> extends ExperienceSource<T> {
private final RandomAmount amount;
/**
* Used to register experience sources with SPECIFIC experience outputs.
* Other experience sources like ENCHANT have their exp output depend on the
* enchanted item. ALCHEMY exp outputs depend on the potion crafted
*/
public SpecificExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser);
config.validate("amount");
amount = new RandomAmount(config.getString("amount"));
}
public RandomAmount getAmount() {
return amount;
}
public int rollAmount() {
return amount.calculateInt();
}
/**
* Used when a player needs to gain experience after performing the action
* corresponding to this exp source
*
* @param player Player gaining the exp
* @param multiplier Used by the CraftItem experience source, multiplies the exp
* earned by a certain factor. When crafting an item, the
* multiplier is equal to the amount of items crafted
* @param hologramLocation Location used to display the exp hologram
*/
public void giveExperience(PlayerData player, double multiplier, @Nullable Location hologramLocation) {
getDispenser().giveExperience(player, rollAmount() * multiplier, hologramLocation);
}
}

View File

@ -2,8 +2,8 @@ package net.Indyuce.mmocore.gui;
import io.lumine.mythic.lib.version.VersionMaterial; import io.lumine.mythic.lib.version.VersionMaterial;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Booster; import net.Indyuce.mmocore.experience.Booster;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
import net.Indyuce.mmocore.api.player.stats.StatType; import net.Indyuce.mmocore.api.player.stats.StatType;

View File

@ -3,7 +3,7 @@ package net.Indyuce.mmocore.gui;
import io.lumine.mythic.lib.api.item.ItemTag; import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.quest.Quest; import net.Indyuce.mmocore.api.quest.Quest;
import net.Indyuce.mmocore.api.util.math.format.DelayFormat; import net.Indyuce.mmocore.api.util.math.format.DelayFormat;

View File

@ -4,7 +4,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerExpChangeEvent; import org.bukkit.event.player.PlayerExpChangeEvent;
import net.Indyuce.mmocore.api.experience.EXPSource; import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
public class RedirectVanillaExp implements Listener { public class RedirectVanillaExp implements Listener {

View File

@ -4,7 +4,7 @@ import io.lumine.mythic.lib.version.VersionSound;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.droptable.dropitem.fishing.FishingDropItem; import net.Indyuce.mmocore.api.droptable.dropitem.fishing.FishingDropItem;
import net.Indyuce.mmocore.api.event.CustomPlayerFishEvent; import net.Indyuce.mmocore.api.event.CustomPlayerFishEvent;
import net.Indyuce.mmocore.api.experience.EXPSource; import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.api.loot.LootBuilder; import net.Indyuce.mmocore.api.loot.LootBuilder;
import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.stats.StatType; import net.Indyuce.mmocore.api.player.stats.StatType;

View File

@ -9,7 +9,7 @@ import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.ConfigFile; import net.Indyuce.mmocore.api.ConfigFile;
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
public class AttributeManager extends MMOManager { public class AttributeManager implements MMOManager {
private final Map<String, PlayerAttribute> map = new HashMap<>(); private final Map<String, PlayerAttribute> map = new HashMap<>();
public PlayerAttribute get(String id) { public PlayerAttribute get(String id) {

View File

@ -26,7 +26,7 @@ import net.Indyuce.mmocore.api.player.profess.event.trigger.ClassChosenEventTrig
import net.Indyuce.mmocore.api.player.profess.event.trigger.LevelUpEventTrigger; import net.Indyuce.mmocore.api.player.profess.event.trigger.LevelUpEventTrigger;
import net.Indyuce.mmocore.api.player.profess.event.trigger.MultipleLevelUpEventTrigger; import net.Indyuce.mmocore.api.player.profess.event.trigger.MultipleLevelUpEventTrigger;
public class ClassManager extends MMOManager { public class ClassManager implements MMOManager {
private final Map<String, PlayerClass> map = new HashMap<>(); private final Map<String, PlayerClass> map = new HashMap<>();
/* /*

View File

@ -22,7 +22,7 @@ import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.logging.Level; import java.util.logging.Level;
public class CustomBlockManager extends MMOManager { public class CustomBlockManager implements MMOManager {
/** /**
* Registered block infos * Registered block infos

View File

@ -16,7 +16,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.droptable.DropTable; import net.Indyuce.mmocore.api.droptable.DropTable;
public class DropTableManager extends MMOManager { public class DropTableManager implements MMOManager {
private final Map<String, DropTable> map = new HashMap<>(); private final Map<String, DropTable> map = new HashMap<>();
public void register(DropTable table) { public void register(DropTable table) {

View File

@ -10,7 +10,7 @@ import java.util.logging.Level;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.ExpCurve; import net.Indyuce.mmocore.experience.ExpCurve;
public class ExperienceManager { public class ExperienceManager {
private final Map<String, ExpCurve> expCurves = new HashMap<>(); private final Map<String, ExpCurve> expCurves = new HashMap<>();

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import org.apache.commons.lang.Validate; import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
@ -12,8 +13,7 @@ import com.google.gson.JsonParseException;
import net.Indyuce.mmocore.api.block.BlockType; import net.Indyuce.mmocore.api.block.BlockType;
import net.Indyuce.mmocore.api.droptable.condition.Condition; import net.Indyuce.mmocore.api.droptable.condition.Condition;
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem; import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.api.load.DefaultMMOLoader; import net.Indyuce.mmocore.api.load.DefaultMMOLoader;
import net.Indyuce.mmocore.api.load.MMOLoader; import net.Indyuce.mmocore.api.load.MMOLoader;
import net.Indyuce.mmocore.api.quest.objective.Objective; import net.Indyuce.mmocore.api.quest.objective.Objective;
@ -41,8 +41,8 @@ public class MMOLoadManager {
return load(Objective.class, config, loader -> loader.loadObjective(config, section)); return load(Objective.class, config, loader -> loader.loadObjective(config, section));
} }
public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, Profession profession) { public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, ExperienceDispenser dispenser) {
return load(ExperienceSource.class, config, loader -> loader.loadExperienceSource(config, profession)); return load(ExperienceSource.class, config, loader -> loader.loadExperienceSource(config, dispenser));
} }
public Trigger loadTrigger(MMOLineConfig config) { public Trigger loadTrigger(MMOLineConfig config) {

View File

@ -1,7 +1,7 @@
package net.Indyuce.mmocore.manager; package net.Indyuce.mmocore.manager;
public abstract class MMOManager { public interface MMOManager {
public abstract void reload(); void reload();
public abstract void clear(); void clear();
} }

View File

@ -13,7 +13,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.quest.Quest; import net.Indyuce.mmocore.api.quest.Quest;
public class QuestManager extends MMOManager { public class QuestManager implements MMOManager {
private final Map<String, Quest> quests = new LinkedHashMap<>(); private final Map<String, Quest> quests = new LinkedHashMap<>();
public void load(File file) { public void load(File file) {

View File

@ -7,7 +7,7 @@ import org.bukkit.potion.PotionType;
import net.Indyuce.mmocore.manager.MMOManager; import net.Indyuce.mmocore.manager.MMOManager;
public class AlchemyManager extends MMOManager { public class AlchemyManager implements MMOManager {
public double splash, lingering, upgrade, extend; public double splash, lingering, upgrade, extend;
// private Map<PotionEffectType, Double> custom = new HashMap<>(); // private Map<PotionEffectType, Double> custom = new HashMap<>();

View File

@ -7,7 +7,7 @@ import org.bukkit.enchantments.Enchantment;
import net.Indyuce.mmocore.manager.MMOManager; import net.Indyuce.mmocore.manager.MMOManager;
public class EnchantManager extends MMOManager { public class EnchantManager implements MMOManager {
private final Map<Enchantment, Double> base = new HashMap<>(); private final Map<Enchantment, Double> base = new HashMap<>();
public void registerBaseExperience(Enchantment enchant, double value) { public void registerBaseExperience(Enchantment enchant, double value) {

View File

@ -1,27 +0,0 @@
package net.Indyuce.mmocore.manager.profession;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import net.Indyuce.mmocore.MMOCore;
public abstract class ExperienceManager<T> implements Listener {
private final Set<T> sources = new HashSet<>();
public ExperienceManager() {
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
}
public void register(T source) {
sources.add(source);
getSources();
}
public Set<T> getSources() {
return sources;
}
}

View File

@ -0,0 +1,30 @@
package net.Indyuce.mmocore.manager.profession;
import net.Indyuce.mmocore.MMOCore;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import java.util.HashSet;
import java.util.Set;
public abstract class ExperienceSourceManager<T> implements Listener {
/**
* List of all active experience sources
*/
private final Set<T> sources = new HashSet<>();
public ExperienceSourceManager() {
Bukkit.getPluginManager().registerEvents(this, MMOCore.plugin);
}
public void registerSource(T source) {
sources.add(source);
getSources();
}
public Set<T> getSources() {
return sources;
}
}

View File

@ -19,7 +19,7 @@ import net.Indyuce.mmocore.api.droptable.dropitem.fishing.FishingDropItem;
import net.Indyuce.mmocore.manager.MMOManager; import net.Indyuce.mmocore.manager.MMOManager;
import io.lumine.mythic.lib.api.MMOLineConfig; import io.lumine.mythic.lib.api.MMOLineConfig;
public class FishingManager extends MMOManager { public class FishingManager implements MMOManager {
private final Set<FishingDropTable> tables = new LinkedHashSet<>(); private final Set<FishingDropTable> tables = new LinkedHashSet<>();
private static final Random random = new Random(); private static final Random random = new Random();

View File

@ -11,25 +11,25 @@ import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.api.experience.source.type.ExperienceSource; import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.manager.MMOManager; import net.Indyuce.mmocore.manager.MMOManager;
public class ProfessionManager extends MMOManager { public class ProfessionManager implements MMOManager {
/* /**
* loaded professions. * Loaded professions.
*/ */
private final Map<String, Profession> professions = new HashMap<>(); private final Map<String, Profession> professions = new HashMap<>();
/* /**
* saves different experience sources based on experience source type. * Saves different experience sources based on experience source type.
*/ */
private final Map<Class<?>, ExperienceManager<?>> managers = new HashMap<>(); private final Map<Class<?>, ExperienceSourceManager<?>> managers = new HashMap<>();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> ExperienceManager<T> getManager(Class<T> t) { public <T> ExperienceSourceManager<T> getManager(Class<T> t) {
return (ExperienceManager<T>) managers.get(t); return (ExperienceSourceManager<T>) managers.get(t);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -38,7 +38,7 @@ public class ProfessionManager extends MMOManager {
if (!managers.containsKey(path)) if (!managers.containsKey(path))
managers.put(path, source.newManager()); managers.put(path, source.newManager());
getManager(path).register(source); getManager(path).registerSource(source);
} }
public void register(Profession profession) { public void register(Profession profession) {

View File

@ -7,7 +7,7 @@ import org.bukkit.Material;
import net.Indyuce.mmocore.manager.MMOManager; import net.Indyuce.mmocore.manager.MMOManager;
public class SmithingManager extends MMOManager { public class SmithingManager implements MMOManager {
private final Map<Material, Double> base = new HashMap<>(); private final Map<Material, Double> base = new HashMap<>();
public void registerBaseExperience(Material material, double value) { public void registerBaseExperience(Material material, double value) {

View File

@ -1,7 +1,7 @@
package net.Indyuce.mmocore.manager.social; package net.Indyuce.mmocore.manager.social;
import net.Indyuce.mmocore.api.experience.Booster; import net.Indyuce.mmocore.experience.Booster;
import net.Indyuce.mmocore.api.experience.Profession; import net.Indyuce.mmocore.experience.Profession;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

@ -15,7 +15,7 @@ import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
public class PartyManager extends MMOManager { public class PartyManager implements MMOManager {
private final Set<Party> parties = new HashSet<>(); private final Set<Party> parties = new HashSet<>();
private final Map<StatType, StatModifier> buffs = new HashMap<>(); private final Map<StatType, StatModifier> buffs = new HashMap<>();