From f19efa89a85c9b9e04002673b18ffc32d8682085 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Mon, 20 Jul 2026 13:18:58 +0800 Subject: [PATCH] =?UTF-8?q?=E9=AB=98=E9=A2=91=E5=87=BA=E5=94=AE=E7=BC=93?= =?UTF-8?q?=E5=86=B2=E6=9C=BA=E5=88=B6:=201=E5=88=86=E9=92=9F=E5=86=85?= =?UTF-8?q?=E5=8D=95=E7=A7=8D=E5=95=86=E5=93=81=E2=89=A510=E6=AC=A1?= =?UTF-8?q?=E6=97=B6=E6=9A=82=E7=BC=93=E6=8E=A8=E9=80=8160=E7=A7=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Sdf1_login/BondManager.java | 8 +-- src/main/java/Sdf1_login/WebManager.java | 88 ++++++++++++++++++++++- src/main/resources/plugin.yml | 2 +- 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/src/main/java/Sdf1_login/BondManager.java b/src/main/java/Sdf1_login/BondManager.java index b8544ba..36b153b 100644 --- a/src/main/java/Sdf1_login/BondManager.java +++ b/src/main/java/Sdf1_login/BondManager.java @@ -13,7 +13,7 @@ public class BondManager { // ===== 交易监听器 ===== public interface TransactionListener { - void onTransaction(String playerName, String type, int amount); + void onTransaction(String playerName, String type, int amount, String targetPlayer); } private final List transactionListeners = new ArrayList<>(); @@ -21,10 +21,10 @@ public class BondManager { transactionListeners.add(listener); } - private void fireTransactionEvent(String playerName, String type, int amount) { + private void fireTransactionEvent(String playerName, String type, int amount, String targetPlayer) { for (TransactionListener listener : transactionListeners) { try { - listener.onTransaction(playerName, type, amount); + listener.onTransaction(playerName, type, amount, targetPlayer); } catch (Exception e) { e.printStackTrace(); } @@ -382,7 +382,7 @@ public class BondManager { ps.executeUpdate(); ps.close(); // 触发交易监听器 - fireTransactionEvent(player, type, amount); + fireTransactionEvent(player, type, amount, targetPlayer); } catch (SQLException e) { e.printStackTrace(); } diff --git a/src/main/java/Sdf1_login/WebManager.java b/src/main/java/Sdf1_login/WebManager.java index 4e51efd..be36f9e 100644 --- a/src/main/java/Sdf1_login/WebManager.java +++ b/src/main/java/Sdf1_login/WebManager.java @@ -872,13 +872,75 @@ public class WebManager { // ★ 注册交易监听器(需在BondManager初始化后调用) public void registerTransactionListener(BondManager bondMgr) { if (bondMgr == null) return; - bondMgr.addTransactionListener((playerName, type, amount) -> { - plugin.getLogger().info("[Web交易即时] 检测到交易: " + playerName + " " + type + " " + amount + ",立即推送"); - requestImmediateTransactionSync(); + bondMgr.addTransactionListener((playerName, type, amount, targetPlayer) -> { + // 高频出售商品缓冲逻辑:shop_sell类型商品在1分钟内≥10次时暂缓推送 + if ("shop_sell".equals(type) && targetPlayer != null && !targetPlayer.isEmpty()) { + handleHighFreqSell(playerName, targetPlayer, amount); + } else { + plugin.getLogger().info("[Web交易即时] 检测到交易: " + playerName + " " + type + " " + amount + ",立即推送"); + requestImmediateTransactionSync(); + } }); plugin.getLogger().info("[Web通信] 交易即时推送监听器已注册"); } + /** + * 高频出售缓冲处理:追踪每种商品的出售频率 + * 1分钟内单种商品售卖≥10次时进入缓冲模式,暂缓推送到PHP,60秒后批量推送 + */ + private void handleHighFreqSell(String playerName, String itemId, int amount) { + long now = System.currentTimeMillis(); + SellItemBuffer buf = sellBuffers.computeIfAbsent(itemId, k -> new SellItemBuffer(itemId)); + + // 如果窗口已过期(>60秒),重置计数器 + if (now - buf.windowStart > 60000) { + buf.count = 0; + buf.windowStart = now; + } + + buf.count++; + + // 已经在缓冲模式中,不做任何推送 + if (buf.buffering && now < buf.bufferEnd) { + plugin.getLogger().info("[Web交易即时] 高频商品缓冲中(" + itemId + "),第" + buf.count + "笔,不推送"); + return; + } + + // 达到阈值,进入缓冲模式 + if (buf.count >= HIGH_FREQ_SELL_THRESHOLD && !buf.buffering) { + buf.buffering = true; + buf.bufferEnd = now + HIGH_FREQ_BUFFER_MS; + inHighFreqBufferMode = true; + bufferModeEndTime = Math.max(bufferModeEndTime, buf.bufferEnd); + plugin.getLogger().info("[Web交易即时] ★ 高频商品触发缓冲: " + itemId + " 1分钟内" + buf.count + "次,暂缓推送60秒"); + + // 调度60秒后的批量推送 + new BukkitRunnable() { + @Override + public void run() { + plugin.getLogger().info("[Web交易即时] 高频缓冲到期(" + itemId + "),批量推送交易"); + buf.buffering = false; + buf.count = 0; + buf.windowStart = System.currentTimeMillis(); + + // 检查是否所有缓冲都结束了 + boolean anyBuffering = false; + for (SellItemBuffer b : sellBuffers.values()) { + if (b.buffering) { anyBuffering = true; break; } + } + if (!anyBuffering) inHighFreqBufferMode = false; + + requestImmediateTransactionSync(); + } + }.runTaskLater(plugin, 20L * 60); // 60秒 + return; + } + + // 普通交易(未达阈值),立即推送 + plugin.getLogger().info("[Web交易即时] 检测到出售: " + playerName + " " + itemId + " " + amount + ",立即推送"); + requestImmediateTransactionSync(); + } + public void start() { if (!enabled) { plugin.getLogger().info("[Web通信] 未启用,在插件设置.txt中设置 web通信-启用=true"); @@ -1318,6 +1380,26 @@ public class WebManager { private static final long MIN_IMMEDIATE_TX_SYNC_MS = 3000; // 最小间隔3秒,防止频繁推送 private volatile boolean pendingImmediateTxSync = false; + // ★ 高频出售商品缓冲机制:1分钟内单种商品售卖≥10次时暂缓推送 + private final ConcurrentHashMap sellBuffers = new ConcurrentHashMap<>(); + private static final int HIGH_FREQ_SELL_THRESHOLD = 10; // 10次触发缓冲 + private static final long HIGH_FREQ_BUFFER_MS = 60000; // 缓冲60秒 + private volatile boolean inHighFreqBufferMode = false; // 全局缓冲模式标志 + private volatile long bufferModeEndTime = 0; // 缓冲模式结束时间 + + private static class SellItemBuffer { + final String itemId; + volatile int count = 0; + volatile long windowStart = 0; + volatile boolean buffering = false; + volatile long bufferEnd = 0; + + SellItemBuffer(String itemId) { + this.itemId = itemId; + this.windowStart = System.currentTimeMillis(); + } + } + private void requestImmediateTransactionSync() { long now = System.currentTimeMillis(); if (now - lastImmediateTxSyncTime < MIN_IMMEDIATE_TX_SYNC_MS) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 2309b04..530d801 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: Sdf1_login -version: 2.8 +version: 2.81 main: Sdf1_login.Main api-version: '1.21' commands: