命令方块吧 关注:6,143贴子:69,109
  • 25回复贴,共1

【1.9】新的实体marker之王——AreaEffectCloud,AEC

只看楼主收藏回复

  大家好,我是秋一。这个帖子相信一些朋友在mcbbs看到过了。最近听说CB吧开始热闹起来,于是我想了想觉得可以搬点以前写过的东西过来,方便新人看看(//我才是新人好嘛)。
  本帖可能用到的一些前缀——
没有前缀默认是CCB, Chain Command Block
icb: 指该指令所在的CB是ICB, Impulse Command Block
rcb: 指该指令所在的CB是RCB, Repeating Command Block
cond: 指该指令所在的CCB是Conditional模式
init: 指该指令只会在OOC生成的时候执行一次(在pcb文档中使用,这里不作详细说明)
mark:name tag1 tag2 … tagn 指代下一个CB/其他方块有一个实体marker
AS ArmorStand,盔甲架
AEC AreaEffectCloud,滞留的区域效果云,俗称药水云
  本帖大致会分成以下几个部分,未完成前,请勿插楼,谢谢√
 1. 什么是Marker,为什么要用Marker
 2. 实体充当Marker应该满足的要求
 3. AEC相比于AS的一些优点和缺点
 4. 应用举例


IP属地:广西1楼2016-02-22 13:51回复
    2楼用作补充吧


    IP属地:广西2楼2016-02-22 13:51
    回复
      1. 什么是Marker,为什么要用Marker?
        Marker是Minecraft当中用于标记和定位某些方块的实体。在CB电路中,我们常常会把一些功能单元单独存放,在使用的时候去调用他们。
      //调用功能单元的一种办法是
        /blockdata x y z {auto:1}
      //这个以以任意形式调用,不局限于聊天窗,CB,牌子等
        上述指令中,x y z指的是该功能单元的起始CB,通常,功能单元以这样的形式起始:
      icb:blockdata ~ ~ ~ {auto:0}
        可以看到,调用该功能单元的时候出现了x y z,即绝对坐标。这个编写习惯对于初学者来说虽然很简单,但是它存在一个巨大的问题,一旦该功能单元移植到其他地方,调用的指令就需要作出相应的修改,在功能单元过多的时候,这是非常不利于后期debug的。
        如果,在该功能单元起始CB的地方,有一个名为module的实体Marker,那么调用指令会变成什么样呢?
        /execute @e[name=module] ~ ~ ~ blockdata ~ ~ ~ {auto:1}
        乍一看,这个指令长了一截,但实际上,却是对逻辑和思维的简化,因为即使移植到别的地方,也不需要修改调用指令。初学者在学习模块编写的时候,强烈建议使用这样的形式去调用功能单元。


      IP属地:广西3楼2016-02-22 14:00
      收起回复
        2. 实体充当Marker应该满足的要求
          前面说了,Marker的作用是标记和定位方块,那么它至少应该满足的条件是
         (1) 不会自然despawn;
         (2) 在没有人为干扰的前提下,不会改变自己的位置;
          因此,在1.8时代,AS完爆其他的实体,成为了Marker之王,当然,AS也由于可以用来做各种各样的模型而深受CBer们的喜爱。本帖不涉及AS模型,因此只讨论Marker方面的优劣。
          到了1.9时代,由于AEC的引入,AS的Marker之王地位开始受到撼动。但从1.8时代过来的CBer,甚至包括一些老手,并没有注意到AEC作为Marker的一些亮点。这也是我写这个帖子的目的,让更多的人了解AEC。


        IP属地:广西5楼2016-02-22 14:08
        回复
          3. AEC相比于AS的一些优点和缺点
            我们来看看AS作为Marker应当具有的基本NBT
          {Marker:1,NoGravity:1}
            在多数情况下,还需要有的NBT
          {Invisible:1,CustomName:"xxx",Tags:["tag1","tag2",...,"tagn"]}
            再看看AEC作为Marker应当具有的NBT
          {Duration:xxxx}
            在多数情况下,还需要有的NBT
          {CustomName:"xxx",Tags:["tag1","tag2",...,"tagn"]}
            为了满足Part 2中提到的两个基本要求,AS通常需要有{Marker:1,NoGravity:1}以防各种手贱敲掉/重力影响。
            这里重点说一下AEC。用summon指令生成出来的AEC,是半径=0,看不见,不会动的实体,但是如果不指定Duration的话,它就会在下一个游戏刻消失掉。
            在讲Duration之前,我们来讲讲另一个NBT,它就是Age。
            AEC是用于表征AEC存在了的时间的NBT。AEC生成之后,其Age就会随游戏刻增加,。
            Duration是定义AEC Marker能存在的时间的一个NBT,数据类型是TAG_int,最大值是2147483647,即2^31-1。
            当Age达到Duration的时候,AEC就会消失掉。默认生成的AEC是{Duration:0,Age:0},因此该AEC在下一游戏刻就会消失掉。
            于是,我们可以看到两个十分重要的用途。
           (1) 将AEC用于临时标记,可以省去清除AEC的工作;
           (2) 将AEC用于伪永久标记,可以节省相当相当多的系统资源;
            用途(1)在后面的例子里面会讲到,这里先讲用途(2)。
            伪永久标记是什么意思呢?前面说了,AEC是用时限的实体,当Age达到Duration的值以后就会消失,因此很多人认为AEC不适合用来充当Marker,但是经过研究,AEC仍然是适合充当实体Marker的。
            理由很简单。Duration最大值是2147483647,在最理想的情况下,1秒=20游戏刻,于是这个值换算成常用时间,就是3年4个月左右。
            那么问题来了,你们认为一个CB存档能在最理想的状态下连续运行这么久吗?
            而且,到那个时候,早就有可以取代AEC的marker了吧?或者说不定Mojang已经移除了CB……(笑)
            退一步讲,就算嫌麻烦一些,改成{Duration:2100000000},也是3年3个月……
            于是,AEC已经完全满足了作为实体Marker的条件。
            相比于AS,AEC没有渲染的模型,更加节省系统资源。在大型点阵系统里面,AEC绝对是不可替代的存在。而使用AS的话,即使是{Invisible:1},在gamemode 3也能看到,依旧会消耗资源去渲染模型。
            我曾经做过测试,在同一个点生成AS/AEC,AS只到500个左右就能把我从满帧卡掉到个位数,而AEC到了2万左右依然坚挺。分散布置点阵的话,10万能没有问题。@pca006132 的电脑可以作证。
            但是,AEC也正是由于没有渲染模型,不方便debug——即使是F3+B来看碰撞箱,也是不太方便的,这一点AS仍然具有相当的优势。


          IP属地:广西6楼2016-02-22 14:30
          回复
            4. 应用举例
            (1) AEC作为临时marker的应用之一:@r随机器
            例如,我需要设计一个受伤的时候有一定概率获得buff的功能
            首先需要个damageTaken的记分板
            init:scoreboard objectives add damageTaken stat.damageTaken 受伤
            然后是功能模块(不需要永久Marker标记)
            //生成临时aec
            rcb:execute @a[score_damageTaken_min=0] ~ ~ ~ summon AreaEffectCloud ~ ~ ~ {CustomName:"ramBuff",Tags:["buff1"]}
            execute @a[score_damageTaken_min=0] ~ ~ ~ summon AreaEffectCloud ~ ~ ~ {CustomName:"ramBuff",Tags:["buff2"]}
            execute @a[score_damageTaken_min=0] ~ ~ ~ summon AreaEffectCloud ~ ~ ~ {CustomName:"ramBuff",Tags:["buff3"]}
            execute @a[score_damageTaken_min=0] ~ ~ ~ execute @e[type=AreaEffectCloud,c=3] ~ ~ ~ summon AreaEffectCloud ~ ~ ~ {CustomName:"ramBuff"}
            //随机选取aec改名
            entitydata @r[type=AreaEffectCloud,name=ramBuff] {CustomName:"ramBuffSelect"}
            //枚举所有随机事件
            execute @e[type=AreaEffectCloud,name=ramBuffSelect,tag=buff1] ~ ~ ~ effect @a[score_damageTaken_min=0] speed 5 1
            execute @e[type=AreaEffectCloud,name=ramBuffSelect,tag=buff2] ~ ~ ~ effect @a[score_damageTaken_min=0] regeneration 5 1
            execute @e[type=AreaEffectCloud,name=ramBuffSelect,tag=buff3] ~ ~ ~ effect @a[score_damageTaken_min=0] resistance 5 1
            //重置记分板以完善系统
            scoreboard players reset @a[score_damageTaken_min=0] damageTaken
            稍微解释一下这个过程,首先,当人受伤以后(是要损血的),damageTaken这个记分板就会记录分数,于是就会被选择器选中
            在一个游戏刻内,依次生成6个名字为ramBuff的AEC,其中3个分别有不同的tag来区分随机事件,此外我还设定了3个额外的AEC来修改触发的概率(古典概型而已)
            选中其中一个,改个名,区分于其他的AEC
            再然后列举出所有的随机事件,来保证执行。
            最后重置掉记分板就可以了。


            IP属地:广西8楼2016-02-22 14:42
            收起回复
              4. 应用举例
              (2)点阵屏
              这个点阵屏的应用很多,例如当时pca做了一个函数画板,可以用来画一些函数的图像。
              点阵屏的制作非常非常简单,只需要一条指令:
              /fill x1 y1 z1 x2 y2 z2 command_block 0 replace {auto:1,Command:"summon AreaEffectCloud ~ ~ ~ {Duration:2100000000,CustomName:\"graphDisplay\"}"}
              然后就可以通过execute选取name=graphDisplay的AEC来做各种各样的事情……比如我做了个毫无技术含量的随机点阵,就不拿出来献丑了23333


              IP属地:广西9楼2016-02-22 14:48
              回复
                4. 应用举例
                (3) AEC时钟
                AEC由于拥有Age这一随游戏刻增加的NBT,因此可以用于制作时钟
                mark:noticeTimer
                //这里的mark前缀指代永久marker
                rcb:testfor @e[type=AreaEffectCloud,name=noticeTimer] {Age:1200}
                //时钟输出1
                cond:say 时间已过去1分钟
                //时钟2
                testfor @e[type=AreaEffectCloud,name=noticeTimer] {Age:1500}
                cond:say Sakalaka BOOOOOOOOOOM!
                //如果需要做成循环式,就加上下面一行
                cond:entitydata @[type=AreaEffectCloud,name=noticeTimer] {Age:0}
                但是有一个十分需要注意的问题,就是这样的时钟最好不要用于制作计数器,因为通过CB来生成的AEC有着1游戏刻的延时(即在刚生成的那个游戏刻是不会被探测到的)
                例如
                通过任意CB执行:/summon AreaEffectCloud ~ ~ ~ {Duration:10,CustomName:"pha"}
                rcb:testfor @e @[type=AreaEffectCloud,name=pha]
                cond:give @p stick 1 0
                当你激活上面那个summon指令以后,你会发现你只得到了9个stick
                但是,如果你是手动输入那条summon指令的话,就会给你10个
                具体原因,就扯到了更新延迟的问题上面了,具体可以看这个帖子:http://tieba.baidu.com/p/4126971513


                IP属地:广西10楼2016-02-22 15:03
                回复
                  时间关系,先举这么点例子吧√
                  欢迎各位指出文中的错误……
                  fin
                  by Civi


                  IP属地:广西11楼2016-02-22 15:04
                  回复
                    Interesting


                    IP属地:上海12楼2016-02-22 15:05
                    收起回复
                      AEC神教赛高【


                      IP属地:江苏13楼2016-02-22 16:06
                      回复
                        表示还在研究AEC中……
                        但是毕竟AEC要改变过去AS在众人眼里的地位,还有很长的一段路要走
                        (我估计至少得等国外的作品用AEC代替AS成为主流为止)


                        IP属地:浙江14楼2016-02-22 16:51
                        收起回复
                          aec在固定marker方面表现确实良好,然而在移动的情况下则有着挺大的问题。所以各位还是需要根据情况使用aec/as


                          来自Android客户端15楼2016-02-22 17:16
                          回复
                            pha好评√


                            IP属地:北京来自Android客户端16楼2016-02-22 20:14
                            回复


                              IP属地:北京17楼2016-02-27 17:49
                              回复