Fixes uncounting of blocks used by wither, golem or snowman making

https://github.com/BentoBoxWorld/Limits/issues/103
This commit is contained in:
tastybento 2020-09-20 09:07:35 -07:00
parent 0c107f2bab
commit 3b367407ae
2 changed files with 68 additions and 53 deletions

View File

@ -323,7 +323,6 @@ public class BlockLimitsListener implements Listener {
return -1;
}
islandCountMap.putIfAbsent(id, new IslandBlockCount(id, gameMode));
saveMap.putIfAbsent(id, 0);
if (add) {
// Check limit
int limit = checkLimit(b.getWorld(), fixMaterial(b.getType()), id);
@ -331,7 +330,6 @@ public class BlockLimitsListener implements Listener {
return limit;
}
islandCountMap.get(id).add(fixMaterial(b.getType()));
saveMap.merge(id, 1, Integer::sum);
} else {
if (islandCountMap.containsKey(id)) {
// Check for changes
@ -345,17 +343,39 @@ public class BlockLimitsListener implements Listener {
islandCountMap.get(id).add(fixed);
}
islandCountMap.get(id).remove(fixMaterial(b.getType()));
saveMap.merge(id, 1, Integer::sum);
}
}
if (saveMap.get(id) > CHANGE_LIMIT) {
handler.saveObjectAsync(islandCountMap.get(id));
saveMap.remove(id);
}
updateSaveMap(id);
return -1;
}).orElse(-1);
}
/**
* Removed a block from any island limit count
* @param b - block to remove
*/
public void removeBlock(Block b) {
// Get island
addon.getIslands().getIslandAt(b.getLocation()).ifPresent(i -> {
String id = i.getUniqueId();
String gameMode = addon.getGameModeName(b.getWorld());
if (gameMode.isEmpty()) {
// Invalid world
return;
}
islandCountMap.computeIfAbsent(id, k -> new IslandBlockCount(id, gameMode)).remove(fixMaterial(b.getType()));
updateSaveMap(id);
});
}
private void updateSaveMap(String id) {
saveMap.putIfAbsent(id, 0);
if (saveMap.merge(id, 1, Integer::sum) > CHANGE_LIMIT) {
handler.saveObjectAsync(islandCountMap.get(id));
saveMap.remove(id);
}
}
/**
* Check if this material is at its limit for world on this island
*

View File

@ -13,6 +13,7 @@ import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@ -42,7 +43,6 @@ public class EntityLimitListener implements Listener {
private static final String MOD_BYPASS = "mod.bypass";
private final Limits addon;
private final List<UUID> justSpawned = new ArrayList<>();
private final boolean jetsMinions;
private static final List<BlockFace> CARDINALS;
static {
List<BlockFace> cardinals = new ArrayList<>();
@ -62,8 +62,6 @@ public class EntityLimitListener implements Listener {
public EntityLimitListener(Limits addon) {
this.addon = addon;
justSpawned.clear();
// Check for JetsMinions
jetsMinions = Bukkit.getPluginManager().getPlugin("JetsMinions") != null;
}
/**
@ -146,42 +144,13 @@ public class EntityLimitListener implements Listener {
break;
}
// Some checks can be done async, some not
// Special handling for JetsMinions
if (jetsMinions && e.getEntityType().equals(EntityType.ARMOR_STAND)) {
// Check limit sync
checkLimit(e, e.getEntity(), e.getSpawnReason(), bypass, false);
return;
}
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;
case BUILD_WITHER:
case BUILD_SNOWMAN:
case BUILD_IRONGOLEM:
checkLimit(e, e.getEntity(), e.getSpawnReason(), bypass, true);
default:
// Check limit sync - TODO, work out why async causes problems.
// Check limit sync
checkLimit(e, e.getEntity(), e.getSpawnReason(), bypass, false);
break;
@ -294,11 +263,13 @@ public class EntityLimitListener implements Listener {
}
private void detectIronGolem(Location l) {
Block legs = l.getBlock();
// Erase legs
l.getBlock().setType(Material.AIR);
addon.getBlockLimitListener().removeBlock(legs);
legs.setType(Material.AIR);
// Look around for possible constructions
for (BlockFace bf : CARDINALS) {
Block body = l.getBlock().getRelative(bf);
Block body = legs.getRelative(bf);
if (body.getType().equals(Material.IRON_BLOCK)) {
// Check for head
Block head = body.getRelative(bf);
@ -311,6 +282,10 @@ public class EntityLimitListener implements Listener {
&& arm1.getRelative(bf.getOppositeFace()).isEmpty()
&& arm2.getRelative(bf.getOppositeFace()).isEmpty()) {
// Erase!
addon.getBlockLimitListener().removeBlock(body);
addon.getBlockLimitListener().removeBlock(arm1);
addon.getBlockLimitListener().removeBlock(arm2);
addon.getBlockLimitListener().removeBlock(head);
body.setType(Material.AIR);
arm1.setType(Material.AIR);
arm2.setType(Material.AIR);
@ -325,16 +300,21 @@ public class EntityLimitListener implements Listener {
}
private void detectSnowman(Location l) {
Block legs = l.getBlock();
// Erase legs
l.getBlock().setType(Material.AIR);
addon.getBlockLimitListener().removeBlock(legs);
legs.setType(Material.AIR);
// Look around for possible constructions
for (BlockFace bf : CARDINALS) {
Block body = l.getBlock().getRelative(bf);
Block body = legs.getRelative(bf);
if (body.getType().equals(Material.SNOW_BLOCK)) {
// Check for head
Block head = body.getRelative(bf);
if (head.getType().equals(Material.CARVED_PUMPKIN)) {
// Erase
addon.getBlockLimitListener().removeBlock(body);
addon.getBlockLimitListener().removeBlock(head);
body.setType(Material.AIR);
head.setType(Material.AIR);
return;
@ -345,12 +325,14 @@ public class EntityLimitListener implements Listener {
}
private void detectWither(Location l) {
Block legs = l.getBlock();
// Erase legs
l.getBlock().setType(Material.AIR);
addon.getBlockLimitListener().removeBlock(legs);
legs.setType(Material.AIR);
// Look around for possible constructions
for (BlockFace bf : CARDINALS) {
Block body = l.getBlock().getRelative(bf);
if (body.getType().equals(Material.SOUL_SAND)) {
Block body = legs.getRelative(bf);
if (isWither(body)) {
// Check for head
Block head = body.getRelative(bf);
if (head.getType().equals(Material.WITHER_SKELETON_SKULL) || head.getType().equals(Material.WITHER_SKELETON_WALL_SKULL)) {
@ -360,14 +342,20 @@ public class EntityLimitListener implements Listener {
Block arm2 = body.getRelative(bf2.getOppositeFace());
Block head2 = arm1.getRelative(bf);
Block head3 = arm2.getRelative(bf);
if (arm1.getType() == Material.SOUL_SAND
&& arm2.getType() == Material.SOUL_SAND
if (isWither(arm1)
&& isWither(arm2)
&& arm1.getRelative(bf.getOppositeFace()).isEmpty()
&& arm2.getRelative(bf.getOppositeFace()).isEmpty()
&& (head2.getType().equals(Material.WITHER_SKELETON_SKULL) || head2.getType().equals(Material.WITHER_SKELETON_WALL_SKULL))
&& (head3.getType().equals(Material.WITHER_SKELETON_SKULL) || head3.getType().equals(Material.WITHER_SKELETON_WALL_SKULL))
) {
// Erase!
addon.getBlockLimitListener().removeBlock(body);
addon.getBlockLimitListener().removeBlock(arm1);
addon.getBlockLimitListener().removeBlock(arm2);
addon.getBlockLimitListener().removeBlock(head);
addon.getBlockLimitListener().removeBlock(head2);
addon.getBlockLimitListener().removeBlock(head3);
body.setType(Material.AIR);
arm1.setType(Material.AIR);
arm2.setType(Material.AIR);
@ -383,6 +371,13 @@ public class EntityLimitListener implements Listener {
}
private boolean isWither(Block body) {
if (Util.getMinecraftVersion() < 16) {
return body.getType().equals(Material.SOUL_SAND);
}
return Tag.WITHER_SUMMON_BASE_BLOCKS.isTagged(body.getType());
}
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)