Mirence 发表于 2023-1-18 16:30:00

【麦仁丝课堂】第二期 在线序数统计系统3.1

本帖最后由 Mirence 于 2024-6-15 19:31 编辑

命令方块进阶教程之
在线序数统计系统3.1
导语:
    在线序数统计系统的功能是给予每一个在线的玩家一个数字,与玩家序数统计系统类似,也就是在每一个玩家上线后便给予其一个序数。如玩家小麦第一个进入了游戏,那么他的在线序数就为1,随后玩家小仁、小丝依次进入游戏,那么他们的在线序数分别为2和3,然后小仁又退出了游戏,于是小丝的玩家序数从3变为了2。在线序数统计系统能让每一个在线的玩家拥有不同的分数,有利于在游戏中跟踪和定位在线玩家,检测玩家时更加方便。
玩家序数统计系统的简要内容如下表:

难度★★★
主要指令/tag, /scoreboard, /execute
指令技巧无延否定,变量分数比较,删除下线玩家数据
用途服务器

玩家序数统计系统的主要流程如下图:



注:由于1.19版本对/execute指令进行了较大更新,现版本下该装置可以进行优化,难度大大降低,不过该教程的内容是在网易版更新1.19版本之前写的,所以该“在线序数统计系统3.1”未进行过优化。

正文:
    在线序数统计系统3.1分为两个部分:给予序数和调整序数。“给予序数”的部分可以说与上一期的玩家序数统计系统的内容完全相同。与其不同的是,在线序数统计系统还多了一个“调整序数”的部分,也就是当有玩家下线时,一些玩家的在线序数会发生变动(减小)。如果游戏有玩家数量上限的话,最高在线序数也不会超过这个上限。


第一部分:给予在线序数
    这部分内容与上一期内容相同,麦仁丝将直接照搬上期内容(有删减),如有需要可以前往上期看详细教程。
第一步:跟踪一个未被统计过的玩家
我们可以随机为一个未被统计过的玩家添加一个实体标签t1,用于跟踪这个玩家。
    我们可以将以下指令输入第一个“循环 开启”命令方块中(t2是已统计的玩家拥有的标签):
tag @r add t1第二步:给予跟踪的玩家在线序数
    首先,我们需要一个虚拟实体来记录当前玩家拥有的最高的序数。在给予序数之前,我们可以为虚拟实体e1在计分板se上的分数加1分,然后再将e1在se上的分数赋值给被跟踪玩家在计分板s1(在线序数计分板)上的分数。此时这个被跟踪玩家的在线序数就能比上一个玩家高1分了。
    我们可以将以下指令输入第二个“连锁 有条件”命令方块中:
scoreboard players add e1 se 1       我们可以将以下指令输入第三个“连锁 有条件”命令方块中:
scoreboard players operation @a s1 = e1 se第三步:取消跟踪玩家
    最后我们只要在给予被跟踪玩家一个表示已统计的标签t2,再去掉被跟踪玩家的跟踪标签t1,这一部分的命令就执行结束了。
    我们可以将以下指令写入第四个“连锁 有条件”命令方块中:
tag @a add t2      我们可以将以下指令写入第五个“连锁 有条件”命令方块中:
tag @a remove t1
第二部分:调整在线序数
    第一部分可以给予每一个上线玩家一个序数,而第二部分就是在有玩家下线时,删除下线玩家的在线序数记录,并调整先前比该下线玩家晚上线的玩家(即序数大于该玩家的在线序数)。
一、删除下线玩家数据*
    当一个在线玩家被给予在线序数后,他(她)除了拥有在s1上的分数外,还拥有已统计标签t2, 我们需要将下线玩家的这些数据都清除掉,因为待他(她)再次上线时,就要再重新给予其在线序数。
①删除下线玩家已统计标签t2
第一步:删除一切玩家的已统计标签
    我们可以将以下指令输入第一个“循环 开启”命令方块中:
tag * remove t2第二步:重新给予所有在线玩家已统计标签
    我们可以将以下指令输入第二个“连锁”命令方块中:
