Fixed some exp sources working across some classes/professions

This commit is contained in:
Jules 2024-05-23 23:34:39 -07:00
parent 0e5ac9ce3a
commit 6e739b3787
21 changed files with 489 additions and 491 deletions

View File

@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Used to differenciate between the main class experience and
* Used to differentiate between the main class experience and
* experience given in a specific profession. Also being used to
* monitor EXP holograms.
*

View File

@ -3,9 +3,9 @@ package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@ -44,44 +44,46 @@ public class BrewPotionExperienceSource extends ExperienceSource<PotionMeta> {
@Override
public ExperienceSourceManager<BrewPotionExperienceSource> newManager() {
return new ExperienceSourceManager<BrewPotionExperienceSource>() {
@EventHandler(priority = EventPriority.HIGHEST, 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());
});
}
};
return new Manager();
}
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;
private static class Manager extends ExperienceSourceManager<BrewPotionExperienceSource> {
@EventHandler(priority = EventPriority.HIGHEST, 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(source, 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();
}
return null;
}
private Optional<Player> getNearbyPlayer(Location loc) {
return loc.getWorld().getPlayers().stream().filter(player -> player.getLocation().distanceSquared(loc) < 100).findAny();
}
public class PotionUpgrade {
private static class PotionUpgrade {
/*
* if the potion was extended using redstone or upgraded using
@ -161,14 +163,14 @@ public class BrewPotionExperienceSource extends ExperienceSource<PotionMeta> {
// effect.getType() == type).findFirst();
// }
public void process(Player player) {
public void process(BrewPotionExperienceSource source, Player player) {
/*
* calculate extra exp due to extra effects
*/
// exp += getTotal(mapEffectDurations());
getDispenser().giveExperience(PlayerData.get(player), exp * multiplier, player.getLocation(), EXPSource.SOURCE);
source.getDispenser().giveExperience(PlayerData.get(player), exp * source.multiplier, player.getLocation(), EXPSource.SOURCE);
}
}
}

View File

@ -11,7 +11,6 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerMoveEvent;
import static org.bukkit.event.EventPriority.HIGHEST;
import static org.bukkit.event.EventPriority.MONITOR;
public class ClimbExperienceSource extends SpecificExperienceSource<Material> {
//Can be Ladder,Vines,Twisting Vines,Weeping Vines.
@ -36,28 +35,11 @@ public class ClimbExperienceSource extends SpecificExperienceSource<Material> {
type = Material.valueOf(str);
}
}
@Override
public ExperienceSourceManager<ClimbExperienceSource> newManager() {
return new ExperienceSourceManager<ClimbExperienceSource>() {
@EventHandler(priority = HIGHEST,ignoreCancelled = true)
public void onClimb(PlayerMoveEvent e) {
double delta=e.getTo().getBlockY()-e.getFrom().getBlockY();
if (delta > 0) {
if (e.getPlayer().hasMetadata("NPC"))
return;
PlayerData playerData = PlayerData.get(e.getPlayer());
for (ClimbExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, e.getFrom().getBlock().getType()))
source.giveExperience(playerData, delta, null);
}
}
}
};
return new Manager();
}
@Override
@ -71,6 +53,22 @@ public class ClimbExperienceSource extends SpecificExperienceSource<Material> {
if (type.equals(Material.TWISTING_VINES))
return material.equals(Material.TWISTING_VINES) || material.equals(Material.TWISTING_VINES_PLANT);
return material.equals(type);
}
private static class Manager extends ExperienceSourceManager<ClimbExperienceSource> {
@EventHandler(priority = HIGHEST, ignoreCancelled = true)
public void onClimb(PlayerMoveEvent e) {
double delta = e.getTo().getBlockY() - e.getFrom().getBlockY();
if (delta > 0) {
if (e.getPlayer().hasMetadata("NPC"))
return;
PlayerData playerData = PlayerData.get(e.getPlayer());
for (ClimbExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, e.getFrom().getBlock().getType()))
source.giveExperience(playerData, delta, null);
}
}
}
}
}

View File

