实现了功能 需要进一步测试
All checks were successful
Java CI-CD with Maven / build (push) Successful in 11m36s

This commit is contained in:
zhangyuheng 2024-03-26 16:14:21 +08:00
parent d63feb0671
commit 9ddaa54cd4
9 changed files with 70 additions and 34 deletions

View File

@ -2,17 +2,25 @@
## 自定义区块卸载规则
## 说明
在 Minecraft 单机版中一个实体进入地狱门后会使得另一侧的区块加载300游戏刻15秒 ,利用此机制可以实现一些双维度刷怪塔(如凋零农场)。
但是在 Paper 系的服务端中,实体在通过地狱门后并不会触发另一测的区块加载。因此导致了一些双维度刷怪塔无法正常工作,因此诞生了区块加载器。
但是在一些更特殊的环境下即便使用了区块加载器加载了区块,也无法实现双维度刷怪塔的效果。
因为在某些服务端中使用区块加载器无法使区块加载等级达到“实体计算”的等级,此情况下的实体在通过门后会被立刻删除。
本插件通过设置区块强制加载标签,保证区块的加载等级达到实体计算等级,以此来还原在服务端的原版双纬度刷怪塔特性。
## 实现逻辑
## 功能介绍
1. 插件会记录玩家经过的每一个区块,并为这些区块添加“强制加载”标签;
2. 被添加了强制加载标签的区块会保持高等级的常加载,此加载等级与玩家在区块中的实体计算等级相同;
3. 当一个玩家拥有的强制加载区块数量超过了配置文件中的最大值时,会将最早的区块取消强制加载标签;
4. 被取消标签的区块会按照服务端常规的区块卸载规则进行卸载;
5. 玩家退出游戏后会自动为其取消所有区块的强制加载标签,避免过多的区块被强制加载;
## 支持版本
- 1.20.1+ (Paper、Folia)
- Folia 1.20.1+
## 安装方法
@ -23,22 +31,40 @@
## 使用方法
## 管理员指南
提示:请合理设置每个玩家能拥有的的最多强加载区块数量,避免因为过多的强加载区块导致服务器内存占用过高。
## 指令
### 玩家指令
### 管理员指令
## 配置文件参考
```yaml
# 启动时清除已有的强加载区块延迟 秒
# 建议设置为10秒 太低可能在世界加载完成前触发操作引起报错
# -1 为不清除 如果你的服务器有其他插件会在启动时加载区块建议设置为-1
ClearLoadedChunksOnStartupDelay: 10
# 每个玩家拥有的最多强加载区块数
MaxDelayChunkPerPlayer: 10
# tps最低阈值 低于此值将会开始自动取消强加载区块
MinimumTpsThreshold: 15.0
# 每次检查tps的间隔 单位为tick 20tick=1s
TpsCheckIntervalTicks: 600
Debug: false
```
## TODO

View File

@ -6,7 +6,7 @@
<groupId>cn.lunadeer</groupId>
<artifactId>BetterChunkUnload</artifactId>
<version>1.9</version>
<version>1.10</version>
<packaging>jar</packaging>
<name>BetterChunkUnload</name>

View File

