本帖最后由 ustc_zzzz 于 2018-3-10 03:08 编辑 
大家好我是萌新
原作者:@ustc_zzzz。
感谢 @玄素 在测试过程中提供的帮助。
本文应该基于所有包含有/testfor系列指令的MC版本,当然1.13就没有了。
起
这件事的发现原因极其无聊,无聊到没人想听的,在此略过不提,直接上正文。
CBer都知道包括但不限于/testfor等指令会匹配一个实体或者物品或者什么的NBT,这种匹配绝大多数情况我们都是清楚的:
好,盲生,你发现了华点,我们试一试。
以下所有测试的最初版本由玄素完成,毕竟你们这些CBer比我有经验得多。
我们先召唤一个物品,它的NBT标签由a、b、c三个字符串组成:
复制代码
然后我们匹配一下这个物品的NBT标签:
复制代码
成功匹配到这个物品了,这说明两个列表完全相同的时候是可以匹配的。
是时候展开更多测试了。
承
我们开始进行更多的测试。
复制代码
以上两个测试成功了,说明列表的匹配是无序的。
复制代码
以上两个测试也成功了,说明列表的匹配是局域的,只要有元素匹配到了就行。
复制代码
以上两个测试失败了,这很正常,毕竟也没d和e两个字符串。
我们好像能摸清一些套路了,我们只要把列表看成一个集合,然后把命令里的a列表匹配游戏元素b列表的条件看成a是b的子集就行了。
但是事实果真如此吗?
转
我们拿一个空列表去匹配:
复制代码
我们惊奇地发现,没有匹配。
然后如果我们用这样的东西去匹配呢?
复制代码
待匹配的物品里只有一个a和一个b,多个a和多个b居然匹配成功了。
这些奇怪的现象已经超出我们常理认知了。
是时候翻代码了(相关方法:net.minecraft.nbt.NBTUtil#areNBTEquals)。
合
经过一些你们也不会愿意看的翻代码过程,我们可以总结出两个列表的匹配规则:
以上规则只对较为复杂的列表成立,作为基本元素的Byte、Int、Long这三种列表要想匹配还是需要列表完全相同且一一有序对应的。
为什么规则这么诡异?因为MJSB就是这么写的。
今天在游戏技巧版块灌水的全部内容就到这里,谢谢大家。
大家好我是萌新
原作者:@ustc_zzzz。
感谢 @玄素 在测试过程中提供的帮助。
本文应该基于所有包含有/testfor系列指令的MC版本,当然1.13就没有了。
起
这件事的发现原因极其无聊,无聊到没人想听的,在此略过不提,直接上正文。
CBer都知道包括但不限于/testfor等指令会匹配一个实体或者物品或者什么的NBT,这种匹配绝大多数情况我们都是清楚的:
- 对于数字、字符串等基本类型,匹配的条件是完全相等。
- 对于复合(Compound)类型,命令里的a匹配游戏元素b的条件是a提供的所有子键b都匹配,比如说{a:b,c:d}匹配{a:b,c:d,e:f}什么的。
 
那等等,对于列表呢?
好,盲生,你发现了华点,我们试一试。
以下所有测试的最初版本由玄素完成,毕竟你们这些CBer比我有经验得多。
我们先召唤一个物品,它的NBT标签由a、b、c三个字符串组成:
- /summon minecraft:item ~ ~ ~ {Item:{tag:{Test:[a,b,c]},id:"minecraft:stick",Count:1},PickupDelay:32767}
然后我们匹配一下这个物品的NBT标签:
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[a,b,c]}}}
成功匹配到这个物品了,这说明两个列表完全相同的时候是可以匹配的。
是时候展开更多测试了。
承
我们开始进行更多的测试。
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[b,c,a]}}}
 
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[c,a,b]}}}
以上两个测试成功了,说明列表的匹配是无序的。
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[b,c]}}}
 
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[c]}}}
以上两个测试也成功了,说明列表的匹配是局域的,只要有元素匹配到了就行。
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[b,c,d]}}}
 
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[a,c,e]}}}
以上两个测试失败了,这很正常,毕竟也没d和e两个字符串。
我们好像能摸清一些套路了,我们只要把列表看成一个集合,然后把命令里的a列表匹配游戏元素b列表的条件看成a是b的子集就行了。
但是事实果真如此吗?
转
我们拿一个空列表去匹配:
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[]}}}
我们惊奇地发现,没有匹配。
然后如果我们用这样的东西去匹配呢?
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[a,a]}}}
 
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[a,a,a]}}}
 
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[a,a,a,a]}}}
 
- /testfor @e[type=item,c=1] {Item:{tag:{Test:[a,b,a,b,a]}}}
待匹配的物品里只有一个a和一个b,多个a和多个b居然匹配成功了。
这些奇怪的现象已经超出我们常理认知了。
是时候翻代码了(相关方法:net.minecraft.nbt.NBTUtil#areNBTEquals)。
合
经过一些你们也不会愿意看的翻代码过程,我们可以总结出两个列表的匹配规则:
命令里的a列表匹配游戏元素b列表的条件是:把a的所有元素拿去和b的元素匹配,只要b中存在元素匹配则称a中的该元素匹配成功,如果a中的所有元素都匹配成功了,那么则称a匹配b。当然有一种例外:如果a列表为空,那么只有b列表为空时才能匹配成功。
以上规则只对较为复杂的列表成立,作为基本元素的Byte、Int、Long这三种列表要想匹配还是需要列表完全相同且一一有序对应的。
为什么规则这么诡异?因为MJSB就是这么写的。
今天在游戏技巧版块灌水的全部内容就到这里,谢谢大家。
 本帖最后由 pca006132 于 2018-3-10 10:12 编辑 
emmm...其实命令进阶有写的
//这就很尴尬了
emmm...其实命令进阶有写的
[NBT及结构]
...
检测的时候不会循序检测,只会看看目标列表里有没有这几个标签,不论次序。
简单来说就是你无法控制次序
...
直接检查[]会检查该列表是否一个空的列表。
[基本类型]
...
而数组则是检查整个数组看看是否符合指定要求,检查包括该标签所在位置、顺序等等。
//这就很尴尬了
pca006132 发表于 2018-3-10 10:09
emmm...其实命令进阶有写的
你没有讨论拿[a,a]这种情况匹配的结果,所以我不算完全火星,哼