Search in sources :

Example 1 with AsyncEntityDeathEvent

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();
    }
}
Also used : AsyncEntityDeathEvent(dev.rosewood.rosestacker.event.AsyncEntityDeathEvent) EntityDeathEvent(org.bukkit.event.entity.EntityDeathEvent) AsyncEntityDeathEvent(dev.rosewood.rosestacker.event.AsyncEntityDeathEvent) StackManager(dev.rosewood.rosestacker.manager.StackManager) ArrayList(java.util.ArrayList) Slime(org.bukkit.entity.Slime) NMSHandler(dev.rosewood.rosestacker.nms.NMSHandler) LivingEntity(org.bukkit.entity.LivingEntity) Animals(org.bukkit.entity.Animals) SlimeStackSettings(dev.rosewood.rosestacker.stack.settings.entity.SlimeStackSettings) Collection(java.util.Collection) ItemStack(org.bukkit.inventory.ItemStack)

Aggregations

AsyncEntityDeathEvent (dev.rosewood.rosestacker.event.AsyncEntityDeathEvent)1 StackManager (dev.rosewood.rosestacker.manager.StackManager)1 NMSHandler (dev.rosewood.rosestacker.nms.NMSHandler)1 SlimeStackSettings (dev.rosewood.rosestacker.stack.settings.entity.SlimeStackSettings)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 Animals (org.bukkit.entity.Animals)1 LivingEntity (org.bukkit.entity.LivingEntity)1 Slime (org.bukkit.entity.Slime)1 EntityDeathEvent (org.bukkit.event.entity.EntityDeathEvent)1 ItemStack (org.bukkit.inventory.ItemStack)1