@ -3,8 +3,8 @@ package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
@ -30,51 +30,7 @@ public class CraftItemExperienceSource extends SpecificExperienceSource<Material
@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());
/**
* This makes sure that the crafting recipe was performed correctly.
*
* In some scenarii, the CraftItemEvent (which is only a click event
* by the way) is not cancelled, but the item is not crafted which makes
* EXP duplication a game breaking glitch. MMOCore make sure that at
* least one ingredient has lowered in amount.
*
* The second objective of that check is to deduce the amount of items that
* were crafted during this event. For that, it finds the item with the lowest
* amount in the crafting matrix and see how many items disappeared,
* multiplied by the recipe output amount (works for a shift click).
*
* References:
* - https://git.lumine.io/mythiccraft/mmocore/-/issues/102
* - https://www.spigotmc.org/threads/how-to-get-amount-of-item-crafted.377598/
*/
final int index = getLowerAmountIngredientIndex(event.getInventory().getMatrix());
final int oldAmount = event.getInventory().getMatrix()[index].getAmount();
final int itemsCraftedPerRecipe = event.getInventory().getResult().getAmount();
final Material resultType = event.getInventory().getResult().getType();
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
// First check
int newAmount = getAmount(event.getInventory().getMatrix()[index]);
if (newAmount >= oldAmount)
return;
// Deduce amount crafted
int amountCrafted = (event.getClick().isShiftClick() ? oldAmount - newAmount : 1) * itemsCraftedPerRecipe;
for (CraftItemExperienceSource source : getSources())
if (source.matches(data, resultType))
source.giveExperience(data, amountCrafted, event.getInventory().getLocation());
});
}
};
return new Manager();
}
@Override
@ -82,23 +38,68 @@ public class CraftItemExperienceSource extends SpecificExperienceSource<Material
return material == obj;
}
private int getAmount(@Nullable ItemStack item) {
return item == null || item.getType() == Material.AIR ? 0 : item.getAmount();
}
private static class Manager extends ExperienceSourceManager<CraftItemExperienceSource> {
private int getLowerAmountIngredientIndex(ItemStack[] matrix) {
int lower = Integer.MAX_VALUE;
int index = -1;
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void a(CraftItemEvent event) {
if (event.getAction() == InventoryAction.NOTHING || event.getInventory().getResult() == null) return;
for (int i = 0; i < matrix.length; i++) {
ItemStack checked = matrix[i];
if (checked != null && checked.getType() != Material.AIR && checked.getAmount() > 0 && checked.getAmount() < lower) {
lower = checked.getAmount();
index = i;
}
PlayerData data = PlayerData.get((Player) event.getWhoClicked());
/**
* This makes sure that the crafting recipe was performed correctly.
*
* In some scenarii, the CraftItemEvent (which is only a click event
* by the way) is not cancelled, but the item is not crafted which makes
* EXP duplication a game breaking glitch. MMOCore make sure that at
* least one ingredient has lowered in amount.
*
* The second objective of that check is to deduce the amount of items that
* were crafted during this event. For that, it finds the item with the lowest
* amount in the crafting matrix and see how many items disappeared,
* multiplied by the recipe output amount (works for a shift click).
*
* References:
* - https://git.lumine.io/mythiccraft/mmocore/-/issues/102
* - https://www.spigotmc.org/threads/how-to-get-amount-of-item-crafted.377598/
*/
final int index = getLowerAmountIngredientIndex(event.getInventory().getMatrix());
final int oldAmount = event.getInventory().getMatrix()[index].getAmount();
final int itemsCraftedPerRecipe = event.getInventory().getResult().getAmount();
final Material resultType = event.getInventory().getResult().getType();
Bukkit.getScheduler().runTask(MMOCore.plugin, () -> {
// First check
int newAmount = getAmount(event.getInventory().getMatrix()[index]);
if (newAmount >= oldAmount) return;
// Deduce amount crafted
int amountCrafted = (event.getClick().isShiftClick() ? oldAmount - newAmount : 1) * itemsCraftedPerRecipe;
for (CraftItemExperienceSource source : getSources())
if (source.matches(data, resultType))
source.giveExperience(data, amountCrafted, event.getInventory().getLocation());
});
}
Validate.isTrue(index != -1, "No item in matrix");
return index;
private int getAmount(@Nullable ItemStack item) {
return item == null || item.getType() == Material.AIR ? 0 : item.getAmount();
}
private int getLowerAmountIngredientIndex(ItemStack[] matrix) {
int lower = Integer.MAX_VALUE;
int index = -1;
for (int i = 0; i < matrix.length; i++) {
ItemStack checked = matrix[i];
if (checked != null && checked.getType() != Material.AIR && checked.getAmount() > 0 && checked.getAmount() < lower) {
lower = checked.getAmount();
index = i;
}
}
Validate.isTrue(index != -1, "No item in matrix");
return index;
}
}
}

View File

@ -3,7 +3,6 @@ package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
import io.lumine.mythic.lib.damage.DamagePacket;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
@ -40,27 +39,29 @@ public class DamageDealtExperienceSource extends SpecificExperienceSource<Void>
@Override
public ExperienceSourceManager<DamageDealtExperienceSource> newManager() {
return new ExperienceSourceManager<DamageDealtExperienceSource>() {
@EventHandler(priority = MONITOR, ignoreCancelled = true)
public void onDamageDealt(PlayerAttackEvent event) {
final PlayerData playerData = PlayerData.get(event.getPlayer());
for (DamageDealtExperienceSource source : getSources())
if (source.matches(playerData, null)) {
double value = event.getDamage().getDamage(source.type);
if (value == 0) continue;
// Cannot count more than the entity's max health
final double enemyMaxHealth = event.getEntity().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
value = Math.min(value, enemyMaxHealth);
source.giveExperience(playerData, value, null);
}
}
};
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, Void v) {
return true;
}
private static class Manager extends ExperienceSourceManager<DamageDealtExperienceSource> {
@EventHandler(priority = MONITOR, ignoreCancelled = true)
public void onDamageDealt(PlayerAttackEvent event) {
final PlayerData playerData = PlayerData.get(event.getPlayer());
for (DamageDealtExperienceSource source : getSources())
if (source.matches(playerData, null)) {
double value = source.type == null ? event.getDamage().getDamage() : event.getDamage().getDamage(source.type);
if (value == 0) continue;
// Cannot count more than the entity's max health
final double enemyMaxHealth = event.getEntity().getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
value = Math.min(value, enemyMaxHealth);
source.giveExperience(playerData, value, null);
}
}
}
}

