开启辅助访问     
收藏本站

站内搜索

搜索

Minecraft(我的世界)苦力怕论坛

[JE教程] 【1.19Modding】如何利用事件系统检测玩家附近的所有物品

 发表于 2022-7-19 14:31:28|显示全部楼层|阅读模式 IP:浙江省
本帖最后由 Wu_tian 于 2022-7-19 14:49 编辑

Hello,我是Wu_tian,最近在尝试制作某个特定物品经过一定时间被腐蚀的功能。其中被一个功能卡壳了很久,也就是获取世界上的物品实体并且给他们修改数值。因此我打算把我此次的经验分享给大家
“在我的世界模组开发的过程中,时常要体验戴着脚镣跳舞的感觉”
一开始我在研究模组时,是因为指令的某些局限性限制了一些想法的发挥(更多体现在计算和穷举上面)。所以一开始我是从事件系统下手,看卡能不能找到“每一刻的实体”的事件,从EntityEvent下手找了半天,发现根本没有,做多也只找到了两个跟ItemEntity有关的事件:image.png (其中第一个是ItemTossEvent,是当物品被玩家抛出时触发事件,第二个是ItemExpireEvent,顾名思义,也就是物品消失时触发的事件)
结果我愣是硬着头皮用ItemTossEvent来尝试获取物品

因为这个事件只会在被丢出来的时候触发一次,所以我要时刻获取这个物品,就必须手动循环,于是我用了while循环。
@SubscribeEvent
public static void ItemOnCorroding(ItemTossEvent event){    while(event.getEntity().isAlive())    {      ....    }}结果也毫不意外,我只要一丢出物品直接卡壳。
于是我想了另一种方法,也许开个多线程可以解决?
@SubscribeEvent
public static void ItemOnCorroding(ItemTossEvent event){   Thread thread = new Thread(new Runnable() {    @Override
    public void run() {
            while(event.getEntity().isAlive())            {            ....            }      
      }
  })  thread.start();}

这个方法也许可行,但是在实践后却仍然发现一些小问题,比如物品必须是丢出去的才会被检测到。还有就是这个isAlive()似乎有些问题,即使物品被捡了,甚至退出了这个世界,这个isAlive()的条件仍是true
正当我快绝望时,我突然想起了以前玩指令时的思路,如果我用指令来检测的话,那一定是用execute指令。
execute as @e[type=item] run ...
但是目前我没有任何方法直接获得这个物品,那不妨将上述的指令变形?
execute as @a at @s run execute as @e[type=item,distance=..100] run ...
通过这种方式,我们可以先找到玩家,再获取玩家附近所有的物品,就这样,我受到了启发,因为这个游戏确实是有“每Tick的玩家”的事件的。
于是我写了以下代码
@SubscribeEvent
public static void ItemOnCorroding(TickEvent.PlayerTickEvent event)
{
    Logger logger = LogUtils.getLogger();
    //nearby -100 - +100 itemEntity Corroding
    entities  = event.player.getLevel().getEntities(null,new AABB(event.player.getBlockX()-100,event.player.getBlockY()-100,event.player.getBlockZ()-100,event.player.getBlockX()+100,event.player.getBlockY()+100,event.player.getBlockZ()+100));
    entities.forEach((entity ->
    {
        if(entity instanceof ItemEntity && ! entity.getLevel().isClientSide())        {           ...        }
    }));
    //Replace Player Item
}
这里,我们先通过玩家每tick的事件时时获取一个玩家的信息,然后通过玩家我们可以获取这个世界和这个世界的实体。
但是获取实体需要一个必要条件,即一定的范围(AABB就是用来确定范围的,AABB具体就是如fill指令中2个对角的坐标所框出来的矩形范围)
我将玩家附近的范围框出来后,再通过instanceof确定实体是物品实体,并且信息是在服务端的,进一步执行接下来我要的内容。
这也便是我最后的解决方案

image.png
苦力怕论坛,感谢有您~

本版积分规则

本站
关于我们
联系我们
坛史纲要
官方
哔哩哔哩
技术博客
下载
网易版
安卓版
JAVA
反馈
意见建议
教程中心
更多
捐助本站
QQ群
QQ群

QQ群

访问手机版

访问手机版

手机版|小黑屋|系统状态|klpbbs.com

粤公网安备 44200002445329号 | 由 木韩网络 提供支持 | GMT+8, 2024-11-24 16:03

声明:本站与Mojang以及微软公司没有从属关系

Powered by Discuz! X3.4 粤ICP备2023071842号-3