tag @a add t2②删除下线玩家在线序数
第一步:备份在线玩家的在线序数
    我们首先要备份在线玩家在s1中的分数到计分板s2中,以删除一切玩家在线序数后能够找回在线玩家的分数。我们可以令所有玩家在s1中的分数赋值给他们自己在s2上的分数。
    我们可以将以下指令输入第一个“循环 开启”命令方块中:(以下指令在1.19版本中已不适用)
execute @a ~~~ scoreboard players operation @s s2 = @s s1      1.19版本用以下指令来代替原指令:
execute as @a run scoreboard players operation @s s2 = @s s1第二步:删除一切玩家的在线序数
    我们可以将以下指令输入第二个“连锁”命令方块中:
scoreboard players reset * s1第三步:还原在线玩家的在线序数
    重置s1后,我们再将所有玩家在s2上备份的分数再赋值给他们在s1上的分数,这样s1上就只有在线玩家有分数了。
    我们可以将以下指令输入第三个“连锁”命令方块中:(以下指令在1.19版本中已不适用)
execute @a ~~~ scoreboard players operation @s s1 = @s s2       1. 19版本用以下指令代替原指令:
execute as @a run scoreboard players operation @s s1 = @s s2    这样我们就能够删除下线玩家的已统计标签和在线序数了。
*删除下线玩家数据:玩家在游戏中拥有的实体标签和计分板分数在玩家下线后会继续保留,玩家上线后仍然拥有原来的实体标签和计分板分数。由于没有关于下线玩家的目标选择器,所以无法直接删除下线玩家的实体标签和计分板分数,但仍然可以通过多个步骤去删除这些数据。
删除下线玩家的实体标签可以分为两步:删除一切参数的实体标签→给予在线玩家相同实体标签
删除下线玩家的计分板分数可以分为三步:备份在线玩家分数→重置一切参数的分数→还原在线玩家的分数
通过命令方块可以在一瞬间完成下线玩家数据的删除,并不会影响其他命令方块组工作。
关于“删除下线玩家”的教程将出现在以后的“命令方块技巧教程”中。
二、调整在线玩家的序数
    如果有一个玩家退出了游戏,那么他的在线序数会被清除,如果他(她)不是最后一个进入游戏的玩家,那么s1上的分数就会出现空缺,也就是“不连续”的。这时,我们只要将在线序数大于空缺分数的玩家的在线序数减1,并将最高序数(e1)也减1即可,s1就能再次“连续”起来。
第一步:创建e2遍历序数
    首先我们要知道这个空缺分数是多少,在3.0版本中,麦仁丝采用的是枚举*的方法,也就是创建一个1至玩家上限的循环数e2,而在3.1版本中,麦仁丝将它改进为1至最高序数(e1)的循环数,这样就可以无视游戏的玩家上限了,并且可以减短调整序数所用的时间。
第1步,持续为e2在se上的分数加1。
    我们可以将以下指令写入第一个“循环 开启”命令方块中:
scoreboard players add e2 se 1*枚举:列出所有的情况,依次对其进行检测。
第2步,比较e2与e1的分数, 这里麦仁丝采用作差法来比较e2与e1的大小*。当e2-e1≤0时,则e2≤e1,此时允许e2继续增大;当e2-e1>0时,则e2>e1,此时e2要重新调回1。这些运算将会在运算计分板sj上进行,并令n1为e2-e1的值。
    首先令n1=e2,我们可以将以下指令输入第二个“连锁”命令方块中:
scoreboard players operation n1 sj = e2 se    然后将n1减去e1,我们可以将以下指令输入第三个“连锁”命令方块中:
scoreboard players operation n1 sj -= e1 se      最后再检测n1是否大于0的,我们可以将以下指令输入第四个“连锁”命令方块中:
scoreboard players test n1 sj 0第3步,调回e2的分数
    若上个命令方块执行成功(n1>0),则将e2调整回1,我们可以将以下指令输入第五个“连锁 有条件”命令方块中:
