修复边框粒子卡死主线程:动态密度控制+粒子总量上限

This commit is contained in:
2026-07-13 12:00:27 +08:00
parent 7489c60286
commit c7cdb60b47
2 changed files with 62 additions and 23 deletions
+61 -22
View File
@@ -3035,30 +3035,50 @@ public class AreaProtection implements Listener {
// ==================== 边框显示 ====================
private void showBorder(Player p, AreaConfig ac, boolean temp) {
cancelBorder(p);
int minX = Math.min(ac.x1, ac.x2);
int maxX = Math.max(ac.x1, ac.x2);
int minZ = Math.min(ac.z1, ac.z2);
int maxZ = Math.max(ac.z1, ac.z2);
int edgeLenX = maxX - minX + 1;
int edgeLenZ = maxZ - minZ + 1;
// 超大领地跳过3D边框粒子
if (edgeLenX > 200 || edgeLenZ > 200) return;
int perimeter = 2 * (edgeLenX + edgeLenZ);
// 动态步长:保证每条边最多~25个粒子点
final int step = Math.max(4, Math.min(10, perimeter / 100));
// 动态层数:大领地减少层数(从6层降到2层)
final int dyStep = perimeter > 200 ? 10 : 5;
final int maxParticlesPerTick = 80;
int taskId = Bukkit.getScheduler()
.runTaskTimer(plugin, new Runnable() {
@Override
public void run() {
if (!p.isOnline()) return;
Location loc = p.getLocation();
int px = loc.getBlockX();
int py = loc.getBlockY();
int pz = loc.getBlockZ();
int minX = Math.min(ac.x1, ac.x2);
int maxX = Math.max(ac.x1, ac.x2);
int minZ = Math.min(ac.z1, ac.z2);
int maxZ = Math.max(ac.z1, ac.z2);
for (int dy = 5; dy <= 30; dy += 5) {
for (int x = minX; x <= maxX; x += 4) {
for (int z = minZ; z <= maxZ; z += 4) {
if (x == minX || x == maxX
|| z == minZ || z == maxZ) {
p.spawnParticle(Particle.END_ROD,
x + 0.5, py + dy, z + 0.5,
1, 0, 0, 0, 0);
}
int count = 0;
for (int dy = 5; dy <= 30 && count < maxParticlesPerTick; dy += dyStep) {
for (int x = minX; x <= maxX && count < maxParticlesPerTick; x += step) {
if (x == minX || x == maxX) {
p.spawnParticle(Particle.END_ROD,
x + 0.5, py + dy, minZ + 0.5,
1, 0, 0, 0, 0);
p.spawnParticle(Particle.END_ROD,
x + 0.5, py + dy, maxZ + 0.5,
1, 0, 0, 0, 0);
count += 2;
}
}
for (int z = minZ + step; z < maxZ && count < maxParticlesPerTick; z += step) {
p.spawnParticle(Particle.END_ROD,
minX + 0.5, py + dy, z + 0.5,
1, 0, 0, 0, 0);
p.spawnParticle(Particle.END_ROD,
maxX + 0.5, py + dy, z + 0.5,
1, 0, 0, 0, 0);
count += 2;
}
}
}
}, 0L, 20L).getTaskId();
@@ -4588,12 +4608,28 @@ public class AreaProtection implements Listener {
int minZ = Math.min(ac.z1, ac.z2);
int maxZ = Math.max(ac.z1, ac.z2);
// === 性能优化:动态密度控制 ===
int edgeLenX = maxX - minX + 1;
int edgeLenZ = maxZ - minZ + 1;
int perimeter = 2 * (edgeLenX + edgeLenZ);
// 超大领地直接跳过粒子(>200格边长)
if (edgeLenX > 200 || edgeLenZ > 200) {
return;
}
// 动态步长:保证每条边最多~30个粒子点
int step = Math.max(2, Math.min(6, perimeter / 120));
// 每轮粒子总量上限60(不含四角)
int maxParticlesPerRound = 60;
Particle.DustTransition dust = new Particle.DustTransition(org.bukkit.Color.fromRGB(0, 255, 255), org.bukkit.Color.fromRGB(255, 255, 0), 1.2f);
// 每20tick刷新一次粒子(共durationTicks/20次)
int rounds = Math.max(1, durationTicks / 20);
for (int i = 0; i < rounds; i++) {
final int round = i;
final int fStep = step;
new org.bukkit.scheduler.BukkitRunnable() {
@Override
public void run() {
@@ -4603,20 +4639,23 @@ public class AreaProtection implements Listener {
int playerY = p.getLocation().getBlockY();
int y = Math.max(ac.yMin, Math.min(playerY, ac.yMax));
int count = 0;
// 四条边
for (int x = minX; x <= maxX; x += 2) {
for (int x = minX; x <= maxX && count < maxParticlesPerRound; x += fStep) {
p.spawnParticle(Particle.DUST_COLOR_TRANSITION, new Location(world, x + 0.5, y, minZ + 0.5), 1, dust);
p.spawnParticle(Particle.DUST_COLOR_TRANSITION, new Location(world, x + 0.5, y, maxZ + 0.5), 1, dust);
count += 2;
}
for (int z = minZ; z <= maxZ; z += 2) {
for (int z = minZ; z <= maxZ && count < maxParticlesPerRound; z += fStep) {
p.spawnParticle(Particle.DUST_COLOR_TRANSITION, new Location(world, minX + 0.5, y, z + 0.5), 1, dust);
p.spawnParticle(Particle.DUST_COLOR_TRANSITION, new Location(world, maxX + 0.5, y, z + 0.5), 1, dust);
count += 2;
}
// 四个角高亮
p.spawnParticle(Particle.END_ROD, new Location(world, minX + 0.5, y, minZ + 0.5), 3);
p.spawnParticle(Particle.END_ROD, new Location(world, maxX + 0.5, y, minZ + 0.5), 3);
p.spawnParticle(Particle.END_ROD, new Location(world, minX + 0.5, y, maxZ + 0.5), 3);
p.spawnParticle(Particle.END_ROD, new Location(world, maxX + 0.5, y, maxZ + 0.5), 3);
// 四个角高亮(各1个粒子,减少ProtocolLib包量)
p.spawnParticle(Particle.END_ROD, new Location(world, minX + 0.5, y, minZ + 0.5), 1);
p.spawnParticle(Particle.END_ROD, new Location(world, maxX + 0.5, y, minZ + 0.5), 1);
p.spawnParticle(Particle.END_ROD, new Location(world, minX + 0.5, y, maxZ + 0.5), 1);
p.spawnParticle(Particle.END_ROD, new Location(world, maxX + 0.5, y, maxZ + 0.5), 1);
}
}.runTaskLater(plugin, round * 20L);
}
+1 -1
View File
@@ -5506,7 +5506,7 @@ public class WebManager {
} else {
player.sendMessage("§c[Web] Token同步失败,请检查Web后端: " + webBaseUrl);
}
player.sendMessage("§7[Web] 使用 §e/sdf1_login weblogin §7可重新获取");
player.sendMessage("§7[Web] 使用 §e/控制台 §7可重新获取");
}
});