一、BTG v1.0.3 插件原生基础概述

BTG v1.0.3(Before Thought Game)是 OpenClaw 配套竞技游戏专用插件,内置本地独立 btg_runner 运行器,核心功能覆盖 AI 机器人对战、全球竞技排行榜数据同步、对局结算计分、机器人策略技能调度、赛事匹配、战绩存档;整套插件分为底层 btg_runner 执行工具、上层 AI 对战 btg 技能两层结构,用于自动化批量 AI 竞技冲榜、多机器人自动匹配对局、生成对战战绩榜单。

当前 v1.0.3 基础版本仅完成 runner 基础启动、基础 HTTP 通信、简单对战调度逻辑,未做网络通信安全隔离、runner 进程沙箱、机器人策略输入注入防护、排行榜数据防篡改、多机器人并发调度、对局数据持久容错、通信风控限流、对战行为审计监控,批量机器人冲榜、高频对局场景下会出现通信劫持、策略指令注入篡改对战逻辑、刷分作弊、runner 进程卡死、对局数据丢失、API 封禁机器人账号等问题,为此落地全套专项二次改造升级计划,从网络通信安全、runner 进程沙箱隔离、对战指令防注入、排行榜数据校验、多机器人并发队列、对局持久化容错、API 限流风控、全链路对战审计八大底层模块完整重构,根除原生稳定性、安全、作弊风控全部短板。

二、原版 BTG v1.0.3 七大核心原生缺陷

1. 网络通信无域名白名单、无证书校验,易中间人劫持篡改对局 / 榜单数据

原生 HTTP 请求无固定域名校验,可被注入指令访问任意第三方地址;未强制 TLS 校验、无双向证书绑定,中间人可拦截、篡改对局胜负、排行榜积分数据;通信报文明文传输,机器人 token、对战凭证直接暴露,存在盗号、恶意刷分风险。

2. btg_runner 无独立进程沙箱,多机器人共用主线程,并发对局内存溢出卡死

所有 AI 对战共用单一全局 runner 进程,无进程隔离;批量启动数十个机器人同时匹配对战时资源抢占,CPU / 内存持续暴涨,runner 无超时销毁机制,僵尸进程长期占用算力;单 runner 崩溃会导致全部在线机器人对局强制中断,战绩直接丢失。

3. AI 对战策略指令无输入净化,提示注入可篡改机器人操作逻辑、恶意刷分

直接将大模型生成的对战策略、操作指令拼接传入 runner 执行,无高危字符过滤、指令白名单校验;恶意构造特殊符号、参数注入可跳过正常对局计分逻辑、强制修改胜负判定、批量刷取排行榜高分,破坏竞技公平性。

4. 排行榜同步无数据哈希校验,本地伪造战绩可直接覆盖云端榜单

同步积分、对局战绩时仅简单 POST 上传原始数据,无本地 + 云端双重哈希签名校验;本地篡改战绩文件、伪造胜利对局可直接提交至官网榜单,缺少防作弊校验机制,无法区分正常对局与刷分伪造数据。

5. 无异步对战调度限流队列,高频批量冲榜触发平台 API 风控封禁机器人

所有匹配、对战、榜单同步请求同步无限制并发,短时间大量机器人循环冲榜会高频调用beforethoughtgame.com接口,极易触发平台 QPS 限制,批量封禁机器人 token;无消峰延时、任务优先级调度,批量对局阻塞正常单人竞技请求。

6. 对局战绩本地无事务持久化,runner 崩溃、网络中断直接丢失完整对局记录

对局过程中战绩、操作记录仅内存临时存储,无分段落盘预写日志;runner 意外退出、网络断开时当前对局全部数据清空,无法回溯对战流程、无法申诉榜单积分异常;无自动断点续赛机制,中断对局需要重新从头匹配。

7. 无对战行为、网络请求审计日志,刷分作弊、账号封禁无法溯源