View File

@ -43,32 +43,7 @@ public class DamageTakenExperienceSource extends SpecificExperienceSource<Entity
@Override
public ExperienceSourceManager<DamageTakenExperienceSource> newManager() {
return new ExperienceSourceManager<DamageTakenExperienceSource>() {
@EventHandler(priority = HIGHEST, ignoreCancelled = true)
public void onDamageTaken(EntityDamageEvent event) {
if (!UtilityMethods.isRealPlayer(event.getEntity())) return;
final PlayerData playerData = PlayerData.get((Player) event.getEntity());
final Lazy<Double> effectiveDamage = Lazy.of(() -> {
final double eventDamage = event.getDamage();
final double maxHealth = ((Player) event.getEntity()).getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
return Math.min(eventDamage, maxHealth);
});
// Wait 2 tick to check if the player died
new BukkitRunnable() {
@Override
public void run() {
for (DamageTakenExperienceSource source : getSources())
if (source.matchesParameter(playerData, event.getCause())) {
// System.out.println("-> " + effectiveDamage.get());
source.giveExperience(playerData, effectiveDamage.get(), null);
}
}
}.runTaskLater(MMOCore.plugin, 2);
}
};
return new Manager();
}
@Override
@ -76,4 +51,32 @@ public class DamageTakenExperienceSource extends SpecificExperienceSource<Entity
if (player.getPlayer().isDead()) return false;
return cause == null || damageCause.equals(cause);
}
private static class Manager extends ExperienceSourceManager<DamageTakenExperienceSource> {
@EventHandler(priority = HIGHEST, ignoreCancelled = true)
public void onDamageTaken(EntityDamageEvent event) {
if (!UtilityMethods.isRealPlayer(event.getEntity())) return;
final PlayerData playerData = PlayerData.get((Player) event.getEntity());
final Lazy<Double> effectiveDamage = Lazy.of(() -> {
final double eventDamage = event.getDamage();
final double maxHealth = ((Player) event.getEntity()).getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
return Math.min(eventDamage, maxHealth);
});
// Wait 2 tick to check if the player died
new BukkitRunnable() {
@Override
public void run() {
for (DamageTakenExperienceSource source : getSources())
if (source.matchesParameter(playerData, event.getCause())) {
// System.out.println("-> " + effectiveDamage.get());
source.giveExperience(playerData, effectiveDamage.get(), null);
}
}
}.runTaskLater(MMOCore.plugin, 2);
}
}
}

View File

@ -33,19 +33,7 @@ public class EatExperienceSource extends SpecificExperienceSource<ItemStack> {
@Override
public ExperienceSourceManager<EatExperienceSource> newManager() {
return new ExperienceSourceManager<EatExperienceSource>() {
@EventHandler(priority = MONITOR,ignoreCancelled = true)
public void a(PlayerItemConsumeEvent e) {
if(!e.getPlayer().hasMetadata("NPC")) {
PlayerData playerData = PlayerData.get(e.getPlayer());
for (EatExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, e.getItem()))
source.giveExperience(playerData, 1, null);
}
}
}
};
return new Manager();
}
@Override
@ -55,4 +43,18 @@ public class EatExperienceSource extends SpecificExperienceSource<ItemStack> {
return type.equals(obj.getType());
}
private static class Manager extends ExperienceSourceManager<EatExperienceSource> {
@EventHandler(priority = MONITOR,ignoreCancelled = true)
public void a(PlayerItemConsumeEvent e) {
if(!e.getPlayer().hasMetadata("NPC")) {
PlayerData playerData = PlayerData.get(e.getPlayer());
for (EatExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, e.getItem()))
source.giveExperience(playerData, 1, null);
}
}
}
}
}

View File

