use of dev.rosewood.rosestacker.event.AsyncEntityDeathEvent in project RoseStacker by Rosewood-Development.
the class StackedEntity method dropPartialStackLoot.
/**
* Drops loot for entities that are part of the stack.
* Does not include loot for the current entity (except for nether stars for withers).
*
* @param internalEntities The entities which should be part of this stack
* @param existingLoot The loot from this.entity, nullable
* @param droppedExp The exp dropped from this.entity
*/
public void dropPartialStackLoot(List<LivingEntity> internalEntities, Collection<ItemStack> existingLoot, int droppedExp) {
// Cache the current entity just in case it somehow changes while we are processing the loot
LivingEntity thisEntity = this.entity;
Collection<ItemStack> loot = new ArrayList<>();
if (existingLoot != null)
loot.addAll(existingLoot);
// The stack loot can either be processed synchronously or asynchronously depending on a setting
// It should always be processed async unless errors are caused by other plugins
boolean async = Setting.ENTITY_DEATH_EVENT_RUN_ASYNC.getBoolean();
boolean multiplyCustomLoot = Setting.ENTITY_MULTIPLY_CUSTOM_LOOT.getBoolean();
Runnable mainTask = () -> {
boolean callEvents = Setting.ENTITY_TRIGGER_DEATH_EVENT_FOR_ENTIRE_STACK_KILL.getBoolean();
int totalExp = droppedExp;
NMSHandler nmsHandler = NMSAdapter.getHandler();
boolean isAnimal = thisEntity instanceof Animals;
boolean isSlime = thisEntity instanceof Slime;
boolean isAccurateSlime = isSlime && ((SlimeStackSettings) this.stackSettings).isAccurateDropsWithKillEntireStackOnDeath();
for (LivingEntity entity : internalEntities) {
// Propagate fire ticks and last damage cause
entity.setFireTicks(thisEntity.getFireTicks());
entity.setLastDamageCause(thisEntity.getLastDamageCause());
nmsHandler.setLastHurtBy(entity, thisEntity.getKiller());
int iterations = 1;
if (isSlime) {
Slime slime = (Slime) entity;
if (isAccurateSlime) {
int totalSlimes = 1;
int size = slime.getSize();
while (size > 1) {
size /= 2;
int currentSlimes = totalSlimes;
totalSlimes = StackerUtils.randomInRange(currentSlimes * 2, currentSlimes * 4);
}
iterations = totalSlimes;
}
slime.setSize(1);
}
boolean isBaby = isAnimal && !((Animals) entity).isAdult();
int desiredExp = isBaby ? 0 : droppedExp;
for (int i = 0; i < iterations; i++) {
Collection<ItemStack> entityLoot = isBaby ? Collections.emptyList() : EntityUtils.getEntityLoot(entity, thisEntity.getKiller(), thisEntity.getLocation());
if (callEvents && !multiplyCustomLoot) {
EntityDeathEvent deathEvent = new AsyncEntityDeathEvent(entity, new ArrayList<>(entityLoot), desiredExp);
Bukkit.getPluginManager().callEvent(deathEvent);
totalExp += deathEvent.getDroppedExp();
loot.addAll(deathEvent.getDrops());
} else {
loot.addAll(entityLoot);
totalExp += desiredExp;
}
}
}
if (multiplyCustomLoot) {
EntityDeathEvent deathEvent = new EntityDeathEvent(thisEntity, new ArrayList<>(), 0);
for (int i = 0, k = this.getStackSize() - 1; i < k; i++) loot.addAll(deathEvent.getDrops());
totalExp += deathEvent.getDroppedExp() * (this.getStackSize() - 1);
}
int finalTotalExp = totalExp;
Runnable finishTask = () -> {
RoseStacker.getInstance().getManager(StackManager.class).preStackItems(loot, thisEntity.getLocation());
if (Setting.ENTITY_DROP_ACCURATE_EXP.getBoolean() && finalTotalExp > 0)
StackerUtils.dropExperience(thisEntity.getLocation(), finalTotalExp, finalTotalExp, finalTotalExp / 2);
};
// Withers always drop nether stars on death, however this isn't in the actual wither loot table for some reason
if (this.entity.getType() == EntityType.WITHER)
loot.addAll(GuiUtil.getMaterialAmountAsItemStacks(Material.NETHER_STAR, internalEntities.size()));
if (async) {
Bukkit.getScheduler().runTask(RoseStacker.getInstance(), finishTask);
} else {
finishTask.run();
}
};
if (async) {
Bukkit.getScheduler().runTaskAsynchronously(RoseStacker.getInstance(), mainTask);
} else {
mainTask.run();
}
}
Aggregations