这是我用DeepSeek写出来的插件
功能一:自定义分钟清理一次全局掉落物,清理前有倒计时提示。
功能二:自定义限制单个区块内实体数量,超出的清除
指令:
手动掉落物清理:/clearloot
手动实体清理:/entitylimiter runnow
重载配置:/entitylimiter reload
Code (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- 立即清理实体"
)
;
}
}
config.yml:
# 实体限制配置
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需要管理员权限"