修复领地增益药效等级无上限,新增用户组药效等级上限配置
问题:领地增益效果的等级完全没校验,管理员配了 255 级就会原样 生效(截图里出现的 Lv255 即源于此)。原版 /effect 的 amplifier 硬 上限是 255(对应药效强度 1~256),插件此前允许写入并施加远超原版 范围的等级。 修复(2026-10-04 任务4): - UserGroupManager 新增 maxEffectLevel 字段,默认 256 · 常量 DEFAULT_MAX_EFFECT_LEVEL = 256 集中定义原版上限 · user_group_config 建表补列 + ALTER 迁移(老库自动升级) · loadGroupConfigs 读取、saveGroupConfigToDB 加为第 14 列 · 新增 getPlayerMaxEffectLevel:普通玩家走原版 256,用户组按组配置 - AreaProtection 新增 getMaxGiveEffectLevel / clampGiveEffectLevel, 在全部 4 个应用点封顶:首次给予(applyRegionEffects)、热更新、 handleEnter、applyEffects;另在 PHP 字段推送(applyFieldToAreaConfig) 与 CLI 添加/编辑两处入口按同一上限做输入校验与提示 - WebManager 用户组同步双向补 max_effect_level(推 PHP + 回读) 规则:普通玩家(未加入任何用户组)严格按原版 256 封顶,严禁超限; 用户组玩家按组配置封顶,组里配多少就是多少,但任何情况下都不得 突破原版 256。原先散落各处的硬编码 255 已统一为该口径。
This commit is contained in:
@@ -3825,7 +3825,8 @@ public class AreaProtection implements Listener {
|
||||
PotionEffectType type =
|
||||
resolveEffectType(eff[0]);
|
||||
if (type == null) continue;
|
||||
int lv = Integer.parseInt(eff[1]) - 1;
|
||||
// ★ 药效等级封顶(2026-10-04 任务4):普通玩家按原版256,用户组按组配置
|
||||
int lv = clampGiveEffectLevel(Integer.parseInt(eff[1]), ac.owner) - 1;
|
||||
int dur = Integer.parseInt(eff[2]) * 20;
|
||||
|
||||
PotionEffect existing =
|
||||
@@ -3891,7 +3892,8 @@ public class AreaProtection implements Listener {
|
||||
PotionEffectType type = resolveEffectType(eff[0]);
|
||||
if (type == null) continue;
|
||||
try {
|
||||
int lv = Integer.parseInt(eff[1]) - 1; // MC amplifier从0开始
|
||||
// ★ 药效等级封顶(2026-10-04 任务4),与首次给予同一口径
|
||||
int lv = clampGiveEffectLevel(Integer.parseInt(eff[1]), ac.owner) - 1; // MC amplifier从0开始
|
||||
int dur = Integer.parseInt(eff[2]) * 20; // 秒→tick
|
||||
expectedEffects.put(type, new int[]{lv, dur});
|
||||
} catch (NumberFormatException ignored) {}
|
||||
@@ -4162,6 +4164,8 @@ public class AreaProtection implements Listener {
|
||||
catch (NumberFormatException ignored) {}
|
||||
try { duration = Integer.parseInt(parts[2]); }
|
||||
catch (NumberFormatException ignored) {}
|
||||
// ★ 药效等级封顶(2026-10-04 任务4)
|
||||
level = clampGiveEffectLevel(level, ac.owner);
|
||||
PotionEffectType type = resolveEffectType(effName);
|
||||
if (type != null) {
|
||||
p.addPotionEffect(new PotionEffect(
|
||||
@@ -4912,6 +4916,39 @@ public class AreaProtection implements Listener {
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* ★ 领地增益【药效等级上限】(2026-10-04 任务4)。
|
||||
* 普通玩家(无用户组)严格按原版最大药效强度 256 封顶;
|
||||
* 用户组玩家按组配置 max_effect_level,组里配多少就是多少。
|
||||
*
|
||||
* @param ownerName 领地所有者(上限跟随领地所有者所属用户组,与数量上限一致口径)
|
||||
* @return 药效强度上限,恒在 1~256 之间
|
||||
*/
|
||||
public int getMaxGiveEffectLevel(String ownerName) {
|
||||
try {
|
||||
UserGroupManager ugm = plugin.getUserGroup();
|
||||
if (ugm != null) {
|
||||
return ugm.getPlayerMaxEffectLevel(ownerName,
|
||||
UserGroupManager.DEFAULT_MAX_EFFECT_LEVEL);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return UserGroupManager.DEFAULT_MAX_EFFECT_LEVEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把领地配置里的药效等级夹到该领地的合法上限内。
|
||||
* 所有写入/应用入口都必须过这一刀。
|
||||
*
|
||||
* @param rawLevel 配置里写的原始药效强度
|
||||
* @param ownerName 领地所有者
|
||||
* @return 夹紧后的药效强度(1~256,且 <= 该领地用户组上限)
|
||||
*/
|
||||
public int clampGiveEffectLevel(int rawLevel, String ownerName) {
|
||||
int cap = getMaxGiveEffectLevel(ownerName);
|
||||
if (rawLevel < 1) return 1;
|
||||
return rawLevel > cap ? cap : rawLevel;
|
||||
}
|
||||
|
||||
public List<String> getUserGroupNames() {
|
||||
List<String> names = new ArrayList<>();
|
||||
UserGroupManager ugm = plugin.getUserGroup();
|
||||
@@ -5111,6 +5148,8 @@ public class AreaProtection implements Listener {
|
||||
catch (NumberFormatException ignored) {}
|
||||
try { duration = Integer.parseInt(parts[2]); }
|
||||
catch (NumberFormatException ignored) {}
|
||||
// ★ 药效等级封顶(2026-10-04 任务4)
|
||||
level = clampGiveEffectLevel(level, ac.owner);
|
||||
|
||||
PotionEffectType type = resolveEffectType(effName);
|
||||
plugin.getLogger().info("[防护调试] 给予: "
|
||||
@@ -10696,11 +10735,13 @@ public class AreaProtection implements Listener {
|
||||
ac.giveEffects = new java.util.ArrayList<>(
|
||||
ac.giveEffects.subList(0, maxEff));
|
||||
}
|
||||
// ★ 药效等级按该领地用户组上限封顶(2026-10-04 任务4)
|
||||
int maxLv = getMaxGiveEffectLevel(ac.owner);
|
||||
for (String[] ef : ac.giveEffects) {
|
||||
if (ef.length >= 2) {
|
||||
try {
|
||||
int lv = Integer.parseInt(ef[1]);
|
||||
if (lv > 255) ef[1] = "255";
|
||||
if (lv > maxLv) ef[1] = String.valueOf(maxLv);
|
||||
else if (lv < 1) ef[1] = "1";
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
@@ -11169,9 +11210,11 @@ public class AreaProtection implements Listener {
|
||||
p.sendMessage("§c§l[添加增益效果] §f等级和秒数必须是数字");
|
||||
return true;
|
||||
}
|
||||
// ★ 验证等级和秒数范围
|
||||
if (effLv < 1 || effLv > 255) {
|
||||
p.sendMessage("§c§l[添加增益效果] §f等级范围: 1~255");
|
||||
// ★ 验证等级和秒数范围(等级上限按用户组配置,2026-10-04 任务4)
|
||||
int maxLvAdd = getMaxGiveEffectLevel(land.owner);
|
||||
if (effLv < 1 || effLv > maxLvAdd) {
|
||||
p.sendMessage("§c§l[添加增益效果] §f等级范围: 1~" + maxLvAdd);
|
||||
p.sendMessage("§7上限说明: 普通玩家为原版上限 256,你当前可用的上限是 " + maxLvAdd);
|
||||
return true;
|
||||
}
|
||||
if (effDur < 1 || effDur > 3600) {
|
||||
@@ -11226,7 +11269,12 @@ public class AreaProtection implements Listener {
|
||||
p.sendMessage("§c请输入有效数字");
|
||||
return true;
|
||||
}
|
||||
if (newLevel < 1 || newLevel > 255) { p.sendMessage("§c等级范围1~255"); return true; }
|
||||
int maxLvEdit = getMaxGiveEffectLevel(land.owner);
|
||||
if (newLevel < 1 || newLevel > maxLvEdit) {
|
||||
p.sendMessage("§c等级范围1~" + maxLvEdit);
|
||||
p.sendMessage("§7上限说明: 普通玩家为原版上限 256,你当前可用的上限是 " + maxLvEdit);
|
||||
return true;
|
||||
}
|
||||
if (eff.length < 2) { String[] tmp = new String[3]; System.arraycopy(eff, 0, tmp, 0, eff.length); eff = tmp; land.giveEffects.set(idx - 1, eff); }
|
||||
eff[1] = String.valueOf(newLevel);
|
||||
p.sendMessage("§a§l[编辑增益] §f已将 §e" + eff[0] + " §f等级修改为 " + newLevel);
|
||||
|
||||
@@ -52,7 +52,8 @@ public class UserGroupManager {
|
||||
+ "max_lands INTEGER DEFAULT -1," // -1 = 使用全局值
|
||||
+ "default_perms TEXT DEFAULT '{}'," // JSON: 默认deny_*标志
|
||||
+ "is_permanent INTEGER DEFAULT 1," // 保留兼容
|
||||
+ "duration_minutes INTEGER DEFAULT 0" // 保留兼容
|
||||
+ "duration_minutes INTEGER DEFAULT 0," // 保留兼容
|
||||
+ "max_effect_level INTEGER DEFAULT 256" // 药效等级上限,<=0=按原版256
|
||||
+ ")");
|
||||
|
||||
// 玩家↔用户组关联
|
||||
@@ -78,6 +79,8 @@ public class UserGroupManager {
|
||||
try { st.executeUpdate("ALTER TABLE user_group_config ADD COLUMN renew_price INTEGER DEFAULT 0"); } catch (Exception ignored) {}
|
||||
// ★ 领地增益效果上限(2026-10-04 任务3):默认5个,<=0=不限
|
||||
try { st.executeUpdate("ALTER TABLE user_group_config ADD COLUMN max_effects INTEGER DEFAULT 5"); } catch (Exception ignored) {}
|
||||
// ★ 药效等级上限(2026-10-04 任务4):默认256=原版最大药效强度,<=0=按原版
|
||||
try { st.executeUpdate("ALTER TABLE user_group_config ADD COLUMN max_effect_level INTEGER DEFAULT 256"); } catch (Exception ignored) {}
|
||||
// duration_minutes已有(旧列),复用
|
||||
|
||||
st.close();
|
||||
@@ -110,6 +113,8 @@ public class UserGroupManager {
|
||||
cfg.durationMinutes = rs.getLong("duration_minutes");
|
||||
cfg.maxEffects = rs.getInt("max_effects");
|
||||
if (rs.wasNull()) cfg.maxEffects = 5;
|
||||
cfg.maxEffectLevel = rs.getInt("max_effect_level");
|
||||
if (rs.wasNull()) cfg.maxEffectLevel = UserGroupManager.DEFAULT_MAX_EFFECT_LEVEL;
|
||||
if (cfg.name != null && !cfg.name.isEmpty()) {
|
||||
groupConfigs.put(cfg.name, cfg);
|
||||
}
|
||||
@@ -131,8 +136,8 @@ public class UserGroupManager {
|
||||
+ "(group_name, display_name, display_color,"
|
||||
+ " priority, land_price_per_sqm, max_lands, default_perms,"
|
||||
+ " home_limit, join_price, auto_renew, renew_price, duration_minutes,"
|
||||
+ " max_effects)"
|
||||
+ " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)");
|
||||
+ " max_effects, max_effect_level)"
|
||||
+ " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
|
||||
ps.setString(1, cfg.name);
|
||||
ps.setString(2, cfg.displayName);
|
||||
ps.setString(3, cfg.displayColor);
|
||||
@@ -146,6 +151,7 @@ public class UserGroupManager {
|
||||
ps.setInt(11, cfg.renewPrice);
|
||||
ps.setLong(12, cfg.durationMinutes);
|
||||
ps.setInt(13, cfg.maxEffects);
|
||||
ps.setInt(14, cfg.maxEffectLevel);
|
||||
ps.executeUpdate();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
@@ -980,6 +986,30 @@ public class UserGroupManager {
|
||||
return cfg.maxEffects;
|
||||
}
|
||||
|
||||
/**
|
||||
* ★ 药效等级上限(2026-10-04 任务4)。
|
||||
* 普通玩家(无用户组)严格按原版最大药效强度 256 封顶;
|
||||
* 用户组玩家按组配置 max_effect_level,配置多少就是多少。
|
||||
* 组配置 <=0 视为「不额外限制」,仍受原版 256 硬上限约束。
|
||||
*
|
||||
* @param player 玩家名
|
||||
* @param globalDefault 无组时的全局默认(原版上限 256)
|
||||
* @return 药效强度上限,恒 >=1 且 <=256
|
||||
*/
|
||||
public int getPlayerMaxEffectLevel(String player, int globalDefault) {
|
||||
int cap = DEFAULT_MAX_EFFECT_LEVEL;
|
||||
if (globalDefault > 0 && globalDefault < cap) {
|
||||
cap = globalDefault;
|
||||
}
|
||||
if (player != null && !player.isEmpty()) {
|
||||
UserGroupConfig cfg = getHighestGroup(player);
|
||||
if (cfg != null && cfg.maxEffectLevel > 0 && cfg.maxEffectLevel < cap) {
|
||||
cap = cfg.maxEffectLevel;
|
||||
}
|
||||
}
|
||||
return cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取玩家的默认领地权限 JSON
|
||||
* 返回:组默认权限 或 空JSON "{}"
|
||||
@@ -1151,6 +1181,14 @@ public class UserGroupManager {
|
||||
|
||||
// ==================== 配置类 ====================
|
||||
|
||||
/**
|
||||
* ★ 原版最大药效强度(2026-10-04 任务4)。
|
||||
* Minecraft 药效强度范围 1~256,amplifier = 强度 - 1,即 0~255,
|
||||
* /effect 命令的 amplifier 参数硬上限就是 255。
|
||||
* 普通玩家(无用户组)一律以此为上限,严禁超限。
|
||||
*/
|
||||
public static final int DEFAULT_MAX_EFFECT_LEVEL = 256;
|
||||
|
||||
public static class UserGroupConfig {
|
||||
public String name;
|
||||
public String displayName = "";
|
||||
@@ -1160,6 +1198,7 @@ public class UserGroupManager {
|
||||
public int landPricePerSqm = -1; // -1 = 使用全局
|
||||
public int maxLands = -1; // -1 = 使用全局
|
||||
public int maxEffects = 5; // 领地增益效果上限,<=0=不限
|
||||
public int maxEffectLevel = DEFAULT_MAX_EFFECT_LEVEL; // 药效等级上限,<=0=按原版256
|
||||
public String defaultPerms = "{}"; // JSON
|
||||
// Home相关
|
||||
public int homeLimit = 0; // 0=跟随全局, >0=独立限制, -1=无限
|
||||
|
||||
@@ -4039,6 +4039,7 @@ public class WebManager {
|
||||
gs.append("\"land_price_per_sqm\":").append(cfg.landPricePerSqm).append(",");
|
||||
gs.append("\"max_lands\":").append(cfg.maxLands).append(",");
|
||||
gs.append("\"max_effects\":").append(cfg.maxEffects).append(",");
|
||||
gs.append("\"max_effect_level\":").append(cfg.maxEffectLevel).append(",");
|
||||
gs.append("\"home_limit\":").append(cfg.homeLimit).append(",");
|
||||
gs.append("\"join_price\":").append(cfg.joinPrice).append(",");
|
||||
gs.append("\"auto_renew\":").append(cfg.autoRenew ? 1 : 0).append(",");
|
||||
@@ -4437,6 +4438,13 @@ public class WebManager {
|
||||
try { cfg.maxEffects = Integer.parseInt(maxEffStr); }
|
||||
catch (Exception ignored) { cfg.maxEffects = 5; }
|
||||
}
|
||||
// ★ 药效等级上限(2026-10-04 任务4)
|
||||
String maxEffLvStr = extractJsonField(obj, "max_effect_level");
|
||||
if (!maxEffLvStr.isEmpty()) {
|
||||
try { cfg.maxEffectLevel = Integer.parseInt(maxEffLvStr); }
|
||||
catch (Exception ignored) { cfg.maxEffectLevel = UserGroupManager.DEFAULT_MAX_EFFECT_LEVEL; }
|
||||
}
|
||||
if (cfg.maxEffectLevel <= 0) cfg.maxEffectLevel = UserGroupManager.DEFAULT_MAX_EFFECT_LEVEL;
|
||||
String homeLimStr = extractJsonField(obj, "home_limit");
|
||||
if (!homeLimStr.isEmpty()) try { cfg.homeLimit = Integer.parseInt(homeLimStr); } catch (Exception ignored) {}
|
||||
String joinStr = extractJsonField(obj, "join_price");
|
||||
|
||||
Reference in New Issue
Block a user