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.commands.AbstractCommand;
import com.songoda.core.utils.TextUtils; import com.songoda.core.utils.TextUtils;
import com.songoda.ultimatestacker.UltimateStacker; import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager; import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
import com.songoda.ultimatestacker.utils.Methods; import com.songoda.ultimatestacker.utils.Methods;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -48,7 +49,9 @@ public class CommandRemoveAll extends AbstractCommand {
if (entityO instanceof LivingEntity && (stackManager.isStackedEntity(entityO) || all) if (entityO instanceof LivingEntity && (stackManager.isStackedEntity(entityO) || all)
&& type.equalsIgnoreCase("entities")) { && type.equalsIgnoreCase("entities")) {
plugin.getEntityStackManager().getStack((LivingEntity) entityO).destroy(); EntityStack stack = plugin.getEntityStackManager().getStack((LivingEntity) entityO);
if (stack == null) continue;
stack.destroy();
amountRemoved++; amountRemoved++;
} else if (entityO.getType() == EntityType.DROPPED_ITEM && type.equalsIgnoreCase("items")) { } else if (entityO.getType() == EntityType.DROPPED_ITEM && type.equalsIgnoreCase("items")) {
if (!UltimateStacker.hasCustomAmount((Item)entityO) && !all) 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.enchantments.Enchantment;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@ -40,8 +41,9 @@ public class BlockListeners implements Listener {
this.plugin = plugin; this.plugin = plugin;
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST)
public void onBlockInteract(PlayerInteractEvent event) { public void onBlockInteract(PlayerInteractEvent event) {
if (event.useInteractedBlock() == Event.Result.DENY) return;
Block block = event.getClickedBlock(); Block block = event.getClickedBlock();
Player player = event.getPlayer(); Player player = event.getPlayer();
CompatibleHand hand = CompatibleHand.getHand(event); 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) { public void onBlockPlace(BlockPlaceEvent event) {
if (event.isCancelled()) return;
Block block = event.getBlock(); Block block = event.getBlock();
Player player = event.getPlayer(); Player player = event.getPlayer();
@ -196,8 +199,9 @@ public class BlockListeners implements Listener {
plugin.updateHologram(stack); plugin.updateHologram(stack);
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST)
public void onBlockBreak(BlockBreakEvent event) { public void onBlockBreak(BlockBreakEvent event) {
if (event.isCancelled()) return;
Block block = event.getBlock(); Block block = event.getBlock();
if (block.getType() != CompatibleMaterial.SPAWNER.getMaterial()) return; 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.UltimateStacker;
import com.songoda.ultimatestacker.settings.Settings; import com.songoda.ultimatestacker.settings.Settings;
import com.songoda.ultimatestacker.stackable.entity.EntityStack; import com.songoda.ultimatestacker.stackable.entity.EntityStack;
import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.GameRule; import org.bukkit.GameRule;
import org.bukkit.Material; import org.bukkit.Material;
@ -82,6 +83,10 @@ public class DeathListeners implements Listener {
drops.clear(); drops.clear();
if (plugin.getCustomEntityManager().getCustomEntity(entity) == null) { 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())) { if (plugin.getEntityStackManager().isStackedEntity(event.getEntity())) {
plugin.getEntityStackManager().getStack(event.getEntity()).onDeath(entity, drops, custom, event.getDroppedExp(), event); plugin.getEntityStackManager().getStack(event.getEntity()).onDeath(entity, drops, custom, event.getDroppedExp(), event);
} else { } else {
@ -92,6 +97,25 @@ public class DeathListeners implements Listener {
finalItems.remove(entity.getUniqueId()); 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) { private boolean shouldDrop(LivingEntity entity, Material material) {
if (entity.getEquipment() != null && entity.getEquipment().getArmorContents().length != 0) { if (entity.getEquipment() != null && entity.getEquipment().getArmorContents().length != 0) {
if (Settings.DONT_DROP_ARMOR.getBoolean()) if (Settings.DONT_DROP_ARMOR.getBoolean())

View File

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

View File

@ -101,6 +101,10 @@ public class LootablesManager {
looting); 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) { public List<Drop> getDrops(LivingEntity entity, int times) {
return getDrops(entity, times, 3); return getDrops(entity, times, 3);
} }

View File

@ -23,6 +23,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
@ -116,22 +117,11 @@ public class EntityStack extends StackedEntity {
killed.setCustomName(null); killed.setCustomName(null);
killed.setCustomNameVisible(false); 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() boolean killWholeStack = Settings.KILL_WHOLE_STACK_ON_DEATH.getBoolean()
|| plugin.getMobFile().getBoolean("Mobs." + killed.getType().name() + ".Kill Whole Stack"); || plugin.getMobFile().getBoolean("Mobs." + killed.getType().name() + ".Kill Whole Stack");
if (killWholeStack && getAmount() > 1) { if (killWholeStack && getAmount() > 1) {
handleWholeStackDeath(killed, drops, custom, droppedExp, event); handleWholeStackDeath(killed, drops, custom, droppedExp, event);
return;
} else if (getAmount() > 1) { } else if (getAmount() > 1) {
List<String> reasons = Settings.INSTANT_KILL.getStringList(); List<String> reasons = Settings.INSTANT_KILL.getStringList();
EntityDamageEvent lastDamageCause = killed.getLastDamageCause(); EntityDamageEvent lastDamageCause = killed.getLastDamageCause();
@ -144,9 +134,9 @@ public class EntityStack extends StackedEntity {
return; return;
} }
} }
}
handleSingleStackDeath(killed, drops, droppedExp, event); handleSingleStackDeath(killed, drops, droppedExp, event);
} }
}
public synchronized LivingEntity takeOneAndSpawnEntity(Location location) { public synchronized LivingEntity takeOneAndSpawnEntity(Location location) {
if (amount <= 0) return null; if (amount <= 0) return null;

View File

@ -111,10 +111,10 @@ public class EntityStackManager {
* @param newEntity The new entity to transfer the stack to. * @param newEntity The new entity to transfer the stack to.
* @return The new stack. * @return The new stack.
*/ */
public EntityStack transferStack(LivingEntity oldEntity, LivingEntity newEntity) { public EntityStack transferStack(LivingEntity oldEntity, LivingEntity newEntity, boolean takeOne) {
EntityStack stack = getStack(oldEntity); EntityStack stack = getStack(oldEntity);
if (stack == null) return null; 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(); stack.destroy();
return newStack; return newStack;
} }

View File

@ -54,4 +54,11 @@ public class CustomEntityManager {
public boolean isCustomEntity(Entity entity) { public boolean isCustomEntity(Entity entity) {
return getCustomEntity(entity) != null && getCustomEntity(entity).isCustomEntity(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) { private List<LivingEntity> getFriendlyStacksNearby(LivingEntity entity, double radius, boolean singleChunk) {
List<LivingEntity> entities = new ArrayList<>(); List<LivingEntity> entities = new ArrayList<>();
try {
Set<CachedChunk> chunks = getNearbyChunks(new SWorld(entity.getWorld()), entity.getLocation(), radius, singleChunk); Set<CachedChunk> chunks = getNearbyChunks(new SWorld(entity.getWorld()), entity.getLocation(), radius, singleChunk);
for (CachedChunk chunk : chunks) { for (CachedChunk chunk : chunks) {
Entity[] entityList = chunk.getEntities(); Entity[] entityList = getEntitiesInChunkSync(chunk).get();
for (Entity e : entityList) { for (Entity e : entityList) {
if (!processed.contains(e.getUniqueId()) && e.getType() == entity.getType() && e instanceof LivingEntity && e.isValid() && e.getLocation().distance(entity.getLocation()) <= radius) { 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.add((LivingEntity) e);
} }
} }
} }
entities.removeIf(entity1 -> entity1.equals(entity)); entities.removeIf(entity1 -> entity1.equals(entity) || !UltimateStacker.getInstance().getCustomEntityManager().isStackable(entity1));
} catch (Exception ex) {
ex.printStackTrace();
}
return entities; return entities;
} }