!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,22 +1,22 @@
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 {
/*
* 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 Condition loadCondition(MMOLineConfig config) { public Condition loadCondition(MMOLineConfig config) {
return null; return null;
} }
@ -33,7 +33,7 @@ public class MMOLoader {
return null; return null;
} }
public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, Profession profession) { public ExperienceSource<?> loadExperienceSource(MMOLineConfig config, ExperienceDispenser dispenser) {
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;
@ -122,17 +124,17 @@ public class PlayerClass extends PostLoadObject {
"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")) {
ExperienceDispenser dispenser = new MainExperienceDispenser(this);
for (String key : config.getStringList("main-exp-sources")) for (String key : config.getStringList("main-exp-sources"))
try { try {
ExperienceSource<?> source = MMOCore.plugin.loadManager.loadExperienceSource(new MMOLineConfig(key), ExperienceSource<?> source = MMOCore.plugin.loadManager.loadExperienceSource(new MMOLineConfig(key), dispenser);
null);
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)) {

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,30 +1,29 @@
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, () -> {
@ -42,7 +41,7 @@ public class KillMythicFactionExperienceSource extends SpecificExperienceSource<
} }
@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,30 +1,29 @@
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, () -> {
@ -41,7 +40,7 @@ public class KillMythicMobExperienceSource extends SpecificExperienceSource<Stri
} }
@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,4 +1,4 @@
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;

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<>();