scoreboard players set e2 se 1    于是e2会继续加1,大于e1后立又刻回到1,形成1~e1的循环数
*分数比较:由于暂时没有比较两个(虚拟)实体分数的指令,所以无法直接用指令比较两个分数的大小,但是我们可以用数学上的“作差法”来比较两个实体分数的大小,首先备份其中一个实体的分数,然后再把这个分数减去另一个实体的分数,得出的结果与0比较,即可判断两者的大小。
第二步:检测空缺分数(wf)
    如果没有玩家退出游戏,s1上的分数是连续的,由于e2在1~e1间循环,所以总会与一个玩家的在线序数相等。那么当没有任何一个玩家的在线序数等于e2时,则说明此刻s1中有空缺分数且空缺分数就等于e2,于是这时所有玩家的在线序数减去都e2后就都不会等于0。而scoreboard指令只能检测存在等于0的分数,而不能够检测不存在等于0的分数,这时就要用到命令方块的“否定”技巧*,由于需要尽快找出空缺分数,所以麦仁丝这里采用了“无延否定”。也就是当所有玩家的在线序数减去e1后,没有结果等于0的时,后续的命令方块才会继续执行。
    在e2加1后就可以直接开始检测空缺分数,因此我们可以继续接上命令方块组。
第1步,备份一次s1至s3,用于运算(减去e2)。
    我们可以将以下指令输入第六个“连锁”命令方块中:(以下指令在1.19版本中已不适用)
execute @a ~~~ scoreboard players operation @s s3 = @s s1      1.19版本中应用以下指令代替原指令:
execute as @a run scoreboard players operation @s s1 = @s s2第2步,将这些s3中备份的分数减去e2。
    我们可以将以下指令输入第七个“连锁”命令方块中:
scoreboard players operation @a s3 -= e2 se第3步,检测s3中是否存在0分。
    我们可以将以下指令输入第八个“连锁”命令方块中:
scoreboard players test @a s3 0 0第4步,采用“无延否定”,如果s3中存在0分(无空缺),那么将f1(无延否定虚拟实体,初始为0)在sf中的分数设置为1分;如果不存在0分(有空缺),则跳过。
    我们可以将以下指令输入第九个“连锁 有条件”命令方块中:
scoreboard players set f1 sf 1第5步,检测不存在0分,当f1为0时,则s3中不存在0分,s1有空缺。
    我们可以将以下指令输入第十个“连锁”命令方块中:
scoreboard players test f1 sf 0 0第三步:调整在线序数
1.调整在线玩家序数,找出需要调整的序数,若s3中不存在0分(f1=0),则说明有空缺,且空缺的分数就等于e2,玩家序数大于e2的就是空缺分数以后的序数,需要调整(减1),因为此时玩家在s3的分数就是由他们的玩家序数减去e2得到的,所以此时在s3中分数大于等于1的玩家就是需要被调整在线序数的玩家;若s3中存在0分(f1≠0), 则跳过。
      我们可以将以下指令输入第十一个“连锁 有条件”命令方块中:
scoreboard players remove @a s1 12.调整最高序数,玩家序数在空缺以上的玩家的在线序数都被减去1,所以最高序数e1自然也要减去一。
    我们可以将以下指令输入第十二个“连锁 有条件”命令方块中:
scoreboard players remove e1 se 1第四步:f1复位
    所有命令执行结束,无延否定虚拟实体f1重置为0,准备下一次“序数调整”。
    我们可以将以下指令输入第十三个“连锁”命令方块中:
scoreboard players set f1 sf 0*否定:指令的检测功能有时不能检测它的否定,如本教程中,“s3中有0分的否定”表示“s3中一个0分都没有”,/scoreboard指令只能够检测有0分,而不能检测无0分。但仍然可以通过红石和命令方块来检测反面条件。麦仁丝将这种方法称为“否定”,通过红石否定会有一定的延迟,而通过多加两个命令方块来否定是没有延迟的,麦仁丝将其称为“无延否定”,简称写为“wf”,一般对低延迟要求较高的装置中适合使用“无延否定”来否定。
    (1.19版本更新/execute指令后,其条件子命令中自带否定执行功能,所以现在已经不需要这么做了)。

    当有玩家退出游戏后,空缺的在线序数会被大于这个序数的玩家向下给补上,最高序数减1。于是便实现了在线玩家序数的统计。