@ -1,17 +1,14 @@
package cn.lunadeer.betterchunkunload;
import cn.lunadeer.betterchunkunload.utils.ChunkClear;
import cn.lunadeer.betterchunkunload.utils.ConfigManager;
import cn.lunadeer.betterchunkunload.utils.XLogger;
import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
import org.bukkit.Chunk;
import org.bukkit.entity.Player;
import org.bukkit.World;
import org.bukkit.plugin.java.JavaPlugin;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class BetterChunkUnload extends JavaPlugin {
@ -26,6 +23,25 @@ public final class BetterChunkUnload extends JavaPlugin {
// register events
getServer().getPluginManager().registerEvents(new Events(), this);
// clear all force loaded chunks
if (config.getClearLoadedChunksOnStartupDelay() >= 0) {
XLogger.info("启动时清理强加载区块已启用");
scheduler.runDelayed(instance, (instance) -> {
int count = 0;
for (World world : BetterChunkUnload.instance.getServer().getWorlds()) {
XLogger.debug("清除所有强加载区块: " + world.getName());
Collection<Chunk> chunks = world.getForceLoadedChunks();
for (Chunk chunk : chunks) {
count++;
world.setChunkForceLoaded(chunk.getX(), chunk.getZ(), false);
}
}
XLogger.info("共清理强加载区块(个): " + count);
}, config.getClearLoadedChunksOnStartupDelay() * 20);
} else {
XLogger.info("启动时清理强加载区块已禁用");
}
// start tps checker
scheduler.runAtFixedRate(instance, (instance) -> {
tpsChecker();

View File

@ -4,7 +4,6 @@ import cn.lunadeer.betterchunkunload.utils.ChunkClear;
import cn.lunadeer.betterchunkunload.utils.XLogger;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.ArrayList;

View File

@ -2,13 +2,10 @@ package cn.lunadeer.betterchunkunload;
import cn.lunadeer.betterchunkunload.utils.XLogger;
import io.papermc.paper.event.packet.PlayerChunkLoadEvent;
import io.papermc.paper.event.packet.PlayerChunkUnloadEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
public class Events implements Listener {

View File

@ -1,19 +0,0 @@
package cn.lunadeer.betterchunkunload;
import cn.lunadeer.betterchunkunload.utils.XLogger;
public class TpsChecker implements Runnable{
@Override
public void run() {
if (!BetterChunkUnload.enable) {
return;
}
if (BetterChunkUnload.instance.getServer().getTPS()[0] > BetterChunkUnload.config.getMinimumTpsThreshold()){
return;
}
XLogger.warn("TPS: " + BetterChunkUnload.instance.getServer().getTPS()[0] + " 低于 " + BetterChunkUnload.config.getMinimumTpsThreshold() + " 开始清理区块");
for (ChunkList chunkList : BetterChunkUnload.getChunkList()) {
chunkList.popFront();
}
}
}

View File

@ -19,6 +19,7 @@ public class ConfigManager {
_MaxDelayChunkPerPlayer = _file.getInt("MaxDelayChunkPerPlayer", 10);
_MinimumTpsThreshold = (float) _file.getDouble("MinimumTpsThreshold", 15.0);
_TpsCheckIntervalTicks = _file.getInt("TpsCheckIntervalTicks", 600);
_ClearLoadedChunksOnStartupDelay = _file.getInt("ClearLoadedChunksOnStartupDelay", 10);
}
public Boolean isDebug() {
@ -61,6 +62,16 @@ public class ConfigManager {
_plugin.saveConfig();
}
public Integer getClearLoadedChunksOnStartupDelay() {
return _ClearLoadedChunksOnStartupDelay;
}
public void setClearLoadedChunksOnStartupDelay(Integer ClearLoadedChunksOnStartupDelay) {
_ClearLoadedChunksOnStartupDelay = ClearLoadedChunksOnStartupDelay;
_file.set("ClearLoadedChunksOnStartupDelay", ClearLoadedChunksOnStartupDelay);
_plugin.saveConfig();
}
private final BetterChunkUnload _plugin;
private FileConfiguration _file;
@ -68,5 +79,6 @@ public class ConfigManager {
private Integer _MaxDelayChunkPerPlayer;
private Float _MinimumTpsThreshold;
private Integer _TpsCheckIntervalTicks;
private Integer _TpsCheckIntervalTicks;
private Integer _ClearLoadedChunksOnStartupDelay;
}

View File

@ -7,7 +7,7 @@ import net.kyori.adventure.text.format.TextColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import static cn.lunadeer.betterchunkunload.utils.XLogger.*;
import static cn.lunadeer.betterchunkunload.utils.XLogger.debug;
public class Notification {
private static final Style i_style = Style.style(TextColor.color(139, 255, 123));

View File

@ -1,3 +1,8 @@
# 启动时清除已有的强加载区块延迟 秒
# 建议设置为10秒 太低可能在世界加载完成前触发操作引起报错
# -1 为不清除 如果你的服务器有其他插件会在启动时加载区块建议设置为-1
ClearLoadedChunksOnStartupDelay: 10
# 每个玩家拥有的最大延迟卸载区块数
MaxDelayChunkPerPlayer: 10