Skip to content

Commit

Permalink
bring back falling block limit
Browse files Browse the repository at this point in the history
  • Loading branch information
xGinko committed Aug 5, 2024
1 parent 83c2df3 commit e898ffc
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package me.xginko.aef.modules.chunklimits;

import com.cryptomorin.xseries.XEntityType;
import me.xginko.aef.modules.AEFModule;
import me.xginko.aef.utils.LocationUtil;
import me.xginko.aef.utils.models.ChunkUID;
import me.xginko.aef.utils.models.ExpiringSet;
import org.bukkit.Chunk;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;

import java.time.Duration;

public class FallingBlockLimit extends AEFModule implements Listener {

private final ExpiringSet<ChunkUID> checkedChunks;
private final int maxFallingGravityBlockPerChunk;
private final boolean logIsEnabled;

public FallingBlockLimit() {
super("chunk-limits.falling-block-limit");
config.addComment(configPath + ".enable", """
Prevent players from placing massive sand chunks, then collapsing\s
them to kill the server.""");
this.logIsEnabled = config.getBoolean(configPath + ".log", false);
this.maxFallingGravityBlockPerChunk = config.getInt(configPath + ".max-falling-gravity-blocks-per-chunk", 60, """
Removes any falling block if there is more than x blocks actively\s
falling in a chunk.""");
long chunkCheckDelay = Math.max(1, config.getInt(configPath + ".chunk-check-delay-in-ticks", 20, """
Delay in ticks until the same chunk can be checked again.\s
Prevents overchecking, because physics events can be called many\s
times in a short time for the same chunk.""")) * 50L;
this.checkedChunks = new ExpiringSet<>(Duration.ofMillis(chunkCheckDelay));
}

@Override
public void enable() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

@Override
public boolean shouldEnable() {
return config.getBoolean(configPath + ".enable", true);
}

@Override
public void disable() {
HandlerList.unregisterAll(this);
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onBlockPhysics(BlockPhysicsEvent event) {
Chunk chunk = event.getBlock().getChunk();
final ChunkUID chunkUID = ChunkUID.of(chunk);
if (checkedChunks.contains(chunkUID)) return;

int count = 0;
boolean removed_falling = false;

for (Entity entity : chunk.getEntities()) {
if (entity.getType() == XEntityType.FALLING_BLOCK.get()) {
count++;
if (count > maxFallingGravityBlockPerChunk) {
entity.remove();
removed_falling = true;
}
}
}

checkedChunks.add(chunkUID);

if (logIsEnabled && removed_falling) info("Removed falling block(s) at " +
LocationUtil.toString(event.getSourceBlock().getLocation()) + " because reached limit of " +
maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk");
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onChangeBlock(EntityChangeBlockEvent event) {
if (!event.getEntityType().equals(XEntityType.FALLING_BLOCK.get())) return;
Chunk chunk = event.getBlock().getChunk();
final ChunkUID chunkUID = ChunkUID.of(chunk);
if (checkedChunks.contains(chunkUID)) return;

int count = 0;
boolean removed_falling = false;

for (Entity entity : chunk.getEntities()) {
if (entity.getType() == XEntityType.FALLING_BLOCK.get()) {
count++;
if (count > maxFallingGravityBlockPerChunk) {
entity.remove();
removed_falling = true;
}
}
}

checkedChunks.add(chunkUID);

if (logIsEnabled && removed_falling) info("Removed falling block(s) at " +
LocationUtil.toString(event.getBlock().getLocation()) + " because reached limit of " +
maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package me.xginko.aef.modules.chunklimits;

import com.cryptomorin.xseries.XEntityType;
import me.xginko.aef.modules.AEFModule;
import me.xginko.aef.utils.LocationUtil;
import me.xginko.aef.utils.models.ChunkUID;
import me.xginko.aef.utils.models.ExpiringSet;
import org.bukkit.Chunk;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;

import java.time.Duration;
import java.util.Set;

public class FallingBlockLimit extends AEFModule implements Listener {

private final Set<ChunkUID> checkedChunks;
private final int maxFallingGravityBlockPerChunk;
private final boolean logIsEnabled;

public FallingBlockLimit() {
super("chunk-limits.falling-block-limit");
config.addComment(configPath + ".enable",
"Prevent players from placing massive sand chunks, then collapsing\n" +
"them to kill the server.");
this.logIsEnabled = config.getBoolean(configPath + ".log", false);
this.maxFallingGravityBlockPerChunk = config.getInt(configPath + ".max-falling-gravity-blocks-per-chunk", 60,
"Removes any falling block if there is more than x blocks actively\n" +
"falling in a chunk.");
this.checkedChunks = new ExpiringSet<>(Duration.ofMillis(
Math.max(1, config.getInt(configPath + ".chunk-check-delay-in-ticks", 20,
"Delay in ticks until the same chunk can be checked again.\n" +
"Prevents overchecking, because physics events can be called many\n" +
"times in a short time for the same chunk.")) * 50L
));
}

@Override
public void enable() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

@Override
public boolean shouldEnable() {
return config.getBoolean(configPath + ".enable", true);
}

@Override
public void disable() {
HandlerList.unregisterAll(this);
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onBlockPhysics(BlockPhysicsEvent event) {
Chunk chunk = event.getBlock().getChunk();
final ChunkUID chunkUID = ChunkUID.of(chunk);
if (checkedChunks.contains(chunkUID)) return;

int count = 0;
boolean removed_falling = false;

for (Entity entity : chunk.getEntities()) {
if (entity.getType() == XEntityType.FALLING_BLOCK.get()) {
count++;
if (count > maxFallingGravityBlockPerChunk) {
entity.remove();
removed_falling = true;
}
}
}

checkedChunks.add(chunkUID);

if (logIsEnabled && removed_falling) info("Removed falling block(s) at " +
LocationUtil.toString(event.getSourceBlock().getLocation()) + " because reached limit of " +
maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk");
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onChangeBlock(EntityChangeBlockEvent event) {
if (!event.getEntityType().equals(XEntityType.FALLING_BLOCK.get())) return;
Chunk chunk = event.getBlock().getChunk();
final ChunkUID chunkUID = ChunkUID.of(chunk);
if (checkedChunks.contains(chunkUID)) return;

int count = 0;
boolean removed_falling = false;

for (Entity entity : chunk.getEntities()) {
if (entity.getType() == XEntityType.FALLING_BLOCK.get()) {
count++;
if (count > maxFallingGravityBlockPerChunk) {
entity.remove();
removed_falling = true;
}
}
}

checkedChunks.add(chunkUID);

if (logIsEnabled && removed_falling) info("Removed falling block(s) at " +
LocationUtil.toString(event.getBlock().getLocation()) + " because reached limit of " +
maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk");
}
}

0 comments on commit e898ffc

Please sign in to comment.