@ -4,9 +4,9 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.experience.EXPSource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
@ -41,28 +41,30 @@ public class EnchantItemExperienceSource extends ExperienceSource<Void> {
@Override
public ExperienceSourceManager<EnchantItemExperienceSource> newManager() {
return new ExperienceSourceManager<EnchantItemExperienceSource>() {
return new Manager();
}
@EventHandler(priority = EventPriority.HIGHEST, 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> applicableEnchants = new HashMap<>(event.getEnchantsToAdd());
private static class Manager extends ExperienceSourceManager<EnchantItemExperienceSource> {
// Filter out enchants if required
if (!source.enchants.isEmpty())
applicableEnchants.keySet().removeIf(enchantment -> !source.enchants.contains(enchantment));
@EventHandler(priority = EventPriority.HIGHEST, 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> applicableEnchants = new HashMap<>(event.getEnchantsToAdd());
if (applicableEnchants.isEmpty())
continue;
// Filter out enchants if required
if (!source.enchants.isEmpty())
applicableEnchants.keySet().removeIf(enchantment -> !source.enchants.contains(enchantment));
double exp = 0;
for (Entry<Enchantment, Integer> entry : applicableEnchants.entrySet())
exp += MMOCore.plugin.enchantManager.getBaseExperience(entry.getKey()) * entry.getValue();
getDispenser().giveExperience(player, exp, event.getEnchantBlock().getLocation(), EXPSource.SOURCE);
}
}
};
if (applicableEnchants.isEmpty())
continue;
double exp = 0;
for (Entry<Enchantment, Integer> entry : applicableEnchants.entrySet())
exp += MMOCore.plugin.enchantManager.getBaseExperience(entry.getKey()) * entry.getValue();
source.getDispenser().giveExperience(player, exp, event.getEnchantBlock().getLocation(), EXPSource.SOURCE);
}
}
}
}

View File

@ -2,8 +2,8 @@ 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.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Material;
import org.bukkit.entity.Item;
@ -25,26 +25,28 @@ public class FishItemExperienceSource extends SpecificExperienceSource<ItemStack
@Override
public ExperienceSourceManager<FishItemExperienceSource> newManager() {
return new ExperienceSourceManager<FishItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGHEST, 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));
}
}
};
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, ItemStack obj) {
return obj.getType() == material;
}
private static class Manager extends ExperienceSourceManager<FishItemExperienceSource> {
@EventHandler(priority = EventPriority.HIGHEST, 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));
}
}
}
}

View File

@ -33,20 +33,22 @@ public class FromExperienceSource extends ExperienceSource {
@Override
public ExperienceSourceManager<FromExperienceSource> newManager() {
return new ExperienceSourceManager<>() {
/**
* Used to register all the children experience sources.
*/
@Override
public void registerSource(FromExperienceSource source) {
source.experienceSources.forEach(expSource -> MMOCore.plugin.experience.registerSource(expSource));
}
};
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, Object obj) {
return false;
}
private static class Manager extends ExperienceSourceManager<FromExperienceSource> {
/**
* Used to register all the children experience sources.
*/
@Override
public void registerSource(FromExperienceSource source) {
source.experienceSources.forEach(expSource -> MMOCore.plugin.experience.registerSource(expSource));
}
}
}

View File