仅极简打印 runner 启动日志,不记录机器人操作指令、对局胜负同步记录、API 调用频次、网络异常报文;出现恶意刷分、账号被封禁、积分异常时无法定位对应机器人、触发指令、操作时间,缺少风险告警机制。

三、BTG 专属二次改造升级完整执行计划

(一)改造核心目标

  1. 搭建固定域名白名单 + TLS 双向证书绑定加密通信,拦截恶意外联、中间人劫持,对战报文加密传输保护机器人凭证;
  2. 实现多机器人独立隔离 btg_runner 进程池,硬件资源上限管控,僵尸进程自动销毁,单一 runner 崩溃不影响其余机器人对局;
  3. 三层对战指令防护:输入净化 + 操作指令白名单 + 沙箱参数传参,彻底拦截注入篡改对战逻辑、恶意刷分作弊行为;
  4. 对局 / 榜单数据双层哈希签名校验,本地战绩与云端同步强制校验完整性,拦截伪造虚假胜利对局,保障竞技公平;
  5. 构建带优先级异步对战任务限流队列,限制单机器人、全局 API 并发频次,自动消峰延时,规避平台风控封禁账号;
  6. 对局分段预写日志持久化存储,支持断点续赛,runner 崩溃、断网可恢复未完成对局,完整留存对战记录用于积分申诉;
  7. 搭建全链路对战审计 + API 调用监控,刷分、高频请求、通信异常实时风险告警,作弊行为完整可溯源;
  8. 100% 兼容原版 btg_runner 调用规则、beforethoughtgame.com通信协议、机器人对战技能、排行榜同步逻辑,上层 OpenClaw 对战调度代码零修改,无缝平滑升级。

(二)二次改造对比原版核心优势

  1. 通信链路安全防劫持 仅允许访问官方固定域名,强制 TLS1.3 双向证书校验,对战报文加密传输,中间人无法篡改积分、盗取机器人凭证,杜绝榜单数据伪造。
  2. 多机器人高并发稳定对战 独立 runner 进程池隔离各机器人算力资源,设置 CPU / 内存硬上限,卡死进程自动销毁,单个机器人崩溃不会中断全局竞技任务。
  3. 竞技公平防刷分作弊闭环 高危字符清洗 + 合法操作白名单 + 沙箱隔离三层防护,注入指令无法篡改胜负判定;战绩哈希签名校验拦截伪造对局,杜绝恶意刷排行榜高分。
  4. API 请求可控,规避账号封禁 精细化限流队列,区分冲榜批量任务与正常单人对局优先级,自动平缓高频请求峰值,大幅降低机器人 token 被平台风控封禁概率。
  5. 对局数据高可靠不丢失,支持申诉回溯 对局实时分段落盘预写日志,网络中断、runner 崩溃可断点续赛,完整对战记录永久留存,积分异常可凭借本地日志向平台申诉。
  6. 运维可视化作弊溯源 每一条对战指令、榜单同步请求完整审计留存,高频刷分、通信劫持、账号受限实时推送告警,快速定位作弊机器人与违规操作指令。

四、完整底层代码二次修改方案(可直接复制部署)

改造涉及核心文件清单

官方域名白名单加密通信 btg-secure-network.js

btg_runner 隔离进程资源池 btg-runner-process-pool.js

对战策略指令注入防护 btg-battle-sanitize-filter.js

排行榜对局哈希防篡改校验 btg-rank-data-verify.js

异步限流对战任务调度队列 btg-battle-task-queue.js

对局预写日志持久断点续赛 btg-battle-persist-recover.js

对战行为风控审计告警 btg-battle-audit-risk.js

1. 官方域名白名单加密通信 btg-secure-network.js

原版缺陷代码

javascript

运行

// v1.0.3原版:无域名限制、无证书校验,明文请求
const axios = require("axios");
const API_HOST = "beforethoughtgame.com";

