Fix entity stacking, looting

This commit is contained in:
ceze88 2023-03-29 21:21:00 +02:00
parent f4811ae1df
commit 640db6e344
9 changed files with 64 additions and 27 deletions

View File

@ -3,6 +3,7 @@ package com.songoda.ultimatestacker.commands;
import com.songoda.core.commands.AbstractCommand;
import com.songoda.core.utils.TextUtils;
import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
import com.songoda.ultimatestacker.utils.Methods;
import org.bukkit.Bukkit;
@ -48,7 +49,9 @@ public class CommandRemoveAll extends AbstractCommand {
if (entityO instanceof LivingEntity && (stackManager.isStackedEntity(entityO) || all)
&& type.equalsIgnoreCase("entities")) {
plugin.getEntityStackManager().getStack((LivingEntity) entityO).destroy();
EntityStack stack = plugin.getEntityStackManager().getStack((LivingEntity) entityO);
if (stack == null) continue;
stack.destroy();
amountRemoved++;
} else if (entityO.getType() == EntityType.DROPPED_ITEM && type.equalsIgnoreCase("items")) {
if (!UltimateStacker.hasCustomAmount((Item)entityO) && !all)

View File

@ -19,6 +19,7 @@ import org.bukkit.block.CreatureSpawner;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
@ -40,8 +41,9 @@ public class BlockListeners implements Listener {
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockInteract(PlayerInteractEvent event) {
if (event.useInteractedBlock() == Event.Result.DENY) return;
Block block = event.getClickedBlock();
Player player = event.getPlayer();
CompatibleHand hand = CompatibleHand.getHand(event);
@ -166,8 +168,9 @@ public class BlockListeners implements Listener {
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockPlace(BlockPlaceEvent event) {
if (event.isCancelled()) return;
Block block = event.getBlock();
Player player = event.getPlayer();
@ -196,8 +199,9 @@ public class BlockListeners implements Listener {
plugin.updateHologram(stack);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockBreak(BlockBreakEvent event) {
if (event.isCancelled()) return;
Block block = event.getBlock();
if (block.getType() != CompatibleMaterial.SPAWNER.getMaterial()) return;

View File

@ -7,6 +7,7 @@ import com.songoda.core.lootables.loot.DropUtils;
import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.settings.Settings;
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.GameRule;
import org.bukkit.Material;
@ -82,6 +83,10 @@ public class DeathListeners implements Listener {
drops.clear();
if (plugin.getCustomEntityManager().getCustomEntity(entity) == null) {
//replace %player% in drop commands with the last player to damage the entity
//Run commands here, or it will be buggy
runCommands(entity, drops);
if (plugin.getEntityStackManager().isStackedEntity(event.getEntity())) {
plugin.getEntityStackManager().getStack(event.getEntity()).onDeath(entity, drops, custom, event.getDroppedExp(), event);
} else {
@ -92,6 +97,25 @@ public class DeathListeners implements Listener {
finalItems.remove(entity.getUniqueId());
}
private void runCommands(LivingEntity entity, List<Drop> drops) {
String lastDamage = plugin.getEntityStackManager().getLastPlayerDamage(entity);
if (lastDamage != null) {
List<String> commands = new ArrayList<>();
drops.forEach(drop -> {
if (drop.getCommand() != null) {
String command = drop.getCommand().replace("%player%", lastDamage);
drop.setCommand(null);
commands.add(command);
}
});
Bukkit.getScheduler().runTask(plugin, () -> {
for (String command : commands) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
}
});
}
}
private boolean shouldDrop(LivingEntity entity, Material material) {
if (entity.getEquipment() != null && entity.getEquipment().getArmorContents().length != 0) {
if (Settings.DONT_DROP_ARMOR.getBoolean())

View File

@ -1,15 +1,16 @@
package com.songoda.ultimatestacker.listeners.entity;
import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.settings.Settings;
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Slime;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityTransformEvent;
import org.bukkit.event.world.EntitiesLoadEvent;
@ -31,11 +32,11 @@ public class EntityCurrentListener implements Listener {
&& event.getEntity() instanceof LivingEntity
&& event.getTransformedEntity() instanceof LivingEntity) {
if (event.getTransformReason().equals(EntityTransformEvent.TransformReason.SPLIT)) {
stackManager.getStack((LivingEntity) event.getEntity()).removeEntityFromStack(1);
event.setCancelled(true);
return;
}
EntityStack stack = stackManager.updateStack((LivingEntity) event.getEntity(), (LivingEntity) event.getTransformedEntity());
if (stack == null) return;
stack.releaseHost();
}
}

View File

@ -101,6 +101,10 @@ public class LootablesManager {
looting);
}
public List<ItemStack> getItemStackDrops(LivingEntity entity, int times) {
return getDrops(entity, times).stream().map(Drop::getItemStack).collect(Collectors.toList());
}
public List<Drop> getDrops(LivingEntity entity, int times) {
return getDrops(entity, times, 3);
}

View File

@ -23,6 +23,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
@ -116,22 +117,11 @@ public class EntityStack extends StackedEntity {
killed.setCustomName(null);
killed.setCustomNameVisible(false);
//replace %player% in drop commands with the last player to damage the entity
String lastDamage = plugin.getEntityStackManager().getLastPlayerDamage(killed);
if (lastDamage != null) {
drops.forEach(drop -> {
if (drop.getCommand() != null) {
drop.setCommand(drop.getCommand().replace("%player%", lastDamage));
}
});
}
boolean killWholeStack = Settings.KILL_WHOLE_STACK_ON_DEATH.getBoolean()
|| plugin.getMobFile().getBoolean("Mobs." + killed.getType().name() + ".Kill Whole Stack");
if (killWholeStack && getAmount() > 1) {
handleWholeStackDeath(killed, drops, custom, droppedExp, event);
return;
} else if (getAmount() > 1) {
List<String> reasons = Settings.INSTANT_KILL.getStringList();
EntityDamageEvent lastDamageCause = killed.getLastDamageCause();
@ -144,8 +134,8 @@ public class EntityStack extends StackedEntity {
return;
}
}
handleSingleStackDeath(killed, drops, droppedExp, event);
}
handleSingleStackDeath(killed, drops, droppedExp, event);
}
public synchronized LivingEntity takeOneAndSpawnEntity(Location location) {

View File

@ -111,10 +111,10 @@ public class EntityStackManager {
* @param newEntity The new entity to transfer the stack to.
* @return The new stack.
*/
public EntityStack transferStack(LivingEntity oldEntity, LivingEntity newEntity) {
public EntityStack transferStack(LivingEntity oldEntity, LivingEntity newEntity, boolean takeOne) {
EntityStack stack = getStack(oldEntity);
if (stack == null) return null;
EntityStack newStack = new EntityStack(newEntity, stack.getAmount());
EntityStack newStack = new EntityStack(newEntity, takeOne ? stack.getAmount()-1 : stack.getAmount());
stack.destroy();
return newStack;
}

View File

@ -54,4 +54,11 @@ public class CustomEntityManager {
public boolean isCustomEntity(Entity entity) {
return getCustomEntity(entity) != null && getCustomEntity(entity).isCustomEntity(entity);
}
public boolean isStackable(Entity entity) {
CustomEntity customEntity = getCustomEntity(entity);
if (customEntity == null) return true;
String key = customEntity.getPluginName().toLowerCase() + "_" + customEntity.getNBTIdentifier(entity).toLowerCase();
return !Settings.BLACKLISTED_CUSTOM_ENTITIES.getStringList().contains(key);
}
}

View File

@ -355,16 +355,20 @@ public class StackingTask extends TimerTask {
*/
private List<LivingEntity> getFriendlyStacksNearby(LivingEntity entity, double radius, boolean singleChunk) {
List<LivingEntity> entities = new ArrayList<>();
Set<CachedChunk> chunks = getNearbyChunks(new SWorld(entity.getWorld()), entity.getLocation(), radius, singleChunk);
for (CachedChunk chunk : chunks) {
Entity[] entityList = chunk.getEntities();
for (Entity e : entityList) {
if (!processed.contains(e.getUniqueId()) && e.getType() == entity.getType() && e instanceof LivingEntity && e.isValid() && e.getLocation().distance(entity.getLocation()) <= radius) {
entities.add((LivingEntity) e);
try {
Set<CachedChunk> chunks = getNearbyChunks(new SWorld(entity.getWorld()), entity.getLocation(), radius, singleChunk);
for (CachedChunk chunk : chunks) {
Entity[] entityList = getEntitiesInChunkSync(chunk).get();
for (Entity e : entityList) {
if (!processed.contains(e.getUniqueId()) && e.getType() == entity.getType() && e instanceof LivingEntity && e.isValid() && e.getLocation().distance(entity.getLocation()) <= radius) {
entities.add((LivingEntity) e);
}
}
}
entities.removeIf(entity1 -> entity1.equals(entity) || !UltimateStacker.getInstance().getCustomEntityManager().isStackable(entity1));
} catch (Exception ex) {
ex.printStackTrace();
}
entities.removeIf(entity1 -> entity1.equals(entity));
return entities;
}