Fixed damagedealt{} exp source crashing the server when giving a cookie to a parrot

This commit is contained in:
Jules 2024-05-23 18:33:05 -07:00
parent dad9db0edd
commit 0e5ac9ce3a
2 changed files with 44 additions and 50 deletions

View File

@ -10,6 +10,7 @@ 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.attribute.Attribute;
import org.bukkit.event.EventHandler;
import java.util.Arrays;
@ -18,7 +19,7 @@ import java.util.stream.Collectors;
import static org.bukkit.event.EventPriority.MONITOR;
public class DamageDealtExperienceSource extends SpecificExperienceSource<DamageType> {
public class DamageDealtExperienceSource extends SpecificExperienceSource<Void> {
private final DamageType type;
/**
@ -28,14 +29,11 @@ public class DamageDealtExperienceSource extends SpecificExperienceSource<Damage
public DamageDealtExperienceSource(ExperienceDispenser dispenser, MMOLineConfig config) {
super(dispenser, config);
if (!config.contains("type"))
type = null;
if (!config.contains("type")) type = null;
else {
String str = UtilityMethods.enumName(config.getString("type"));
//Checks if the damage type correspond to a value of the damage type enum
Validate.isTrue(Arrays.stream(DamageType.values()).map(Objects::toString).collect(Collectors.toList()).contains(str),
"Type value not allowed. Type value allowed: magic, physical, weapon, skill, projectile," +
" unarmed, on-hit, minion, dot.");
Validate.isTrue(Arrays.stream(DamageType.values()).map(Objects::toString).collect(Collectors.toList()).contains(str), "Type value not allowed. Type value allowed: magic, physical, weapon, skill, projectile," + " unarmed, on-hit, minion, dot.");
type = DamageType.valueOf(str);
}
}
@ -43,35 +41,26 @@ public class DamageDealtExperienceSource extends SpecificExperienceSource<Damage
@Override
public ExperienceSourceManager<DamageDealtExperienceSource> newManager() {
return new ExperienceSourceManager<DamageDealtExperienceSource>() {
//It isn't triggered when the PlayerAttackEvent gets cancelled
@EventHandler(priority = MONITOR,ignoreCancelled = true)
public void onDamageDealt(PlayerAttackEvent e) {
PlayerData playerData = PlayerData.get(e.getPlayer());
for (DamageDealtExperienceSource source : getSources()) {
double value = 0;
for (DamagePacket packet : e.getDamage().getPackets()) {
for (DamageType damageType : packet.getTypes()) {
if (source.matchesParameter(playerData, damageType))
value += packet.getFinalValue();
}
@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);
}
source.giveExperience(playerData, value, null);
}
}
};
}
@Override
public boolean matchesParameter(PlayerData player, DamageType damageType) {
if (type == null) {
return true;
}
else {
return type.equals(damageType);
}
public boolean matchesParameter(PlayerData player, Void v) {
return true;
}
}

View File

@ -1,13 +1,15 @@
package net.Indyuce.mmocore.experience.source;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.MMOLineConfig;
import io.lumine.mythic.lib.util.Lazy;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.player.PlayerData;
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.OfflinePlayer;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageEvent;
@ -42,33 +44,36 @@ public class DamageTakenExperienceSource extends SpecificExperienceSource<Entity
@Override
public ExperienceSourceManager<DamageTakenExperienceSource> newManager() {
return new ExperienceSourceManager<DamageTakenExperienceSource>() {
@EventHandler(priority = HIGHEST,ignoreCancelled = true)
@EventHandler(priority = HIGHEST, ignoreCancelled = true)
public void onDamageTaken(EntityDamageEvent e) {
if (e.getEntity() instanceof Player && !e.getEntity().hasMetadata("NPC")) {
double amount = e.getDamage();
PlayerData playerData = PlayerData.get((OfflinePlayer) e.getEntity());
//We wait 2 tick to check if the player is Dead
new BukkitRunnable() {
@Override
public void run() {
for (DamageTakenExperienceSource source : getSources()) {
if (source.matchesParameter(playerData, e.getCause()))
source.giveExperience(playerData, amount, null);
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);
}
}
}.runTaskLater(MMOCore.plugin, 2);
}
};
}
@Override
public boolean matchesParameter(PlayerData player, EntityDamageEvent.DamageCause damageCause) {
if (player.getPlayer().isDead())
return false;
if (cause == null)
return true;
return damageCause.equals(cause);
if (player.getPlayer().isDead()) return false;
return cause == null || damageCause.equals(cause);
}
}