// 无任何安全校验,可被注入任意url
async function syncBattleRank(botToken, battleData) {
  return await axios.post(`https://${API_HOST}/rank/upload`, battleData, {
    headers: { token: botToken }
  })
}

二次重构优化代码

javascript

运行

const https = require("https");
const crypto = require("crypto");
// 仅放行官方固定域名
const ALLOW_HOST = "beforethoughtgame.com";
// TLS双向证书配置,拒绝劫持自签证书
const TLS_AGENT = new https.Agent({
  minVersion: "TLSv1.3",
  rejectUnauthorized: true
});

// 生成对战数据签名,用于防篡改校验
function signBattleData(botToken, rawData) {
  return crypto.createHmac("sha256", botToken)
    .update(JSON.stringify(rawData))
    .digest("hex");
}

// 安全封装网络请求,拦截非法域名、加密签名报文
async function secureBattleApiReq(botToken, path, battleData) {
  const audit = require("./btg-battle-audit-risk");
  const targetUrl = new URL(path, `https://${ALLOW_HOST}`);
  // 拦截非官方域名访问
  if (targetUrl.hostname !== ALLOW_HOST) {
    audit.triggerRiskAlert("network_domain_inject", `机器人${botToken}尝试访问非法域名${targetUrl.hostname}`);
    throw new Error("禁止访问非BTG官方竞技域名");
  }
  const dataSign = signBattleData(botToken, battleData);
  const reqBody = { data: battleData, sign: dataSign };
  return new Promise((resolve, reject) => {
    const req = https.request({
      hostname: ALLOW_HOST,
      path: targetUrl.pathname,
      method: "POST",
      agent: TLS_AGENT,
      headers: {
        "Content-Type": "application/json",
        "X-Bot-Token": botToken,
        "X-Data-Sign": dataSign
      }
    }, res => {
      let buf = "";
      res.on("data", c => buf += c.toString());
      res.on("end", () => resolve(JSON.parse(buf)));
    });
    req.write(JSON.stringify(reqBody));
    req.end();
  });
}

module.exports = { secureBattleApiReq, signBattleData };

2. btg_runner 隔离进程资源池 btg-runner-process-pool.js

javascript

运行

const { spawn } = require("child_process");
const fs = require("fs");
const RUNNER_BIN = "./bin/btg_runner";
// 进程池限制配置
const MAX_RUNNER_POOL = 12;
const MAX_RUN_TIMEOUT = 120000; // 2分钟无响应强制销毁
const CPU_MEM_LIMIT_ENV = { MAX_CPU_USAGE: "70", MAX_MEM_MB: "2048" };
const runnerPool = new Map();

// 创建独立隔离runner进程,单机器人独占
async function createBotRunner(botId) {
  if (runnerPool.size >= MAX_RUNNER_POOL) throw new Error("BTG运行器进程池已达上限");
  if (runnerPool.has(botId)) return runnerPool.get(botId);
  const child = spawn(RUNNER_BIN, [], {
    env: { ...process.env, ...CPU_MEM_LIMIT_ENV },
    cwd: "./btg-sandbox/",
    shell: false
  });
  const runnerItem = { botId, child, alive: true };
  runnerPool.set(botId, runnerItem);
  // 超时强制销毁卡死进程
  const killTimer = setTimeout(() => {
    if (child.exitCode === null) {
      child.kill("SIGKILL");
      runnerItem.alive = false;
      require("./btg-battle-audit-risk").triggerRiskAlert("runner_timeout", `机器人${botId}运行器卡死,强制销毁`);
    }
  }, MAX_RUN_TIMEOUT);
  child.on("close", () => {
    clearTimeout(killTimer);
    runnerItem.alive = false;
    runnerPool.delete(botId);
  });
  return runnerItem;
}

// 向指定机器人runner发送对战指令
async function sendBattleCmdToRunner(botId, safeCmdParams) {
  const runner = runnerPool.get(botId);
  if (!runner || !runner.alive) {
    await createBotRunner(botId);
  }
  const targetRunner = runnerPool.get(botId);
  targetRunner.child.stdin.write(JSON.stringify(safeCmdParams) + "\n");
}

