- 版权类型
- 原创
- 插件中文名称
- 自动清理和区块实体限制
- 插件英文名称
- EntityLimiter
- 原帖地址
- #
- 支持的核心(服务端)
- Paper
- 语言支持
- 中文(简体)
- 前置组件
- 无
- 适配版本(Java)
- 1.21
这是我用DeepSeek写出来的插件
功能一:自定义分钟清理一次全局掉落物,清理前有倒计时提示。
功能二:自定义限制单个区块内实体数量,超出的清除
指令:
手动掉落物清理:/clearloot
手动实体清理:/entitylimiter runnow
重载配置:/entitylimiter reload
代码:
Java:
package MyPlugin.entityLimiter;
import org.bukkit.*;
import org.bukkit.command.*;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.*;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
public class EntityLimiter extends JavaPlugin {
private Map<EntityType, Integer> entityLimits = new HashMap<>();
private int entityTaskId = -1;
private int itemCleanTaskId = -1;
// ========== 插件生命周期 ==========
@Override
public void onEnable() {
saveDefaultConfig();
loadConfig();
startSchedulers();
registerCommands();
}
@Override
public void onDisable() {
cancelTasks();
}
// ========== 配置加载 ==========
private void loadConfig() {
reloadConfig();
FileConfiguration config = getConfig();
// 加载实体限制配置
entityLimits.clear();
config.getConfigurationSection("entities").getKeys(false).forEach(key -> {
try {
EntityType type = EntityType.valueOf(key.toUpperCase());
entityLimits.put(type, config.getInt("entities." + key));
} catch (IllegalArgumentException e) {
getLogger().warning("无效的实体类型: " + key);
}
});
}
// ========== 任务调度 ==========
private void startSchedulers() {
startEntityScheduler();
startItemCleanScheduler();
}
private void cancelTasks() {
Arrays.asList(entityTaskId, itemCleanTaskId).forEach(id -> {
if (id != -1) Bukkit.getScheduler().cancelTask(id);
});
}
// ========== 实体限制系统 ==========
private void startEntityScheduler() {
entityTaskId = new BukkitRunnable() {
int countdown = 30 * 60;
@Override
public void run() {
handleCountdown(countdown,
5*60, 3*60, 1*60,
"§c实体限制检查倒计时:",
this::performEntityCleanup
);
countdown = (countdown > 0) ? countdown - 1 : 30 * 60;
}
private void performEntityCleanup() {
}
}.runTaskTimer(this, 0L, 20L).getTaskId();
}
private void performEntityCleanup() {
int[] totalRemoved = {0};
Bukkit.getWorlds().forEach(world -> {
Arrays.stream(world.getLoadedChunks()).forEach(chunk -> {
totalRemoved[0] += processChunk(chunk);
});
});
broadcast("§a实体清理完成,共移除 " + totalRemoved[0] + " 个实体");
}
private int processChunk(Chunk chunk) {
Map<EntityType, Integer> counter = new HashMap<>();
List<Entity> toRemove = new ArrayList<>();
Arrays.stream(chunk.getEntities()).forEach(entity -> {
EntityType type = entity.getType();
if (!entityLimits.containsKey(type)) return;
int count = counter.getOrDefault(type, 0) + 1;
counter.put(type, count);
if (count > entityLimits.get(type)) {
toRemove.add(entity);
}
});
toRemove.forEach(Entity::remove);
return toRemove.size();
}
// ========== 掉落物清理系统 ==========
private void startItemCleanScheduler() {
itemCleanTaskId = new BukkitRunnable() {
int countdown = getConfig().getInt("item-clean.interval-minutes") * 60;
@Override
public void run() {
handleCountdown(countdown,
getConfig().getInt("item-clean.warnings.5m") * 60,
getConfig().getInt("item-clean.warnings.3m") * 60,
getConfig().getInt("item-clean.warnings.1m") * 60,
"§6掉落物清理倒计时:",
() -> performItemCleanup(false)
);
countdown = (countdown > 0) ? countdown - 1 :
getConfig().getInt("item-clean.interval-minutes") * 60;
}
}.runTaskTimer(this, 0L, 20L).getTaskId();
}
private void performItemCleanup(boolean isManual) {
Bukkit.getScheduler().runTask(this, () -> {
int total = 0;
// 遍历所有已加载区块
for (World world : Bukkit.getWorlds()) {
for (Chunk chunk : world.getLoadedChunks()) {
// 双重检查区块加载状态
if (!chunk.isLoaded()) continue;
// 遍历区块实体
for (Entity entity : chunk.getEntities()) {
if (entity instanceof Item) {
total++;
}
}
}
}
// 执行清理命令
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "kill @e[type=item]");
// 广播结果
String message = isManual ?
"§a手动清理完成!共移除 " + total + " 个掉落物" :
"§a定时清理完成!共移除 " + total + " 个掉落物";
broadcast(message);
});
}
// ========== 通用工具方法 ==========
private void handleCountdown(int current, int w5m, int w3m, int w1m,
String prefix, Runnable callback) {
if (current == w5m) broadcast(prefix + "5分钟");
else if (current == w3m) broadcast(prefix + "3分钟");
else if (current == w1m) broadcast(prefix + "1分钟");
else if (current <= 10) {
if (current > 0) {
broadcast(prefix + current + "秒");
} else {
callback.run();
}
}
}
private void broadcast(String message) {
Bukkit.getOnlinePlayers().forEach(p -> p.sendMessage(message));
getLogger().info(ChatColor.stripColor(message));
}
// ========== 指令系统 ==========
private void registerCommands() {
register("clearloot", this::handleClearLoot);
register("entitylimiter", this::handleMainCommand);
}
private void register(String cmd, CommandExecutor executor) {
PluginCommand command = getCommand(cmd);
if (command != null) {
command.setExecutor(executor);
command.setTabCompleter(this::onTabComplete);
}
}
private boolean handleClearLoot(CommandSender sender, Command cmd,
String label, String[] args) {
if (!checkPermission(sender, "entitylimiter.clearloot")) return true;
performItemCleanup(true);
return true;
}
private boolean handleMainCommand(CommandSender sender, Command cmd,
String label, String[] args) {
if (!checkPermission(sender, "entitylimiter.admin")) return true;
if (args.length == 0) {
sendHelp(sender);
return true;
}
switch (args[0].toLowerCase()) {
case "reload":
loadConfig();
cancelTasks();
startSchedulers();
sender.sendMessage("§a配置已重载!");
return true;
case "runnow":
performEntityCleanup();
return true;
default:
sendHelp(sender);
return true;
}
}
public List<String> onTabComplete(CommandSender sender, Command cmd,
String alias, String[] args) {
List<String> list = new ArrayList<>();
if (cmd.getName().equalsIgnoreCase("entitylimiter") && args.length == 1) {
list.addAll(Arrays.asList("reload", "runnow"));
}
return list;
}
private boolean checkPermission(CommandSender sender, String perm) {
if (!sender.hasPermission(perm)) {
sender.sendMessage("§c权限不足!");
return false;
}
return true;
}
private void sendHelp(CommandSender sender) {
sender.sendMessage("§6===== EntityLimiter 帮助 =====");
sender.sendMessage("§a/clearloot §7- 立即清理掉落物");
sender.sendMessage("§a/entitylimiter reload §7- 重载配置");
sender.sendMessage("§a/entitylimiter runnow §7- 立即清理实体");
}
}
# 实体限制配置
entities:
ZOMBIE: 15
SKELETON: 10
CREEPER: 5
# 掉落物清理配置
item-clean:
interval-minutes: 30
warnings:
5m: 5
3m: 3
1m: 1
countdown-seconds: 10
check-loaded-chunks-only: true #仅检查已加载的块
plugin.yml:
name: EntityLimiter
main: MyPlugin.entityLimiter.EntityLimiter
version: 1.2.0
api-version: 1.21
authors: [YourName]
commands:
clearloot:
description: 清理全服掉落物
usage: /clearloot
permission: entitylimiter.clearloot
permission-message: "§c需要权限 entitylimiter.clearloot"
entitylimiter:
description: 插件管理命令
usage: /entitylimiter [reload|runnow]
permission: entitylimiter.admin
aliases: [el]
permission-message: "§c需要管理员权限"