在线序数统计系统3.1 思维导图:



在线序数统计系统3.1 指令内容汇总:

1tag @r add t1   循环 开启
2scoreboard players add e1 se 1   连锁 有条件
3scoreboard players operation @a s1 = e1 se    连锁 有条件
4tag @a add t2   连锁 有条件
5tag @a remove t1   连锁 有条件
6tag * remove t2   循环 开启
7tag @a add t2   连锁
8execute @a ~~~ scoreboard players operation @s s2 = @s s1   循环 开启
9scoreboard players reset * s1   连锁
10 execute @a ~~~ scoreboard players operation @s s1 = @s s2   连锁
11 scoreboard players add e2 se 1   循环 开启
12 scoreboard players operation n1 sj = e2 se   连锁
13 scoreboard players operation n1 sj -= e1 se   连锁
14 scoreboard players test n1 sj 0   连锁
15 scoreboard players set e2 se 1   连锁 有条件
16 execute @a ~~~ scoreboard players operation @s s3 = @s s1   连锁
17 scoreboard players operation @a s3 -= e2 se   连锁
18 scoreboard players test @a s3 0 0   连锁
19 scoreboard players set f1 sf 1   连锁 有条件
20 scoreboard players test f1 sf 0 0   连锁
21 scoreboard players remove @a s1 1   连锁 有条件
22 scoreboard players remove e1 se 1   连锁 有条件
23 scoreboard players set f1 sf 0   连锁


在线序数统计系统3.1 事物名称汇总:

计分板:3个
s1:在线序数计分板
s2:s1清除下线玩家备份
s3:s1运算备份(@a:s1-e2:se)
se:虚拟实体计分板
sj:运算计分板
sf:无延否定计分板
实体标签:2个
t1:已统计玩家(清楚下线)
t2:用于跟踪未统计玩家
虚拟实体:
e1:最高序数
e2:1~e1循环数
n1:e2-e1的值,用于比较
f1:0:有空缺;1:无空缺

创作时间:2022.7.27




      那么,本期的教程就到这里啦。如若教程中有错误或者可以改善的地方,欢迎大家积极指正,感谢大家的支持!!!

(本期教程最早于2021年8月11日发布于网易我的世界论坛,现麦仁丝已转驻苦力怕论坛,将停止在网易我的世界论坛上的发布教程)

点此前往 麦仁丝课堂 目录

点此前往 命令方块进阶教程 食用指南


(本期教程无视频版)

在线序数统计系统 版本更新日志:
1.0 命令方块繁多,上线至下线期间在线序数不改变,上线玩家会重新补上最小的空缺分数。
2.0 减少命令方块数量,改变序数给予方式,在线序数在有玩家下线后会被调整,但受游戏玩家上线限制;
3.0 大大减少命令方块数量,改善在线序数调整方式,采用枚举算法检测空缺分数,延迟略微加长,受游戏玩家上限限制。
3.1 枚举范围受玩家数量而变动(1~玩家数),不再受游戏玩家上限限制。
3.1plus 利用新版/execute指令大大减少命令方块数量,难度下降。
4.0 采用全新解析算法大大提高效率,实现瞬间定位空缺分数,没有延迟,并混合原有的枚举算法避免出现bug。




Mirence 发表于 2023-2-11 21:05:36

在线序数统计系统4.0 预告

本帖最后由 Mirence 于 2024-6-14 16:00 编辑

      利用1.19版本更新的新版/execute指令,该装置的“调整序数”部分可以大大简化,从原来的13个命令方块简化到只需要4个命令方块!
      请期待未来的 在线序数统计系统3.1 pro。[哔哩_呲牙]

冰冰冰 发表于 2023-1-18 17:07:35

太厉害了[哔哩_脱单]

zhizhuzhu1231 发表于 2023-1-18 17:20:46

虽然看不懂但是我还是要看,大佬真厉害[哔哩_脱单]

Gfunhud 发表于 2023-2-14 13:57:45

懂了,可惜不开服务器(悲
页: [1]
查看完整版本: 【麦仁丝课堂】第二期 在线序数统计系统3.1