From 4160c60aa63eb0902846b5f871d81c0c1ba3be3c Mon Sep 17 00:00:00 2001 From: ypsdf1 Date: Sun, 4 Oct 2026 19:26:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7=E7=BB=84?= =?UTF-8?q?=E8=8D=AF=E6=95=88=E7=AD=89=E7=BA=A7=E4=B8=8A=E9=99=90=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=EF=BC=8C=E4=B8=8EJava=E7=AB=AF=E5=8F=8C=E5=90=91?= =?UTF-8?q?=E6=89=93=E9=80=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 配合 Java 端 6f92028(原版药效强度上限 256)。原版 /effect 的 amplifier 硬上限是 255,即药效强度 1~256,此前 Web 侧封顶写死 255 且各建表点口径不一,本次统一为 max_effect_level 配置项。 改动: - web_user_groups 增加 max_effect_level 列(默认 256) · sync.php / land_api.php / core.php 全部 8 处建表块补列 · 3 处迁移表补 ALTER 条目,老库自动升级 - api/sync.php syncUserGroups:Java 推送时接收并写入 max_effect_level, <=0 或超过 256 一律归一到 256(原版硬上限不可突破) - api/land_api.php 新增 getLandMaxEffectLevel():按领地所有者所属 最高优先级用户组取上限,无组则 256;handleUpdateLandField 写入 give_effects 时改用该上限 clamp(原先硬编码 255) - api/land_api.php update_user_group 读写补该字段 - admin.php 用户组新建/编辑弹窗补「药效等级上限」输入框 (1~256,默认 256),并附原版范围说明;两处提交参数同步带上 规则:普通玩家(未加入任何用户组)固定按 256 封顶,严禁超限; 加入用户组后按组配置封顶,填 256 即不额外限制。 --- admin.php | 20 ++++++++++++++----- api/land_api.php | 50 ++++++++++++++++++++++++++++++++++++++++++++---- api/sync.php | 10 ++++++++-- core.php | 1 + 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/admin.php b/admin.php index 3bf0382..47e2440 100644 --- a/admin.php +++ b/admin.php @@ -3105,12 +3105,17 @@ function showAddUserGroup() { -
+
- +
+
+ + +
+
药效强度原版范围 1~256,普通玩家(未加入任何用户组)固定按 256 封顶,严禁超限。
@@ -3150,6 +3155,7 @@ async function doAddUserGroup() { const price = document.getElementById('ugPrice')?.value || '-1'; const maxLands = document.getElementById('ugMaxLands')?.value || '-1'; const maxEffects = document.getElementById('ugMaxEffects')?.value || '5'; + const maxEffectLevel = document.getElementById('ugMaxEffectLevel')?.value || '256'; const homeLimit = document.getElementById('ugHomeLimit')?.value || '0'; const joinPrice = document.getElementById('ugJoinPrice')?.value || '0'; const renewPrice = document.getElementById('ugRenewPrice')?.value || '0'; @@ -3164,7 +3170,7 @@ async function doAddUserGroup() { try { const res = await apiCall('update_user_group', { name, display_name: displayName, display_color: color, - priority, land_price_per_sqm: price, max_lands: maxLands, max_effects: maxEffects, + priority, land_price_per_sqm: price, max_lands: maxLands, max_effects: maxEffects, max_effect_level: maxEffectLevel, home_limit: homeLimit, join_price: joinPrice, renew_price: renewPrice, duration_minutes: duration, auto_renew: autoRenew, default_perms: '{}' @@ -3211,9 +3217,12 @@ async function showEditUserGroup(groupName) {
`; html += `
-
+
+
+
`; + html += `
说明:药效强度原版范围 1~256,普通玩家(未加入任何用户组)固定按 256 封顶,严禁超限。加入本组后按上面的值封顶,填 256 即不额外限制。
`; html += `
@@ -3259,6 +3268,7 @@ async function doEditUserGroup(groupName) { const price = document.getElementById('eugPrice')?.value || '-1'; const maxLands = document.getElementById('eugMaxLands')?.value || '-1'; const maxEffects = document.getElementById('eugMaxEffects')?.value || '5'; + const maxEffectLevel = document.getElementById('eugMaxEffectLevel')?.value || '256'; const homeLimit = document.getElementById('eugHomeLimit')?.value || '0'; const duration = document.getElementById('eugDuration')?.value || '0'; const joinPrice = document.getElementById('eugJoinPrice')?.value || '0'; @@ -3274,7 +3284,7 @@ async function doEditUserGroup(groupName) { try { const res = await apiCall('update_user_group', { name: groupName, display_name: displayName, display_color: color, - priority, land_price_per_sqm: price, max_lands: maxLands, max_effects: maxEffects, + priority, land_price_per_sqm: price, max_lands: maxLands, max_effects: maxEffects, max_effect_level: maxEffectLevel, home_limit: homeLimit, duration_minutes: duration, join_price: joinPrice, renew_price: renewPrice, auto_renew: autoRenew, default_perms: JSON.stringify(perms) diff --git a/api/land_api.php b/api/land_api.php index 474eed0..a05ecbd 100644 --- a/api/land_api.php +++ b/api/land_api.php @@ -1680,6 +1680,7 @@ function getLandMaxEffects($db, $land) { land_price_per_sqm INTEGER DEFAULT -1, max_lands INTEGER DEFAULT -1, max_effects INTEGER DEFAULT 5, + max_effect_level INTEGER DEFAULT 256, home_limit INTEGER DEFAULT 0, join_price INTEGER DEFAULT 0, auto_renew INTEGER DEFAULT 0, @@ -1711,6 +1712,33 @@ function getLandMaxEffects($db, $land) { return $fallback; } +/** + * ★ 领地增益【药效等级上限】(2026-10-04 任务4) + * 取领地所有者所属最高优先级用户组的 max_effect_level,默认 256(原版最大药效强度)。 + * <=0 或非法值一律归一到 256 —— 原版 /effect 的 amplifier 硬上限是 255(= 强度256), + * 任何情况下都不允许突破原版。 + */ +function getLandMaxEffectLevel($db, $land) { + $fallback = 256; + $owner = $land['owner'] ?? ''; + if (empty($owner)) return $fallback; + try { + $st = $db->prepare("SELECT g.max_effect_level FROM web_user_group_members m + LEFT JOIN web_user_groups g ON m.group_name = g.group_name + WHERE m.player_name = :p AND (m.expiry_time = 0 OR m.expiry_time > :now) + ORDER BY g.priority DESC LIMIT 1"); + $st->bindValue(':p', $owner, SQLITE3_TEXT); + $st->bindValue(':now', time(), SQLITE3_INTEGER); + $row = $st->execute()->fetchArray(SQLITE3_ASSOC); + if ($row && $row['max_effect_level'] !== null) { + $v = (int)$row['max_effect_level']; + if ($v <= 0 || $v > $fallback) return $fallback; + return $v; + } + } catch (\Throwable $e) { /* 表缺失等 */ } + return $fallback; +} + function handleUpdateLandField($db, $playerName, $post) { $name = $post['name'] ?? ''; $field = $post['field'] ?? ''; @@ -1772,18 +1800,20 @@ function handleUpdateLandField($db, $playerName, $post) { $arr = json_decode($value, true); if (is_array($arr)) { if ($field === 'give_effects') { - // ★ 2026-10-04 任务3:数量上限(按领地所有者用户组 max_effects,默认5)+ 等级封顶1~255 + // ★ 2026-10-04 任务3:数量上限(按领地所有者用户组 max_effects,默认5) + // ★ 2026-10-04 任务4:等级封顶(按 max_effect_level,普通玩家=原版256) $maxEff = getLandMaxEffects($db, $land); if (count($arr) > $maxEff) { $arr = array_slice($arr, 0, $maxEff); } + $maxLv = getLandMaxEffectLevel($db, $land); // [["夜视","1","99999"]] → "夜视:1:99999" $parts = []; foreach ($arr as $e) { if (is_array($e)) { if (isset($e[1]) && $e[1] !== '') { $lv = (int)$e[1]; - $e[1] = (string)max(1, min(255, $lv)); + $e[1] = (string)max(1, min($maxLv, $lv)); } $parts[] = implode(':', $e); } else { @@ -2371,6 +2401,7 @@ function handleListUserGroups($db) { land_price_per_sqm INTEGER DEFAULT -1, max_lands INTEGER DEFAULT -1, max_effects INTEGER DEFAULT 5, + max_effect_level INTEGER DEFAULT 256, home_limit INTEGER DEFAULT 0, join_price INTEGER DEFAULT 0, auto_renew INTEGER DEFAULT 0, @@ -2392,6 +2423,7 @@ function handleListUserGroups($db) { 'renew_price' => 'ALTER TABLE web_user_groups ADD COLUMN renew_price INTEGER DEFAULT 0', 'duration_minutes' => 'ALTER TABLE web_user_groups ADD COLUMN duration_minutes INTEGER DEFAULT 0', 'max_effects' => 'ALTER TABLE web_user_groups ADD COLUMN max_effects INTEGER DEFAULT 5', + 'max_effect_level' => 'ALTER TABLE web_user_groups ADD COLUMN max_effect_level INTEGER DEFAULT 256', ]; foreach ($migrations as $col => $sql) { if (!in_array($col, $columns)) { @@ -2430,6 +2462,7 @@ function handleUpdateUserGroup($db, $data) { land_price_per_sqm INTEGER DEFAULT -1, max_lands INTEGER DEFAULT -1, max_effects INTEGER DEFAULT 5, + max_effect_level INTEGER DEFAULT 256, home_limit INTEGER DEFAULT 0, join_price INTEGER DEFAULT 0, auto_renew INTEGER DEFAULT 0, @@ -2446,6 +2479,9 @@ function handleUpdateUserGroup($db, $data) { $pricePerSqm = (int)($data['land_price_per_sqm'] ?? -1); $maxLands = (int)($data['max_lands'] ?? -1); $maxEffects = (int)($data['max_effects'] ?? 5); // 领地增益效果上限,<=0=不限 + // ★ 药效等级上限:<=0 或超过原版 256 一律归一到 256 + $maxEffectLevel = (int)($data['max_effect_level'] ?? 256); + if ($maxEffectLevel <= 0 || $maxEffectLevel > 256) $maxEffectLevel = 256; $homeLimit = (int)($data['home_limit'] ?? 0); $joinPrice = (int)($data['join_price'] ?? 0); $renewPrice = (int)($data['renew_price'] ?? 0); @@ -2455,9 +2491,9 @@ function handleUpdateUserGroup($db, $data) { $stmt = $db->prepare("INSERT OR REPLACE INTO web_user_groups (group_name, display_name, display_color, display_emoji, priority, - land_price_per_sqm, max_lands, max_effects, home_limit, join_price, auto_renew, renew_price, duration_minutes, default_perms, synced_at) + land_price_per_sqm, max_lands, max_effects, max_effect_level, home_limit, join_price, auto_renew, renew_price, duration_minutes, default_perms, synced_at) VALUES (:name, :display, :color, :emoji, :priority, - :price, :maxlands, :maxEffects, :homeLimit, :joinPrice, :autoRenew, :renewPrice, :duration, :perms, :synced)"); + :price, :maxlands, :maxEffects, :maxEffectLevel, :homeLimit, :joinPrice, :autoRenew, :renewPrice, :duration, :perms, :synced)"); $stmt->bindValue(':name', $name, SQLITE3_TEXT); $stmt->bindValue(':display', $displayName, SQLITE3_TEXT); $stmt->bindValue(':color', $displayColor, SQLITE3_TEXT); @@ -2466,6 +2502,7 @@ function handleUpdateUserGroup($db, $data) { $stmt->bindValue(':price', $pricePerSqm, SQLITE3_INTEGER); $stmt->bindValue(':maxlands', $maxLands, SQLITE3_INTEGER); $stmt->bindValue(':maxEffects', $maxEffects, SQLITE3_INTEGER); + $stmt->bindValue(':maxEffectLevel', $maxEffectLevel, SQLITE3_INTEGER); $stmt->bindValue(':homeLimit', $homeLimit, SQLITE3_INTEGER); $stmt->bindValue(':joinPrice', $joinPrice, SQLITE3_INTEGER); $stmt->bindValue(':autoRenew', $autoRenew, SQLITE3_INTEGER); @@ -2654,6 +2691,7 @@ function handleGetPlayerGroups($db, $player) { land_price_per_sqm INTEGER DEFAULT -1, max_lands INTEGER DEFAULT -1, max_effects INTEGER DEFAULT 5, + max_effect_level INTEGER DEFAULT 256, home_limit INTEGER DEFAULT 0, join_price INTEGER DEFAULT 0, auto_renew INTEGER DEFAULT 0, @@ -2673,6 +2711,7 @@ function handleGetPlayerGroups($db, $player) { 'renew_price' => 'ALTER TABLE web_user_groups ADD COLUMN renew_price INTEGER DEFAULT 0', 'duration_minutes' => 'ALTER TABLE web_user_groups ADD COLUMN duration_minutes INTEGER DEFAULT 0', 'max_effects' => 'ALTER TABLE web_user_groups ADD COLUMN max_effects INTEGER DEFAULT 5', + 'max_effect_level' => 'ALTER TABLE web_user_groups ADD COLUMN max_effect_level INTEGER DEFAULT 256', ]; foreach ($migrations as $col => $sql) { if (!in_array($col, $columns)) { @@ -2697,6 +2736,7 @@ function handleGetPlayerGroups($db, $player) { land_price_per_sqm INTEGER DEFAULT -1, max_lands INTEGER DEFAULT -1, max_effects INTEGER DEFAULT 5, + max_effect_level INTEGER DEFAULT 256, home_limit INTEGER DEFAULT 0, join_price INTEGER DEFAULT 0, auto_renew INTEGER DEFAULT 0, @@ -2733,6 +2773,7 @@ function handleListAvailableGroups($db) { land_price_per_sqm INTEGER DEFAULT -1, max_lands INTEGER DEFAULT -1, max_effects INTEGER DEFAULT 5, + max_effect_level INTEGER DEFAULT 256, home_limit INTEGER DEFAULT 0, join_price INTEGER DEFAULT 0, auto_renew INTEGER DEFAULT 0, @@ -2750,6 +2791,7 @@ function handleListAvailableGroups($db) { 'renew_price' => 'ALTER TABLE web_user_groups ADD COLUMN renew_price INTEGER DEFAULT 0', 'duration_minutes' => 'ALTER TABLE web_user_groups ADD COLUMN duration_minutes INTEGER DEFAULT 0', 'max_effects' => 'ALTER TABLE web_user_groups ADD COLUMN max_effects INTEGER DEFAULT 5', + 'max_effect_level' => 'ALTER TABLE web_user_groups ADD COLUMN max_effect_level INTEGER DEFAULT 256', ]; foreach ($migrations as $col => $sql) { if (!in_array($col, $columns)) { diff --git a/api/sync.php b/api/sync.php index 0336d41..fc35fc6 100644 --- a/api/sync.php +++ b/api/sync.php @@ -914,6 +914,7 @@ function syncUserGroups() { land_price_per_sqm INTEGER DEFAULT -1, max_lands INTEGER DEFAULT -1, max_effects INTEGER DEFAULT 5, + max_effect_level INTEGER DEFAULT 256, home_limit INTEGER DEFAULT 0, join_price INTEGER DEFAULT 0, auto_renew INTEGER DEFAULT 0, @@ -936,6 +937,7 @@ function syncUserGroups() { 'renew_price' => 'ALTER TABLE web_user_groups ADD COLUMN renew_price INTEGER DEFAULT 0', 'duration_minutes' => 'ALTER TABLE web_user_groups ADD COLUMN duration_minutes INTEGER DEFAULT 0', 'max_effects' => 'ALTER TABLE web_user_groups ADD COLUMN max_effects INTEGER DEFAULT 5', + 'max_effect_level' => 'ALTER TABLE web_user_groups ADD COLUMN max_effect_level INTEGER DEFAULT 256', ]; foreach ($migrations as $col => $sql) { if (!in_array($col, $columns)) { @@ -946,10 +948,10 @@ function syncUserGroups() { $now = time(); $stmt = $db->prepare("INSERT OR REPLACE INTO web_user_groups (group_name, display_name, display_color, display_emoji, priority, - land_price_per_sqm, max_lands, max_effects, home_limit, join_price, auto_renew, + land_price_per_sqm, max_lands, max_effects, max_effect_level, home_limit, join_price, auto_renew, renew_price, duration_minutes, default_perms, synced_at) VALUES (:name, :display, :color, :emoji, :priority, - :price, :maxlands, :maxeffects, :homelimit, :joinprice, :autorenew, + :price, :maxlands, :maxeffects, :maxeffectlevel, :homelimit, :joinprice, :autorenew, :renewprice, :duration, :perms, :synced)"); $count = 0; foreach ($groups as $g) { @@ -961,6 +963,10 @@ function syncUserGroups() { $stmt->bindValue(':price', (int)($g['land_price_per_sqm'] ?? -1), SQLITE3_INTEGER); $stmt->bindValue(':maxlands', (int)($g['max_lands'] ?? -1), SQLITE3_INTEGER); $stmt->bindValue(':maxeffects', (int)($g['max_effects'] ?? 5), SQLITE3_INTEGER); + // ★ 药效等级上限(2026-10-04 任务4):<=0 归一到原版上限 256 + $mel = (int)($g['max_effect_level'] ?? 256); + if ($mel <= 0 || $mel > 256) $mel = 256; + $stmt->bindValue(':maxeffectlevel', $mel, SQLITE3_INTEGER); $stmt->bindValue(':homelimit', (int)($g['home_limit'] ?? 0), SQLITE3_INTEGER); $stmt->bindValue(':joinprice', (int)($g['join_price'] ?? 0), SQLITE3_INTEGER); $stmt->bindValue(':autorenew', (int)($g['auto_renew'] ?? 0), SQLITE3_INTEGER); diff --git a/core.php b/core.php index e1d7ff0..6b56831 100644 --- a/core.php +++ b/core.php @@ -645,6 +645,7 @@ function initTables(SQLite3 $db) { land_price_per_sqm INTEGER DEFAULT -1, max_lands INTEGER DEFAULT -1, max_effects INTEGER DEFAULT 5, + max_effect_level INTEGER DEFAULT 256, home_limit INTEGER DEFAULT 0, join_price INTEGER DEFAULT 0, auto_renew INTEGER DEFAULT 0,