mirror of
https://github.com/BentoBoxWorld/Limits.git
synced 2025-02-19 22:03:05 +01:00
Possible fix for dupe exploits
https://github.com/BentoBoxWorld/Limits/issues/97
This commit is contained in:
parent
b8682960cf
commit
07101c72dc
@ -16,7 +16,9 @@ import org.bukkit.World;
|
|||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
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;
|
||||||
@ -120,12 +122,49 @@ public class EntityLimitListener implements Listener {
|
|||||||
case SPAWNER_EGG:
|
case SPAWNER_EGG:
|
||||||
bypass = checkByPass(e.getLocation());
|
bypass = checkByPass(e.getLocation());
|
||||||
break;
|
break;
|
||||||
|
case SHOULDER_ENTITY:
|
||||||
|
// Special case - do nothing - jumping around spawns parrots as they drop off player's shoulder
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
// Other natural reasons
|
// Other natural reasons
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Tag the entity with the island spawn location
|
// Some checks can be done async, some not
|
||||||
checkLimit(e, bypass);
|
switch (e.getSpawnReason()) {
|
||||||
|
case BEEHIVE:
|
||||||
|
case BREEDING:
|
||||||
|
case CURED:
|
||||||
|
case DISPENSE_EGG:
|
||||||
|
case EGG:
|
||||||
|
case ENDER_PEARL:
|
||||||
|
case EXPLOSION:
|
||||||
|
case INFECTION:
|
||||||
|
case JOCKEY:
|
||||||
|
case LIGHTNING:
|
||||||
|
case MOUNT:
|
||||||
|
case NETHER_PORTAL:
|
||||||
|
case OCELOT_BABY:
|
||||||
|
case PATROL:
|
||||||
|
case RAID:
|
||||||
|
case REINFORCEMENTS:
|
||||||
|
case SHEARED:
|
||||||
|
case SHOULDER_ENTITY:
|
||||||
|
case SILVERFISH_BLOCK:
|
||||||
|
case SLIME_SPLIT:
|
||||||
|
case SPAWNER_EGG:
|
||||||
|
case TRAP:
|
||||||
|
case VILLAGE_DEFENSE:
|
||||||
|
case VILLAGE_INVASION:
|
||||||
|
// Check limit sync
|
||||||
|
checkLimit(e, e.getEntity(), e.getSpawnReason(), bypass, false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Check limit async
|
||||||
|
checkLimit(e, e.getEntity(), e.getSpawnReason(), bypass, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkByPass(Location l) {
|
private boolean checkByPass(Location l) {
|
||||||
@ -169,93 +208,107 @@ public class EntityLimitListener implements Listener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkLimit(CreatureSpawnEvent e, boolean bypass) {
|
/**
|
||||||
e.setCancelled(true);
|
* Check if a creature is allowed to spawn or not
|
||||||
|
* @param e - CreatureSpawnEvent
|
||||||
|
* @param bypass - true if the player involved can bypass the checks
|
||||||
|
* @param async
|
||||||
|
*/
|
||||||
|
private void checkLimit(Cancellable c, LivingEntity e, SpawnReason reason, boolean bypass, boolean async) {
|
||||||
Location l = e.getLocation();
|
Location l = e.getLocation();
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(BentoBox.getInstance(), () ->
|
if (async) {
|
||||||
|
c.setCancelled(true);
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(BentoBox.getInstance(), () -> processIsland(c, e, l, reason, bypass, async));
|
||||||
|
} else {
|
||||||
|
processIsland(c, e, l, reason, bypass, async);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processIsland(Cancellable c, LivingEntity e, Location l, SpawnReason reason, boolean bypass, boolean async) {
|
||||||
addon.getIslands().getIslandAt(e.getLocation()).ifPresent(island -> {
|
addon.getIslands().getIslandAt(e.getLocation()).ifPresent(island -> {
|
||||||
// Check if creature is allowed to spawn or not
|
// Check if creature is allowed to spawn or not
|
||||||
AtLimitResult res = atLimit(island, e.getEntity());
|
AtLimitResult res = atLimit(island, e);
|
||||||
|
|
||||||
if (bypass || island.isSpawn() || !res.hit()) {
|
if (bypass || island.isSpawn() || !res.hit()) {
|
||||||
// Allowed
|
// Allowed
|
||||||
Bukkit.getScheduler().runTask(BentoBox.getInstance(), () -> {
|
if (async) {
|
||||||
//BentoBox.getInstance().logDebug("Allowed " + e.getEntity());
|
Bukkit.getScheduler().runTask(BentoBox.getInstance(), () -> {
|
||||||
/*
|
l.getWorld().spawn(l, e.getClass(), entity -> preSpawn(entity, reason, l));
|
||||||
e.getEntity().remove();
|
|
||||||
// If the entity was build, drop the building materials
|
|
||||||
Bukkit.getScheduler().runTask(addon.getPlugin(), () -> replaceEntity(e));
|
|
||||||
*/
|
|
||||||
|
|
||||||
l.getWorld().spawn(l, e.getEntity().getClass(), entity -> {
|
|
||||||
justSpawned.add(entity.getUniqueId());
|
|
||||||
// Check for entities that need cleanup
|
|
||||||
switch (e.getSpawnReason()) {
|
|
||||||
case BUILD_IRONGOLEM:
|
|
||||||
l.getBlock().setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
// Look for arms
|
|
||||||
if (l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).getType().equals(Material.IRON_BLOCK)) {
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.SOUTH).setType(Material.AIR);
|
|
||||||
} else {
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.EAST).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.WEST).setType(Material.AIR);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BUILD_SNOWMAN:
|
|
||||||
l.getBlock().setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
break;
|
|
||||||
case BUILD_WITHER:
|
|
||||||
l.getBlock().setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
// Look for arms
|
|
||||||
if (l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).getType().equals(Material.SOUL_SAND)) {
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.SOUTH).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.SOUTH).getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
} else {
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.EAST).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.WEST).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.EAST).getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.WEST).getRelative(BlockFace.UP).setType(Material.AIR);
|
|
||||||
}
|
|
||||||
// Create explosion
|
|
||||||
l.getWorld().createExplosion(l, 7F, true, true, entity);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
} // else do nothing
|
||||||
} else {
|
} else {
|
||||||
e.getEntity().remove();
|
if (async) {
|
||||||
|
e.remove();
|
||||||
|
} else {
|
||||||
|
c.setCancelled(true);
|
||||||
|
}
|
||||||
// If the reason is anything but because of a spawner then tell players within range
|
// If the reason is anything but because of a spawner then tell players within range
|
||||||
tellPlayers(e, res);
|
tellPlayers(c, l, e, reason, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void preSpawn(Entity entity, SpawnReason reason, Location l) {
|
||||||
|
justSpawned.add(entity.getUniqueId());
|
||||||
|
// Check for entities that need cleanup
|
||||||
|
switch (reason) {
|
||||||
|
case BUILD_IRONGOLEM:
|
||||||
|
l.getBlock().setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
// Look for arms
|
||||||
|
if (l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).getType().equals(Material.IRON_BLOCK)) {
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.SOUTH).setType(Material.AIR);
|
||||||
|
} else {
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.EAST).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.WEST).setType(Material.AIR);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BUILD_SNOWMAN:
|
||||||
|
l.getBlock().setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
break;
|
||||||
|
case BUILD_WITHER:
|
||||||
|
l.getBlock().setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
// Look for arms
|
||||||
|
if (l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).getType().equals(Material.SOUL_SAND)) {
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.SOUTH).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.NORTH).getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.SOUTH).getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
} else {
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.EAST).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.WEST).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.EAST).getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
l.getBlock().getRelative(BlockFace.UP).getRelative(BlockFace.WEST).getRelative(BlockFace.UP).setType(Material.AIR);
|
||||||
|
}
|
||||||
|
// Create explosion
|
||||||
|
l.getWorld().createExplosion(l, 7F, true, true, entity);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
private void tellPlayers(CreatureSpawnEvent e, AtLimitResult res) {
|
|
||||||
if (!e.getSpawnReason().equals(SpawnReason.SPAWNER) && !e.getSpawnReason().equals(SpawnReason.NATURAL)
|
}
|
||||||
&& !e.getSpawnReason().equals(SpawnReason.INFECTION) && !e.getSpawnReason().equals(SpawnReason.NETHER_PORTAL)
|
}
|
||||||
&& !e.getSpawnReason().equals(SpawnReason.REINFORCEMENTS) && !e.getSpawnReason().equals(SpawnReason.SLIME_SPLIT)) {
|
|
||||||
World w = e.getLocation().getWorld();
|
private void tellPlayers(Cancellable e, Location l, LivingEntity entity, SpawnReason reason, AtLimitResult res) {
|
||||||
|
if (!reason.equals(SpawnReason.SPAWNER) && !reason.equals(SpawnReason.NATURAL)
|
||||||
|
&& !reason.equals(SpawnReason.INFECTION) && !reason.equals(SpawnReason.NETHER_PORTAL)
|
||||||
|
&& !reason.equals(SpawnReason.REINFORCEMENTS) && !reason.equals(SpawnReason.SLIME_SPLIT)) {
|
||||||
|
World w = l.getWorld();
|
||||||
if (w == null) return;
|
if (w == null) return;
|
||||||
Bukkit.getScheduler().runTask(addon.getPlugin(), () -> {
|
Bukkit.getScheduler().runTask(addon.getPlugin(), () -> {
|
||||||
for (Entity ent : w.getNearbyEntities(e.getLocation(), 5, 5, 5)) {
|
for (Entity ent : w.getNearbyEntities(l, 5, 5, 5)) {
|
||||||
if (ent instanceof Player) {
|
if (ent instanceof Player) {
|
||||||
if (res.getTypelimit() != null) {
|
if (res.getTypelimit() != null) {
|
||||||
User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]",
|
User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]",
|
||||||
Util.prettifyText(e.getEntityType().toString()),
|
Util.prettifyText(entity.getType().toString()),
|
||||||
TextVariables.NUMBER, String.valueOf(res.getTypelimit().getValue()));
|
TextVariables.NUMBER, String.valueOf(res.getTypelimit().getValue()));
|
||||||
} else {
|
} else {
|
||||||
User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]",
|
User.getInstance(ent).notify("entity-limits.hit-limit", "[entity]",
|
||||||
|
Loading…
Reference in New Issue
Block a user