@ -38,44 +38,47 @@ public class KillMobExperienceSource extends SpecificExperienceSource<Entity> {
@Override
public ExperienceSourceManager<KillMobExperienceSource> newManager() {
return new ExperienceSourceManager<KillMobExperienceSource>() {
/**
* This map is used to keep track of the last player who
* hit some entity. It is flushed on entity death.
*/
private final FlushableRegistry<UUID, UUID> registry = new FlushableRegistry<>((entity, attacker) -> Bukkit.getEntity(entity) == null, 20 * 60);
@Override
public void whenClosed() {
registry.close();
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void registerLastAttacker(PlayerAttackEvent event) {
registry.getRegistry().put(event.getEntity().getUniqueId(), event.getAttacker().getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.MONITOR)
public void giveExp(EntityDeathEvent event) {
// Always remove entry from map
final @Nullable UUID lastAttacker = this.registry.getRegistry().remove(event.getEntity().getUniqueId());
if (lastAttacker == null) return;
if (event.getEntity().getPersistentDataContainer().has(new NamespacedKey(MMOCore.plugin, "spawner_spawned"), PersistentDataType.STRING))
return;
final PlayerData data = PlayerData.get(lastAttacker);
for (KillMobExperienceSource source : getSources())
if (source.matches(data, event.getEntity()))
source.giveExperience(data, 1, MMOCoreUtils.getCenterLocation(event.getEntity()));
}
};
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, Entity obj) {
return obj.getType() == type && (displayName == null || displayName.equals(obj.getCustomName()));
}
private static class Manager extends ExperienceSourceManager<KillMobExperienceSource> {
/**
* This map is used to keep track of the last player who
* hit some entity. It is flushed on entity death.
*/
private final FlushableRegistry<UUID, UUID> registry = new FlushableRegistry<>((entity, attacker) -> Bukkit.getEntity(entity) == null, 20 * 60);
@Override
public void whenClosed() {
registry.close();
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void registerLastAttacker(PlayerAttackEvent event) {
registry.getRegistry().put(event.getEntity().getUniqueId(), event.getAttacker().getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.MONITOR)
public void giveExp(EntityDeathEvent event) {
// Always remove entry from map
final @Nullable UUID lastAttacker = this.registry.getRegistry().remove(event.getEntity().getUniqueId());
if (lastAttacker == null) return;
if (event.getEntity().getPersistentDataContainer().has(new NamespacedKey(MMOCore.plugin, "spawner_spawned"), PersistentDataType.STRING))
return;
final PlayerData data = PlayerData.get(lastAttacker);
for (KillMobExperienceSource source : getSources())
if (source.matches(data, event.getEntity()))
source.giveExperience(data, 1, MMOCoreUtils.getCenterLocation(event.getEntity()));
}
}
}

View File

@ -4,8 +4,8 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.GameMode;
import org.bukkit.Material;
@ -40,36 +40,36 @@ public class MineBlockExperienceSource extends SpecificExperienceSource<Material
@Override
public ExperienceSourceManager<MineBlockExperienceSource> newManager() {
return new ExperienceSourceManager<MineBlockExperienceSource>() {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void a(BlockBreakEvent event) {
if (event.getPlayer().getGameMode() != GameMode.SURVIVAL) return;
if (UtilityMethods.isFake(event)) 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);
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, Material obj) {
return material == obj;
}
private static class Manager extends ExperienceSourceManager<MineBlockExperienceSource> {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void a(BlockBreakEvent event) {
if (event.getPlayer().getGameMode() != GameMode.SURVIVAL) return;
if (UtilityMethods.isFake(event)) 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);
}
}
}

View File

@ -36,27 +36,7 @@ public class MoveExperienceSource extends SpecificExperienceSource {
@Override
public ExperienceSourceManager<MoveExperienceSource> newManager() {
return new ExperienceSourceManager<MoveExperienceSource>() {
@EventHandler(priority = MONITOR,ignoreCancelled = true)
public void onMove(PlayerMoveEvent e) {
double deltax = e.getTo().getBlockX() - e.getFrom().getBlockX();
double deltay = e.getTo().getBlockY() - e.getFrom().getBlockY();
double deltaz = e.getTo().getBlockZ() - e.getFrom().getBlockZ();
if (deltax != 0 || deltay != 0 || deltaz != 0) {
double delta = Math.sqrt(deltax * deltax + deltay * deltay + deltaz * deltaz);
if (e.getPlayer().hasMetadata("NPC"))
return;
Player player = e.getPlayer();
PlayerData playerData = PlayerData.get(player);
for (MoveExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, null)) {
giveExperience(playerData, delta, null);
}
}
}
}
};
return new Manager();
}
@Override
@ -69,7 +49,7 @@ public class MoveExperienceSource extends SpecificExperienceSource {
FLY((p) -> p.isFlying() || p.isGliding()),
SWIM((p) -> p.getLocation().getBlock().isLiquid()),
SPRINT(Player::isSprinting),
WALK((p) -> !p.isSneaking() && !p.isSprinting() &&((Entity)p).isOnGround()&& !p.isFlying() && !p.getLocation().getBlock().isLiquid());
WALK((p) -> !p.isSneaking() && !p.isSprinting() && ((Entity) p).isOnGround() && !p.isFlying() && !p.getLocation().getBlock().isLiquid());
private final Function<Player, Boolean> matching;
@ -82,4 +62,24 @@ public class MoveExperienceSource extends SpecificExperienceSource {
}
}
private static class Manager extends ExperienceSourceManager<MoveExperienceSource> {
@EventHandler(priority = MONITOR, ignoreCancelled = true)
public void onMove(PlayerMoveEvent e) {
double deltax = e.getTo().getBlockX() - e.getFrom().getBlockX();
double deltay = e.getTo().getBlockY() - e.getFrom().getBlockY();
double deltaz = e.getTo().getBlockZ() - e.getFrom().getBlockZ();
if (deltax != 0 || deltay != 0 || deltaz != 0) {
double delta = Math.sqrt(deltax * deltax + deltay * deltay + deltaz * deltaz);
if (e.getPlayer().hasMetadata("NPC"))
return;
Player player = e.getPlayer();
PlayerData playerData = PlayerData.get(player);
for (MoveExperienceSource source : getSources())
if (source.matchesParameter(playerData, null))
source.giveExperience(playerData, delta, null);
}
}
}
}

View File

@ -2,8 +2,8 @@ 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.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.GameMode;
import org.bukkit.Material;
@ -23,23 +23,26 @@ public class PlaceBlockExperienceSource extends SpecificExperienceSource<Materia
@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());
}
};
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, Material obj) {
return material == obj;
}
private static class Manager extends 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());
}
}
}

