LiteLDev / LeviLamina

A lightweight, modular and versatile mod loader for Minecraft Bedrock Edition, formerly known as LiteLoaderBDS
https://levimc.org/software/levilamina
GNU Lesser General Public License v3.0
1.14k stars 117 forks source link

给事件系统监听器分发添加权重 #1381

Closed twoone-3 closed 1 year ago

twoone-3 commented 2 years ago

异常模块

ScriptEngine(脚本引擎)

操作系统

Windows 11

LiteLoader版本

2.5.1

BDS版本

1.1.9.20

发生了什么?

LL控制台chat输出即使拦截了也输出

复现此问题的步骤

// 单次聊天时间限制(毫秒)
const wait_time = 1000;

mc.listen('onChat', function (player, msg) {
    if (player.getExtraData('in_chat_limit') == 1) {
        player.tell('You are too fast, please wait.');
        return false;
    }
    if (msg.length > 100) {
        player.tell('Your message is too long.');
        return false;
    }
    player.setExtraData('in_chat_limit', true);
    setTimeout(function () {
        player.setExtraData('in_chat_limit', false);
    }, wait_time);
    return true;
})

在游戏很快打出多条消息

有关的日志/输出

18:34:42 INFO [Chat] <twoone3> bb
18:34:42 INFO [Chat] <twoone3> bb
18:34:42 INFO [Chat] <twoone3> bb
18:34:42 INFO [Chat] <twoone3> bb
18:34:42 INFO [Chat] <twoone3> bb
18:34:43 INFO [Chat] <twoone3> bb
18:34:43 INFO [Chat] <twoone3> bb
18:34:44 INFO [Chat] <twoone3> bb
18:34:44 INFO [Chat] <twoone3> bb

插件列表

none
yqs112358 commented 2 years ago
image

true != 1

twoone-3 commented 2 years ago

不是这个逻辑问题,游戏内拦截了,控制台还是输出,我觉得控制台的Chat提示要判断一下是否有插件拦截

yqs112358 commented 2 years ago

“控制台还是输出”这个指的是什么,LLSE的行为日志插件?还是什么别的东西输出的

Jasonzyt commented 2 years ago

但是true==1 is true,只有true===1 is false

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: YQ @.> 发送时间: 2022年8月14日 18:50 收件人: LiteLDev/LiteLoaderBDS @.> 抄送: Subscribed @.***> 主题: Re: [LiteLDev/LiteLoaderBDS] LL控制台chat输出即使拦截了也输出 (Issue LiteLDev/LiteLoader#6)

true != 1 — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>

twoone-3 commented 2 years ago

应该是行为日志吧,就是前面那个有关的日志/输出里面的

yqs112358 commented 2 years ago

这个是不是LL自带的控制台输出聊天消息的功能来着

twoone-3 commented 2 years ago

嗯,我就觉得如果呗脚本拦截了那就应该不输出

yqs112358 commented 2 years ago

是这样,这个跟事件系统的设计有关。LL的事件系统的设计是串行的,先listen的先获取到事件,处理完之后再往后传,因此如果某个插件拦截此事件,则其他引擎能不能获得此事件跟listen的顺序有关: 如果此插件注册Listen在发起拦截的插件之后,就获取不到此事件;如果此插件注册Listen在发起拦截的插件之前,就会获取到此事件

yqs112358 commented 2 years ago

这个也是所有事件分发系统不可避免的问题,Hook机制也有此问题,因为Hook也是串行的,之前写LLSE RPC的时候碰到很离谱的死锁情况就跟这个有关

twoone-3 commented 2 years ago

那有没有办法把那个控制台输出一直置于最后一个

yqs112358 commented 2 years ago

这个是不可解决的问题,就算把控制台输出这个功能放到最后一个了,也可能有其他插件在他前面注册(比如行为日志)然后输出到控制台。这个是实际意义的不可解,而不是因为写的不好或者什么别的

twoone-3 commented 2 years ago

那给事件系统加个权重呗

yqs112358 commented 2 years ago

后面有空考虑修改

Jasonzyt commented 2 years ago

这个是不可解决的问题,就算把控制台输出这个功能放到最后一个了,也可能有其他插件在他前面注册(比如行为日志)然后输出到控制台。这个是实际意义的不可解,而不是因为写的不好或者什么别的

其实可以加个拦截回调,重构Event的时候可以尝试

mc.listen("XX", (ev) => {
  ev.prevent();
  ev.onPrevented(() => {});
  ev.onExecuted(() => {});
});
Yushu2606 commented 2 years ago

个人认为一个插件理应不可以从底层影响另一个插件 否则等着冲突吧xwx

LazuliKao commented 2 years ago

其实可以增加一个listen重载,增加一个事件优先级参数,添加事件时自动按照优先级排序。 需要高优先级的拦截插件可以填0到1000,低优先级的日志类插件可以填1000到2000,类似这样

LazuliKao commented 2 years ago

执行同时执行事件回调时得按照最短路径,高优先级事件return false则不往下执行

twoone-3 commented 2 years ago

嗯我也是这么想的,这就是权重的思想

yqs112358 commented 2 years ago

哈哈,就怕这个 Screenshot_2022-08-22-10-43-02-358_com.zhihu.android.jpg

yqs112358 commented 2 years ago

最后是个插件都去申请高优先级,然后退化成原本的线性模型(乐)

Jasonzyt commented 2 years ago

不如给传event对象进去,提供方法让插件能知道何时被阻止

RimuruChan commented 2 years ago

我认为还是要提供优先级的,这个feature是有人需要的。 除了特殊情况一般不会有人故意抢占优先级。 优先级不用太多,可以采用数值并提供一定预设。