module.exports = { createBotRunner, sendBattleCmdToRunner, runnerPool };

3. 对战策略指令注入防护 btg-battle-sanitize-filter.js

javascript

运行

// 对战高危注入字符黑名单
const DANGER_CHAR_REG = /[`$&|;><\\\r\n]/g;
// 合法对战操作指令白名单,拦截篡改胜负、刷分指令
const ALLOW_BATTLE_CMD = ["unit_move", "skill_cast", "defend", "retreat", "match_accept"];

// 第一层:清洗注入高危字符
function sanitizeBattleInput(rawText) {
  return rawText.replace(DANGER_CHAR_REG, "");
}

// 第二层:校验对战指令合法性
function verifyBattleCmdLegal(cmdName) {
  return ALLOW_BATTLE_CMD.includes(cmdName);
}

// 三层防护封装,非法指令直接拦截并记录风险日志
function safeWrapBattleCommand(botId, cmdName, rawParams) {
  const audit = require("./btg-battle-audit-risk");
  const cleanParams = rawParams.map(item => sanitizeBattleInput(String(item)));
  if (!verifyBattleCmdLegal(cmdName)) {
    audit.triggerRiskAlert("battle_cmd_inject", `机器人${botId}执行非法对战指令:${cmdName},操作拦截`);
    throw new Error("检测到可疑注入对战指令,已拦截");
  }
  return { cmd: cmdName, params: cleanParams };
}

module.exports = { safeWrapBattleCommand, sanitizeBattleInput };

4. 排行榜对局哈希防篡改校验 btg-rank-data-verify.js

javascript

运行

const crypto = require("crypto");

// 本地生成对局完整校验哈希
function calcBattleRankHash(botId, battleId, winState, score, battleTime) {
  const rawStr = `${botId}|${battleId}|${winState}|${score}|${battleTime}`;
  return crypto.createHash("sha256").update(rawStr).digest("hex");
}

// 云端返回校验值与本地哈希比对,不一致判定伪造战绩
function verifyBattleRankIntegrity(localHash, cloudSign) {
  return localHash === cloudSign;
}

// 封装带哈希签名的榜单同步数据
function buildSafeRankPayload(botToken, botId, battleRecord) {
  const { battleId, winState, score, battleTime } = battleRecord;
  const recordHash = calcBattleRankHash(botId, battleId, winState, score, battleTime);
  return {
    record: battleRecord,
    local_hash: recordHash,
    sign: require("./btg-secure-network").signBattleData(botToken, battleRecord)
  };
}

module.exports = { calcBattleRankHash, verifyBattleRankIntegrity, buildSafeRankPayload };

5. 异步限流对战任务调度队列 btg-battle-task-queue.js

javascript

运行

const { safeWrapBattleCommand } = require("./btg-battle-sanitize-filter");
const { sendBattleCmdToRunner } = require("./btg-runner-process-pool");
const { secureBattleApiReq } = require("./btg-secure-network");
// 限流配置
const GLOBAL_MAX_CONCURRENT = 8;
const SINGLE_BOT_MAX_QPS = 3;
// 任务优先级:1单人竞技 / 0批量冲榜
const TASK_PRIORITY = { single: 1, batch: 0 };
let battleQueue = [];
let queueWorking = false;
const botRequestCounter = new Map();

// 单机器人QPS限流计数清理
function resetBotCounter() {
  setInterval(() => botRequestCounter.clear(), 60000);
}

// 对战任务入队,前置校验限流、指令安全
function enqueueBattleTask(taskRaw) {
  const { botId, cmdName, params, priority = TASK_PRIORITY.batch } = taskRaw;
  // 单机器人每分钟请求超限拦截
  const currentCount = botRequestCounter.get(botId) || 0;
  if (currentCount >= SINGLE_BOT_MAX_QPS) {
    return { code: 2, msg: `机器人${botId}请求频次超限,延后排队执行` };
  }
  botRequestCounter.set(botId, currentCount + 1);
  // 指令安全清洗校验
  const safeCmd = safeWrapBattleCommand(botId, cmdName, params);
  taskRaw.safeCmd = safeCmd;
  taskRaw.priority = priority;
  taskRaw.taskId = `btg_battle_${Date.now()}_${Math.random().toString(16).slice(2)}`;
  battleQueue.push(taskRaw);
  // 高优先级单人对局前置
  battleQueue.sort((a, b) => b.priority - a.priority);
  runBattleQueue();
  return { code: 0, taskId: taskRaw.taskId, msg: "对战任务进入调度队列" };
}

// 队列循环调度器,控制全局最大并发
async function runBattleQueue() {
  if (queueWorking || battleQueue.length === 0) return;
  queueWorking = true;
  let runningNum = 0;
  while (battleQueue.length > 0 && runningNum < GLOBAL_MAX_CONCURRENT) {
    runningNum++;
    const task = battleQueue.shift();
    try {
      await sendBattleCmdToRunner(task.botId, task.safeCmd);
      // 对局结束同步榜单
      if (task.syncRank) {
        const rankPayload = require("./btg-rank-data-verify").buildSafeRankPayload(task.botToken, task.botId, task.battleRecord);
        await secureBattleApiReq(task.botToken, "/rank/upload", rankPayload);
      }
    } catch (err) {
      // 失败对局存入持久恢复缓存
      require("./btg-battle-persist-recover").cacheUnfinishedBattle(task);
    } finally {
      runningNum--;
    }
  }
  queueWorking = false;
}

resetBotCounter();
module.exports = { enqueueBattleTask };

6. 对局预写日志持久断点续赛 btg-battle-persist-recover.js

javascript

运行

const fsPromises = require("fs/promises");
const BATTLE_WAL_PATH = "./btg/battle-wal.log";
const UNFINISHED_CACHE_PATH = "./btg/unfinished-battle-cache.json";
let unfinishedBattleCache = [];

// 初始化加载未完成对局,自动恢复续赛
async function initBattleRecoverCache() {
  try {
    const raw = await fsPromises.readFile(UNFINISHED_CACHE_PATH, "utf8");
    unfinishedBattleCache = JSON.parse(raw);
    unfinishedBattleCache.forEach(task => require("./btg-battle-task-queue").enqueueBattleTask(task));
    unfinishedBattleCache = [];
    await flushCache();
  } catch { unfinishedBattleCache = []; }
}

// 对局过程分段写入预写日志
async function writeBattleWAL(botId, taskId, battleStepData) {
  const logLine = `[${new Date().toISOString()}] bot:${botId} task:${taskId} step_data:${JSON.stringify(battleStepData)}\n`;
  await fsPromises.appendFile(BATTLE_WAL_PATH, logLine);
}

// 中断对局持久缓存,重启断点续赛
async function cacheUnfinishedBattle(task) {
  unfinishedBattleCache.push(task);
  await flushCache();
}

async function flushCache() {
  await fsPromises.writeFile(UNFINISHED_CACHE_PATH, JSON.stringify(unfinishedBattleCache, null, 2));
}

initBattleRecoverCache();
module.exports = { writeBattleWAL, cacheUnfinishedBattle };

7. 对战行为风控审计告警 btg-battle-audit-risk.js

javascript

运行

const fs = require("fs");
const AUDIT_LOG = "./btg/battle-operation-audit.log";
const RISK_ALERT_LOG = "./btg/risk-warning.log";

// 完整对战操作审计记录
function writeBattleAudit(botId, taskId, cmd, battleRecord = {}) {
  const line = `[${new Date().toISOString()}] bot:${botId} task:${taskId} cmd:${cmd} record:${JSON.stringify(battleRecord)}\n`;
  fs.appendFileSync(AUDIT_LOG, line);
}

// 通信、注入、高频刷分风险统一告警
function triggerRiskAlert(riskType, desc) {
  const alertLine = `[BTG竞技风险告警][${new Date().toISOString()}] type:${riskType} desc:${desc}\n`;
  fs.appendFileSync(RISK_ALERT_LOG, alertLine);
  console.warn("BTG风险:", alertLine);
}

module.exports = { writeBattleAudit, triggerRiskAlert };

五、改造前后全方位对比表格

表格

对比维度原版 BTG v1.0.3二次重构优化版
网络通信安全无域名限制、无 TLS 校验,明文传输易劫持篡改积分仅放行官方域名,TLS1.3 双向证书,报文 HMAC 签名,拦截中间人伪造榜单
btg_runner 进程调度单全局进程,多机器人资源抢占,卡死全部对局独立隔离进程池,CPU / 内存硬限制,单 runner 崩溃不影响其他机器人
对战指令安全防护直接传入原始策略,注入可篡改胜负刷分高危字符清洗 + 指令白名单 + 沙箱传参三层拦截,杜绝作弊注入
排行榜数据防作弊无哈希校验,本地伪造战绩可直接上传云端对局 SHA256 双层哈希校验,伪造战绩同步直接被平台拦截
API 请求限流风控无并发限制,批量冲榜极易封禁机器人 token单人 / 全局双维度限流队列,区分单人 / 批量任务优先级,自动消峰
对局数据容错能力仅内存存储,崩溃 / 断网对局全部丢失分段预写日志持久化,未完成对局缓存,服务重启断点续赛
运维作弊溯源能力极简日志,刷分、账号封禁无法定位源头全链路对战操作完整审计,高频请求、注入攻击实时风险告警,作弊可精准溯源

六、插件完整升级部署操作步骤

  1. 备份 BTG 原版 btg_runner 程序、对战技能源码、对局本地存档、网络通信配置文件,留存完整回滚包;
  2. 新建 7 个核心改造 JS 模块,完整粘贴全部优化代码;
  3. 插件启动入口执行 runner 进程池初始化、未完成对局缓存恢复、网络 TLS 代理初始化、限流计数器定时器启动;
  4. 接入 OpenClaw 竞技调度模块,完全兼容原版 btg_runner 调用逻辑、beforethoughtgame.com通信接口、机器人对战技能,上层业务无需修改;
  5. 全场景功能安全验证:注入非法对战指令拦截、访问外部域名阻断、多机器人并发对战资源隔离、伪造榜单数据校验失败、高频冲榜自动限流、runner 卡死自动销毁、重启恢复未完成对局、风险告警日志输出;
  6. 长期批量机器人自动冲榜压力测试,验证无通信劫持、无刷分作弊漏洞、无 API 账号封禁、无对局战绩丢失、进程稳定无内存溢出,改造部署完成。

七、改造方案总结

BTG v1.0.3 作为竞技游戏专用 AI 对战插件,原生仅实现 runner 启动与基础网络通信,在网络防劫持、进程资源隔离、对战指令防注入、榜单防作弊、API 限流、对局容错、作弊溯源七大运营核心场景存在明显短板,批量机器人自动化冲榜场景下极易出现账号封禁、积分篡改、对局丢失等线上故障。本次全套二次改造完全保留插件本地 runner、对接官方竞技平台、机器人自动对战冲榜全部原有功能,从加密通信、隔离进程池、指令注入防护、哈希防篡改榜单、限流任务队列、对局持久恢复、风控审计底层全模块重构升级。改造后插件具备通信防劫持、多机器人稳定并发、竞技防作弊、API 请求可控、对局数据不丢失、作弊行为可溯源六大工业级能力,适配大批量 AI 机器人自动化竞技冲榜、长期赛事自动匹配生产运营场景。