View File

@ -15,7 +15,6 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.util.Objects;
public class PlayExperienceSource extends SpecificExperienceSource {
private final World world;
private final double x1, x2, z1, z2;
private final boolean inCombat;
@ -48,7 +47,7 @@ public class PlayExperienceSource extends SpecificExperienceSource {
@Override
public ExperienceSourceManager<PlayExperienceSource> newManager() {
return new PlayingExperienceSourceManager();
return new Manager();
}
@ -65,9 +64,9 @@ public class PlayExperienceSource extends SpecificExperienceSource {
}
private class PlayingExperienceSourceManager extends ExperienceSourceManager<PlayExperienceSource> {
private static class Manager extends ExperienceSourceManager<PlayExperienceSource> {
public PlayingExperienceSourceManager() {
public Manager() {
new BukkitRunnable() {
@Override
@ -77,7 +76,7 @@ public class PlayExperienceSource extends SpecificExperienceSource {
PlayerData playerData = PlayerData.get(player);
for (PlayExperienceSource source : getSources())
if (source.matchesParameter(playerData, null))
giveExperience(playerData, 1, null);
source. giveExperience(playerData, 1, null);
}
});
}

View File

@ -1,7 +1,8 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.MMOCore;
import io.lumine.mythic.lib.util.FlushableRegistry;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
@ -16,10 +17,8 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -30,8 +29,7 @@ public class ProjectileExperienceSource extends SpecificExperienceSource<Project
public ProjectileExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
if (!config.contains("type"))
projectileType = null;
if (!config.contains("type")) projectileType = null;
else {
String str = config.getString("type").toUpperCase().replace("-", "_");
Validate.isTrue(Arrays.stream(ProjectileType.values()).map(ProjectileType::toString).collect(Collectors.toList()).contains(str));
@ -41,76 +39,17 @@ public class ProjectileExperienceSource extends SpecificExperienceSource<Project
@Override
public ExperienceSourceManager<ProjectileExperienceSource> newManager() {
return new ExperienceSourceManager<ProjectileExperienceSource>() {
HashMap<Projectile, Location> projectiles = new HashMap<>();
@EventHandler(priority = HIGHEST,ignoreCancelled = true)
public void onHit(ProjectileHitEvent e) {
if (e.getHitBlock() != null && projectiles.containsKey(e.getEntity()))
projectiles.remove(e.getEntity());
}
@EventHandler(priority = HIGHEST,ignoreCancelled = true)
public void onDamage(EntityDamageByEntityEvent e) {
if (e.getEntity() instanceof Projectile) {
Projectile projectile = (Projectile) e.getEntity();
if (!projectiles.containsKey(projectile))
return;
if (projectile.getShooter() instanceof Player && !((Player) projectile.getShooter()).hasMetadata("NPC")) {
Player player = (Player) projectile.getShooter();
PlayerData playerData = PlayerData.get(player);
double distance = projectiles.get(projectile).distance(e.getEntity().getLocation());
for (ProjectileExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, projectile))
source.giveExperience(playerData, e.getFinalDamage() * distance, null);
}
}
projectiles.remove(projectile);
}
}
//Mark every arrow with the the location at which it was shot to calculate the distance
@EventHandler
public void onLaunch(ProjectileLaunchEvent e) {
if (e.getEntity().getShooter() instanceof Player) {
Player player = (Player) e.getEntity().getShooter();
if (player.hasMetadata("NPC"))
return;
projectiles.put(e.getEntity(), e.getLocation());
//Remove the projectile 15 s after it was launched
new BukkitRunnable() {
@Override
public void run() {
projectiles.remove(e.getEntity());
}
}.runTaskLater(MMOCore.plugin, 60 * 20L);
}
}
};
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, Projectile projectile) {
if (projectileType == null)
return true;
if (projectileType == null) return true;
return projectileType.matches(projectile);
}
public enum ProjectileType {
ARROW((p) -> p instanceof Arrow),
TRIDENT((p) -> p instanceof Trident);
ARROW((p) -> p instanceof Arrow), TRIDENT((p) -> p instanceof Trident);
private final Function<Projectile, Boolean> matching;
@ -124,4 +63,41 @@ public class ProjectileExperienceSource extends SpecificExperienceSource<Project
}
}
private static class Manager extends ExperienceSourceManager<ProjectileExperienceSource> {
private final FlushableRegistry<Projectile, Location> projectiles = new FlushableRegistry<>((proj, loc) -> proj.isDead(), 20 * 60);
@EventHandler(priority = HIGHEST, ignoreCancelled = true)
public void onHit(ProjectileHitEvent e) {
if (e.getHitBlock() != null) projectiles.getRegistry().remove(e.getEntity());
}
@EventHandler(priority = HIGHEST, ignoreCancelled = true)
public void onDamage(EntityDamageByEntityEvent e) {
if (e.getEntity() instanceof Projectile) {
Projectile projectile = (Projectile) e.getEntity();
Location loc = projectiles.getRegistry().get(projectile);
if (loc == null) return;
if (projectile.getShooter() instanceof Player && !((Player) projectile.getShooter()).hasMetadata("NPC")) {
Player player = (Player) projectile.getShooter();
PlayerData playerData = PlayerData.get(player);
double distance = loc.distance(e.getEntity().getLocation());
for (ProjectileExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, projectile))
source.giveExperience(playerData, e.getFinalDamage() * distance, null);
}
}
}
}
// Mark every arrow with the location at which it was shot to calculate the distance
@EventHandler
public void onLaunch(ProjectileLaunchEvent e) {
if (e.getEntity().getShooter() instanceof Player && UtilityMethods.isRealPlayer((Player) e.getEntity().getShooter())) {
projectiles.getRegistry().put(e.getEntity(), e.getLocation());
}
}
}
}

