|
本帖最后由 夙S溯 于 2024-9-17 22:30 编辑 其实经常写sapi的会发现mojang给我们准备了很多事件,只要调用几个函数传个参数就可以在事件触发时将这些函数全部执行,怎么做的,subscribe内部是怎么写的呢(当然我不知道,我只是模仿一下)? 首先我们需要来看一下,什么是事件,通过观察,我们发现一个事件,他由触发条件,执行逻辑构成 首先我们来定义一个事件,比如实体攻击事件 const Event = { entityAttack:{} } 接着,就是处理触发条件,比如我们规定,只有特定实体攻击时,才会触发这个事件,那我们可以利用官方的entityHitEntity world.afterEvents.entityHitEntity.subscribe(arg=>{ //EntityProperties是允许触发该事件的实体 if(!(arg.damagingEntity.typeId in EntityProperties))return "trigger" }) 条件有了,可是如何触发呢,我们这个时候应该开始填充我们的entityAttack事件了 entityAttack:{ //定义订阅方法 subscribe:function(arg0){ Event.entityAttack.logic.push(arg0) }, //定义取消订阅方法 unsubscribe:function(arg0){ const logic = Event.entityAttack.logic logic.splice(logic.indexOf(arg0),1) }, //储存触发事件时执行的函数 logic:[] /*该事件的最终逻辑,我们定义为扣血,这里使用typescript声明一下arg0的类型 interface EntityAttack { damage:number, hit:Entity, damaging:Entity } 本身不属于js语法,上面的subscribe以及unsubscribe的类型应该为 function(arg0:EntityAttack):void 因为他们是要处理这个EntityAttack参数, */ execute:function(arg0){ const health = arg0.hit.getComponent('minecraft:health') health.setCurrentValue(health.currentValue - arg0.damage) } } //接下来我们再定义一个触发器,他会帮我们运行上面储存的函数和最终的逻辑,eventname是事件名,p是要处理的参数 function trigger(eventname,p){ const event = Event[eventname] //由于js的对象是按引用传递的,p直接传能会被修改掉 for(const logic of event.logic){ //观察mojang的代码可知,cancel属性被设置为true订阅的事件就会全部停止,这里模仿一下 if(p.cancel === true)return logic(p) } //待处理完之后执行最终的逻辑 event.execute(p) } 回到上面的entityHitEntity事件,将"trigger"换成 trigger('entityAttack',{ //这里在自定义时按需要填写 hit:arg.hitEntity, damaging:arg.damagingEntity, damage:EntityProperties[arg.damagingEntity.typeId].damage }) 然后,你就自定义好了一个事件,仿造这个例子,你可以尝试去创造更多的自定义事件以满足自己的需求,如果把官方事件还原了一遍的话,以后官方再改什么属性名,你就只需要把trigger参数里的改改就好,而无需动用查找加替换 |
提升卡
观察者