LagAssist is a plugin that provides tools to prevent, analyse or resolve lag.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
5.8 KiB

package cx.sfy.LagAssist.chunks;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.event.vehicle.VehicleCreateEvent;
import cx.sfy.LagAssist.Main;
import cx.sfy.LagAssist.utils.Cache;
public class ChkLimiter implements Listener {
private static Cache<Chunk, Entity[]> entcache = new Cache<Chunk, Entity[]>(30);
private static Cache<Chunk, BlockState[]> tilecache = new Cache<Chunk, BlockState[]>(100);
private static int moblimit = -1;
private static int tilelimit = -1;
public static void Enabler(boolean reload) {
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new ChkLimiter(), Main.p);
runTask();
}
Bukkit.getLogger().info(" §e[§a✔§e] §fChunk Limiter.");
moblimit = Main.config.getInt("limiter.mobs.total-limit");
tilelimit = Main.config.getInt("limiter.tiles.total-limit");
}
static int i = 0;
private static void runTask() {
Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.p, () -> {
i++;
if (i % Main.config.getInt("limiter.timer-time") == 0) {
for (World w : Bukkit.getWorlds()) {
for (Chunk chk : w.getLoadedChunks()) {
Map<EntityType, Integer> counts = new HashMap<EntityType, Integer>();
for (Entity ent : chk.getEntities()) {
EntityType type = ent.getType();
int allowed = getMobMaxHard(type);
if (allowed == -1) {
continue;
}
int count = counts.getOrDefault(ent.getType(), 0);
// Over 30 bye
if (count < allowed) {
counts.put(type, count + 1);
continue;
}
ent.remove();
}
}
}
}
tilecache.tick();
entcache.tick();
}, 1L, 1L);
}
private static int getMobMaxHard(EntityType entype) {
String location = "limiter.mobs.hard-limit." + entype.toString().toLowerCase();
if (Main.config.contains(location)) {
return Main.config.getInt(location);
}
return -1;
}
private static int getMobMaxSoft(EntityType entype) {
String location = "limiter.mobs.soft-limit." + entype.toString().toLowerCase();
if (Main.config.contains(location)) {
return Main.config.getInt(location);
}
return -1;
}
private static int getMobMaxSoft(Entity ent) {
return getMobMaxSoft(ent.getType());
}
private static int getTileMax(Class<?> cls) {
String location = "limiter.tiles.per-limit." + cls.getSimpleName().toLowerCase();
if (Main.config.contains(location)) {
return Main.config.getInt(location);
}
return -1;
}
private static int getTileMax(Block b) {
return getTileMax(b.getState().getClass());
}
private static int getMobCount(Chunk chk, EntityType entype) {
int ents = 0;
if (!entcache.isCached(chk)) {
entcache.putCached(chk, chk.getEntities());
}
for (Entity ent : entcache.getCached(chk)) {
if (ent == null) {
continue;
}
if (ent.getType() != entype) {
continue;
}
ents++;
}
return ents;
}
private static int getMobCount(Chunk chk) {
return chk.getEntities().length;
}
private static int getTileCount(Chunk chk, Class<?> type) {
int tls = 0;
if (!tilecache.isCached(chk)) {
tilecache.putCached(chk, chk.getTileEntities());
}
for (BlockState tle : tilecache.getCached(chk)) {
if (tle == null) {
continue;
}
if (!tle.getClass().equals(type)) {
continue;
}
tls++;
}
return tls;
}
private static int getTileCount(Chunk chk) {
return chk.getTileEntities().length;
}
// VERIFIERS (CODE QUALITY IMPROVERS)
private static boolean isDeniedMob(Entity ent) {
EntityType etype = ent.getType();
// Fix issues with destroying player objects.
if (etype == EntityType.PLAYER) {
return false;
}
Chunk chk = ent.getLocation().getChunk();
int current = getMobCount(chk, etype);
int maximum = getMobMaxSoft(ent);
if (maximum < 0) {
current = getMobCount(chk);
maximum = moblimit;
}
if (maximum < 0) {
return false;
}
if (current < maximum) {
return false;
}
return true;
}
private static boolean isDeniedTile(Block b) {
Chunk chk = b.getLocation().getChunk();
Class<?> type = b.getState().getClass();
String typename = type.getSimpleName().toLowerCase();
Main.sendDebug("isDeniedTile: " + typename, 1);
if (typename.equals("craftblockstate")) {
return false;
}
int current = getTileCount(chk, type);
int maximum = getTileMax(b);
if (maximum < 0) {
current = getTileCount(chk);
maximum = tilelimit;
}
if (maximum < 0) {
return false;
}
if (current < maximum) {
return false;
}
return true;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onVehicleSpawn(VehicleCreateEvent e) {
Vehicle ent = e.getVehicle();
// 1.8 doesn't support cancel. Fuk
if (isDeniedMob(ent)) {
ent.remove();
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onSpawn(EntitySpawnEvent e) {
if (e.isCancelled()) {
return;
}
Entity ent = e.getEntity();
e.setCancelled(isDeniedMob(ent));
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlace(BlockPlaceEvent e) {
if (e.isCancelled()) {
return;
}
Block b = e.getBlock();
e.setCancelled(isDeniedTile(b));
}
}