View File

@ -41,10 +41,10 @@ public class RepairItemExperienceSource extends ExperienceSource<ItemStack> {
@Override
public ExperienceSourceManager<RepairItemExperienceSource> newManager() {
return new CustomExperienceManager();
return new Manager();
}
private class CustomExperienceManager extends ExperienceSourceManager<RepairItemExperienceSource> {
private static class Manager extends ExperienceSourceManager<RepairItemExperienceSource> {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void a(InventoryClickEvent event) {
@ -80,8 +80,8 @@ public class RepairItemExperienceSource extends ExperienceSource<ItemStack> {
*/
final double exp = MMOCore.plugin.smithingManager.getBaseExperience(item.getType())
* Math.max(0, ((Damageable) old.getItemMeta()).getDamage() - ((Damageable) item.getItemMeta()).getDamage()) / 100;
getDispenser().giveExperience(data, exp, data.getPlayer().getLocation(), EXPSource.SOURCE);
source.getDispenser().giveExperience(data, exp, data.getPlayer().getLocation(), EXPSource.SOURCE);
}
}
}
}
}

View File

@ -1,12 +1,13 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
import org.apache.commons.lang.Validate;
import org.bukkit.event.EventHandler;
@ -21,39 +22,37 @@ public class ResourceExperienceSource extends SpecificExperienceSource<PlayerRes
*/
public ResourceExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
if (!config.contains("type"))
resource = null;
if (!config.contains("type")) resource = null;
else {
String str = config.getString("type").toUpperCase().replace("-", "_");
Validate.isTrue(str.equals("MANA") || str.equals("STELLIUM") || str.equals("STAMINA"),
"ResourceExperienceSource problem: The resource can only be mana, stamina or STELLIUM");
Validate.isTrue(str.equals("MANA") || str.equals("STELLIUM") || str.equals("STAMINA"), "ResourceExperienceSource problem: The resource can only be mana, stamina or STELLIUM");
resource = PlayerResource.valueOf(str);
}
}
@Override
public ExperienceSourceManager<ResourceExperienceSource> newManager() {
return new ExperienceSourceManager<ResourceExperienceSource>() {
@EventHandler(priority = HIGHEST,ignoreCancelled = true)
public void onResource(PlayerResourceUpdateEvent e) {
if (e.getPlayer().hasMetadata("NPC"))
return;
PlayerData playerData = PlayerData.get(e.getPlayer());
if(e.getAmount()<0)
for (ResourceExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, e.getResource()))
source.giveExperience(playerData, -e.getAmount(), null);
}
}
};
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, PlayerResource obj) {
if (resource == null)
return !obj.equals(PlayerResource.HEALTH);
if (resource == null) return !obj.equals(PlayerResource.HEALTH);
return resource.equals(obj);
}
private static class Manager extends ExperienceSourceManager<ResourceExperienceSource> {
@EventHandler(priority = HIGHEST, ignoreCancelled = true)
public void onResource(PlayerResourceUpdateEvent event) {
if (!UtilityMethods.isRealPlayer(event.getPlayer())) return;
PlayerData playerData = PlayerData.get(event.getPlayer());
if (event.getAmount() >= 0) return;
for (ResourceExperienceSource source : getSources())
if (source.matchesParameter(playerData, event.getResource()))
source.giveExperience(playerData, -event.getAmount(), null);
}
}
}

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
@ -40,29 +41,7 @@ public class RideExperienceSource extends SpecificExperienceSource<EntityType> {
@Override
public ExperienceSourceManager<RideExperienceSource> newManager() {
return new ExperienceSourceManager<RideExperienceSource>() {
@EventHandler(priority = HIGHEST,ignoreCancelled = true)
public void onRide(PlayerMoveEvent e) {
if (e.getPlayer().isInsideVehicle()) {
double deltax = e.getTo().getBlockX() - e.getFrom().getBlockX();
double deltay = e.getTo().getBlockY() - e.getFrom().getBlockY();
double deltaz = e.getTo().getBlockZ() - e.getFrom().getBlockZ();
if (deltax != 0 && deltay != 0 && deltaz != 0) {
double delta = Math.sqrt(deltax * deltax + deltay * deltay + deltaz * deltaz);
if (e.getPlayer().hasMetadata("NPC"))
return;
PlayerData playerData = PlayerData.get(e.getPlayer());
Entity vehicle = e.getPlayer().getVehicle();
for (RideExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, vehicle.getType()))
giveExperience(playerData, e.getFrom().distance(e.getTo()), null);
}
}
}
}
};
return new Manager();
}
@Override
@ -72,4 +51,25 @@ public class RideExperienceSource extends SpecificExperienceSource<EntityType> {
return type.equals(obj);
}
private static class Manager extends ExperienceSourceManager<RideExperienceSource> {
@EventHandler(priority = HIGHEST, ignoreCancelled = true)
public void onRide(PlayerMoveEvent event) {
if (!event.getPlayer().isInsideVehicle()) return;
double deltax = event.getTo().getBlockX() - event.getFrom().getBlockX();
double deltay = event.getTo().getBlockY() - event.getFrom().getBlockY();
double deltaz = event.getTo().getBlockZ() - event.getFrom().getBlockZ();
if (deltax != 0 || deltay != 0 || deltaz != 0) {
if (!UtilityMethods.isRealPlayer(event.getPlayer())) return;
PlayerData playerData = PlayerData.get(event.getPlayer());
Entity vehicle = event.getPlayer().getVehicle();
for (RideExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, vehicle.getType()))
source.giveExperience(playerData, event.getFrom().distance(event.getTo()), null);
}
}
}
}
}

