LegacyScriptEngine icon indicating copy to clipboard operation
LegacyScriptEngine copied to clipboard

[Bug] mc.runcmdEx 执行部分命令时出现报错

Open zmsgsb opened this issue 5 months ago • 3 comments

Describe the bug

Image Image

注册真指令后,使用时抛出错误,时而报错,时而不报错,但是在这个插件刚写出来时使用时没有报错,在服务器运行一段时间后再次使用指令控制台出现错误,目前不清楚是跨插件调用时内存管理问题还是什么问题 这是被调用到的其他插件API的另一个插件:

B-FakePlayer.zip

To Reproduce

const { PAPI } = require('./GMLIB-LegacyRemoteCallApi/lib/BEPlaceholderAPI-JS'); // 导入PAPI
mc.listen("onServerStarted", () => {
    const listEx_command = mc.newCommand(`listex`, `列出在线玩家和假人`, PermType.Any);
    listEx_command.overload([]);
    listEx_command.setCallback((cmd, ori, out, res) => {
        try {
            const getFakePlayerInfo = (str) => {
                // 安全检查:确保插件存在且导出函数可用
                if (ll.hasExported("B-FakePlayer", "get_B_FakePlayerInfo")) {
                    const result = ll.imports("B-FakePlayer", "get_B_FakePlayerInfo")(str);

                    // 确保返回的是数组且长度足够
                    if (Array.isArray(result) && result.length >= 8) {
                        return result;
                    }
                }
                // 返回安全的默认值
                return [false];
            }

            const onlinePlayers = mc.getOnlinePlayers();
            // 安全处理:确保onlinePlayers是数组
            if (!Array.isArray(onlinePlayers)) {
                out.error("获取在线玩家列表失败");
                return;
            }

            // 分离真实玩家和假人
            const realPlayers = onlinePlayers.filter(p => p && !p.isSimulatedPlayer());
            const fakePlayers = onlinePlayers.filter(p => p && p.isSimulatedPlayer());

            // 获取玩家名称列表
            const realPlayerNames = realPlayers.map(p => p.realName || p.name || "未知玩家").join(', ');

            // 安全处理假人信息
            const fakePlayerEntries = fakePlayers.map(p => {
                try {
                    const info = getFakePlayerInfo(p.name);
                    // 检查是否有有效的假人信息
                    if (info[0] && info[7]) {
                        return `${p.name}(由${info[7]}创建)`;
                    }
                } catch (e) {
                    logger.error(`处理假人 ${p.name} 时出错: ${e}`);
                }
                return p.name; // 无创建者信息时只显示假人名称
            });

            const fakePlayerNames = fakePlayerEntries.join(', ');
            //const fakePlayerNames = fakePlayers.map(p => p.name).join(', ');

            const content =
                `目前有 ${onlinePlayers.length}/%server_max_players% 个玩家在线:\n` +
                `玩家 (${realPlayers.length} 个): ${realPlayerNames}\n` +
                `假人 (${fakePlayers.length} 个): ${fakePlayerNames}`;

            out.success(PAPI.translateString(content));
        } catch (e) {
            logger.error(`listex 命令执行出错: ${e}\n${e.stack}`);
            out.error("执行命令时发生错误,请查看服务器日志");
        }
    });
    listEx_command.setup();
})

已知代码中的ll.imports("B-FakePlayer", "get_B_FakePlayerInfo")(str) 传入的参数是字符串,返回的是一个数组(最多11个元素,最少1个元素,并且只有1个元素时这个元素是false)

Expected behavior

不报错

Screenshots

Image Image

Platform

win10

Version

1.3.4

Additional context

No response

zmsgsb avatar Jul 14 '25 11:07 zmsgsb

经过实际测试:似乎是 mc.runcmdEx(cmd) 的问题,在控制台中直接输入指令并回车一切正常没有报错,但是使用 mc.runcmdEx(cmd) 就会报错

Image

以上那段代码我主要用于给nodejs插件的机器人框架写群命令,比如群内发送查服会使用 mc.runcmdEx 执行一个控制台指令然后根据执行是否成功来给群内发送 output

zmsgsb avatar Jul 14 '25 11:07 zmsgsb

logger.warn(mc.runcmdEx("listex").success);
logger.warn(mc.runcmdEx("listex").output);
Image Image

由此可见直接控制台输入指令确实没问题,经过实际测试 mc.runcmd("listex") 也没问题,游戏内输入也没问题,只有使用 mc.runcmdEx 时有问题

zmsgsb avatar Jul 14 '25 11:07 zmsgsb

Image

重启服务器后又正常了,不知道怎么回事,运行一段时间再看看

zmsgsb avatar Jul 15 '25 00:07 zmsgsb