领地/商城目录接入alignGate差集对账,重启不再整包推,多退少补
This commit is contained in:
@@ -4169,6 +4169,44 @@ public class WebManager {
|
||||
new String[]{"target", "ban_type", "reason", "source", "expire_time"},
|
||||
new String[]{"expire_time"},
|
||||
alignMap("ban_type", "type", "expire_time", "expire"), true, false));
|
||||
// —— 领地数据(PHP web_area_lands;游戏内 area_lands 为唯一权威)——
|
||||
// pull=false:Web 后台的领地改动不回流 Java(与改造前一致)。
|
||||
// pushOnExtra=true:PHP 多出的行(游戏里已删 / 后台自建)→ 触发一次整包推,
|
||||
// 由 sync_lands 的「name NOT IN」退侧清掉 → 完成「多退」;「少补」靠 missing。
|
||||
// ★ 指纹 = 两端列交集 72 列:排除 PHP 独有的 synced_at/admin_changed/area_size/
|
||||
// clear_all_bad_effects(PHP 每轮写入都会变 → 恒 changed)与 Java 独有的
|
||||
// create_cost/deny_farmland_trample/deny_ender_teleport(PHP 无此列)。
|
||||
// ★ warp_x/y/z/yaw/pitch 是 REAL,必须放进 intcols:Java String.valueOf(1.0)="1.0"
|
||||
// 而 PHP (string)1.0="1" → 若按文本比对每轮恒 changed;两端都按整数截断
|
||||
// (alignCanonVal/alignmentCanonVal 双端同款)才严格一致,warp_world 是文本列。
|
||||
ALIGN_CFGS.put("lands", new AlignCfg("lands",
|
||||
new String[]{"id"},
|
||||
new String[]{
|
||||
"id", "name", "owner", "world", "x1", "z1",
|
||||
"x2", "z2", "y_min", "y_max", "confiscate_items", "deny_use_items",
|
||||
"give_effects", "clear_effects", "clear_all_bad", "punish_commands", "deny_block_place", "deny_block_break",
|
||||
"deny_container", "deny_pvp", "deny_fall_damage", "deny_hunger", "deny_all_damage", "deny_drop",
|
||||
"deny_mount", "deny_ender_pearl", "deny_bow", "deny_potion", "deny_explosion", "deny_raid",
|
||||
"deny_fire_spread", "deny_all_effects", "deny_item_frame", "deny_move", "deny_pickup", "deny_fire",
|
||||
"peace_mode", "peace_mode_duration", "peace_whitelist", "enforce_game_mode", "mode_exempt", "enter_msg",
|
||||
"leave_msg", "confiscate_msg", "enable_announce", "announce_template", "txt_content", "created_at",
|
||||
"deny_thrown_projectiles", "deny_glowing", "deny_redstone_interaction", "deny_door_interaction", "deny_noteblock_jukebox", "deny_lead",
|
||||
"deny_crop_harvest", "deny_wool_shear", "deny_animal_feeding", "warp_x", "warp_y", "warp_z",
|
||||
"warp_yaw", "warp_pitch", "warp_world", "deny_mob_attack", "is_public_building", "deny_fluid",
|
||||
"allow_visitor_teleport", "deny_entity_interact", "deny_sign_edit", "deny_spawn_egg", "deny_wax", "bad_effects"
|
||||
},
|
||||
new String[]{
|
||||
"id", "x1", "z1", "x2", "z2", "y_min",
|
||||
"y_max", "clear_all_bad", "deny_block_place", "deny_block_break", "deny_container", "deny_pvp",
|
||||
"deny_fall_damage", "deny_hunger", "deny_all_damage", "deny_drop", "deny_mount", "deny_ender_pearl",
|
||||
"deny_bow", "deny_potion", "deny_explosion", "deny_raid", "deny_fire_spread", "deny_all_effects",
|
||||
"deny_item_frame", "deny_move", "deny_pickup", "deny_fire", "peace_mode", "peace_mode_duration",
|
||||
"enable_announce", "created_at", "deny_thrown_projectiles", "deny_glowing", "deny_redstone_interaction", "deny_door_interaction",
|
||||
"deny_noteblock_jukebox", "deny_lead", "deny_crop_harvest", "deny_wool_shear", "deny_animal_feeding", "warp_x",
|
||||
"warp_y", "warp_z", "warp_yaw", "warp_pitch", "deny_mob_attack", "is_public_building",
|
||||
"deny_fluid", "allow_visitor_teleport", "deny_entity_interact", "deny_sign_edit", "deny_spawn_egg", "deny_wax"
|
||||
},
|
||||
alignMap(), false, true));
|
||||
// —— 在线玩家:PHP 端是「整表重建」,PHP 比 Java 多的行(人已下线)必须靠一次推送清掉
|
||||
// 所以 extra 也要触发推送;指纹只比「谁在线」,login_time 每次都变不能进指纹 ——
|
||||
ALIGN_CFGS.put("online", new AlignCfg("online",
|
||||
@@ -5107,7 +5145,14 @@ public class WebManager {
|
||||
syncBans();
|
||||
syncAdmins();
|
||||
|
||||
if (currentHash.equals(lastLandDataHash)) {
|
||||
// ★ 双向对账(多退少补):PHP 数据齐全就不推 —— 消除「重启必整包推」
|
||||
// (lastLandDataHash 是内存字段,重启清零,旧逻辑每次开服必整包一次)。
|
||||
// 对账无答复(alignTimeout)时 needPush()==false → 同样不推,符合「本轮不推不收」;
|
||||
// 只有对账请求本身没做成(返回 null)才回退本地 hash 判断,行为与改造前一致。
|
||||
AlignResult arLands = alignGate("lands", lands);
|
||||
if (arLands != null && !arLands.needPush()) return;
|
||||
// 走到这里:要么对账明确要求补推(本地 hash 相等也不得拦截),要么对账没做成
|
||||
if (arLands == null && currentHash.equals(lastLandDataHash)) {
|
||||
// ★ hash未变化,静默跳过(但首次运行或强制刷新时会同步)
|
||||
return;
|
||||
}
|
||||
@@ -10321,10 +10366,22 @@ public class WebManager {
|
||||
return;
|
||||
}
|
||||
String json = sm.buildCatalogJson();
|
||||
|
||||
// ★ 双向对账(多退少补):复用 "shop" 配置(同表 shop_items、同键 id、
|
||||
// 同指纹列 id/category/display_name/material/buy_price/sell_price),与
|
||||
// syncShopData 共用一套对账状态 —— 两边同源于 shop/*.md,且 alignGate 的
|
||||
// changed 只在「Java 自己的指纹变过」时才推(pull=false),两个推送源
|
||||
// 不会互相覆盖。PHP 齐全 → 不推(消除「重启必整包推」);PHP 缺行 → 补推;
|
||||
// 对账没做成或目录行解析不出来 → 回退本地 hash,行为与改造前一致。
|
||||
List<Map<String, Object>> rows = buildShopCatalogRows(json);
|
||||
AlignResult arCat = rows.isEmpty() ? null : alignGate("shop", rows);
|
||||
boolean alignNeedPushCat = arCat != null && arCat.needPush();
|
||||
|
||||
// ★ 无变化静默:目录只由 Java 写(PHP 的 set_shop_catalog 只 upsert 目录字段,
|
||||
// 库存/管理员价走独立列),内容没变就别每轮整包硬推 —— 这是「无脑推」大户之一。
|
||||
// 对账明确要补推时本地 hash 不得短路(PHP 被清空后本地没变也要推,同 syncShopData)。
|
||||
String catalogHash = json.length() + ":" + json.hashCode();
|
||||
if (catalogHash.equals(lastShopCatalogHash)) return;
|
||||
if (!alignNeedPushCat && catalogHash.equals(lastShopCatalogHash)) return;
|
||||
String urlStr = webBaseUrl + "/api/sync.php?action=set_shop_catalog&secret="
|
||||
+ java.net.URLEncoder.encode(secretKey, "UTF-8");
|
||||
String resp = doPost(urlStr, json);
|
||||
@@ -10339,6 +10396,44 @@ public class WebManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从商品目录 JSON 构造对账行(字段名必须与 "shop" 对账配置 / PHP shop_items 一致)。
|
||||
* 解析不出来返回空列表 —— 调用方按「对账没做成」回退本地 hash,不误判。
|
||||
*/
|
||||
private static List<Map<String, Object>> buildShopCatalogRows(String json) {
|
||||
List<Map<String, Object>> rows = new ArrayList<>();
|
||||
try {
|
||||
Map<String, Object> root = parseJson(json);
|
||||
Object cats = root.get("categories");
|
||||
if (!(cats instanceof List)) return rows;
|
||||
for (Object c : (List<?>) cats) {
|
||||
if (!(c instanceof Map)) continue;
|
||||
Map<?, ?> cat = (Map<?, ?>) c;
|
||||
String catName = strOf(cat.get("name"));
|
||||
if (catName.isEmpty()) continue;
|
||||
Object items = cat.get("items");
|
||||
if (!(items instanceof List)) continue;
|
||||
for (Object o : (List<?>) items) {
|
||||
if (!(o instanceof Map)) continue;
|
||||
Map<?, ?> it = (Map<?, ?>) o;
|
||||
String id = strOf(it.get("id"));
|
||||
if (id.isEmpty()) continue;
|
||||
Map<String, Object> r = new LinkedHashMap<>();
|
||||
r.put("id", id);
|
||||
r.put("category", catName);
|
||||
r.put("display_name", strOf(it.get("display_name")));
|
||||
r.put("material", strOf(it.get("material")));
|
||||
r.put("buy_price", it.get("buy_price"));
|
||||
r.put("sell_price", it.get("sell_price"));
|
||||
rows.add(r);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// 解析失败 → 空列表,调用方回退本地 hash 判断
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除PHP端的管理员价格标记
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user