View File

@ -2,8 +2,8 @@ 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.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.Location;
import org.bukkit.Material;
@ -27,43 +27,41 @@ public class SmeltItemExperienceSource extends SpecificExperienceSource<ItemStac
@Override
public ExperienceSourceManager<SmeltItemExperienceSource> newManager() {
return new ExperienceSourceManager<SmeltItemExperienceSource>() {
@EventHandler(priority = EventPriority.HIGHEST, 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);
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, ItemStack obj) {
return obj.getType() == material;
}
private static class Manager extends ExperienceSourceManager<SmeltItemExperienceSource> {
@EventHandler(priority = EventPriority.HIGHEST, 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);
}
}
}

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import net.Indyuce.mmocore.api.player.PlayerData;
import net.Indyuce.mmocore.api.util.MMOCoreUtils;
@ -7,38 +8,44 @@ import net.Indyuce.mmocore.experience.dispenser.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.SpecificExperienceSource;
import net.Indyuce.mmocore.manager.profession.ExperienceSourceManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Wolf;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityTameEvent;
public class TameExperienceSource extends SpecificExperienceSource {
public class TameExperienceSource extends SpecificExperienceSource<EntityType> {
public TameExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
}
@Override
public ExperienceSourceManager<TameExperienceSource> newManager() {
return new ExperienceSourceManager<TameExperienceSource>() {
@EventHandler(priority = EventPriority.HIGHEST,ignoreCancelled = true)
public void onWolfHit(EntityDamageByEntityEvent e) {
if(e.getDamager() instanceof Wolf) {
Wolf wolf= (Wolf) e.getDamager();
if(wolf.getOwner() instanceof Player &&!((Player) wolf.getOwner()).hasMetadata("NPC")) {
PlayerData playerData=PlayerData.get((OfflinePlayer) wolf.getOwner());
for(TameExperienceSource source:getSources()) {
source.giveExperience(playerData,e.getDamage(), MMOCoreUtils.getCenterLocation(e.getEntity()));
}
}
}
}
};
return new Manager();
}
@Override
public boolean matchesParameter(PlayerData player, Object obj) {
return false;
public boolean matchesParameter(PlayerData player, EntityType entityType) {
return true;
}
private static class Manager extends ExperienceSourceManager<TameExperienceSource> {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onWolfHit(EntityTameEvent event) {
// Only wolves at the moment
if (!(event.getEntity() instanceof Wolf)) return;
if (!(event.getOwner() instanceof Player) || !UtilityMethods.isRealPlayer((Entity) event.getOwner()))
return;
PlayerData playerData = PlayerData.get((OfflinePlayer) event.getOwner());
for (TameExperienceSource source : getSources())
if (source.matches(playerData, event.getEntity().getType()))
source.giveExperience(playerData, 1, MMOCoreUtils.getCenterLocation(event.getEntity()));
}
}
}