因为服务器有几个大户家里的机器过多,导致他们家区块被加载的时候服务器的TPS经常下降得很大,影响了正常玩家的游戏体验,故群里有人提议加个投票重启mod。 而MC1.12.2并没有能够这样做的mod,于是我拿命令方块撸了一个,用着还可以。
基本原理
由重启提出者按按钮触发投票,创建一个类型为trigger的计分项目,并给玩家修改的权限。 通过/tellraw给玩家创建可以修改这个trigger的clickevent(同意为1,反对为0)。 规定时间后将所有玩家的分数集中到一个虚拟实体上,检查这个虚拟实体的分数,根据分数是多少来决定下一步动作。如需要全体成员都同意(即分数都为1)则将所有人分数相乘,全部同意的情况下积为1,此时的操作就是进行重启准备,只要有人反对(即分数为0)最终的积就会为0,此时不会进行重启。如需要半数成员同意,则将所有人分数相加,将和与0做比较,大于0的重启,小于等于0的不重启。 执行/stop的命令方块,使用活塞短脉冲发生器产生0.5红时刻的脉冲,防止重启后命令方块依旧被激活。 通过漏斗计时器来进行时间限制。
详细命令
//在用户触发地
/scoreboard players tag @p add applicant //给触发申请的人单独上tag以免@p圈错人
/setblock x y z redstone_torch //每一个红石火把的放置都是为了触发下一个电路
//在x y z处
/tellraw @a ["",{"text":"================================\n","color":"yellow"},{"text":"【公告】","color":"light_purple","bold":true},{"text":"玩家","color":"none","bold":false},{"text":"@","color":"gold","bold":true},{"selector":"@p[tag=applicant]","color":"gold","bold":true},{"text":"提出重启服务器,请投票\n","color":"none","bold":false},{"text":"请于30秒内做出选择,弃权视为反对\n","color":"none"},{"text":"【支持重启】","color":"dark_green","bold":true,"underlined":true,"clickEvent":{"action":"run_command","value":"/trigger reboot set 1"}},{"text":" ","color":"none","bold":false,"underlined":false},{"text":"【反对重启】","color":"dark_red","bold":true,"underlined":true,"clickEvent":{"action":"run_command","value":"/trigger reboot set 0"}},{"text":"\n================================","color":"yellow","bold":false,"underlined":false}]
/scoreboard objectives add reboot trigger 重启支持情况
/scoreboard players set @a reboot 0 //默认=反对
/scoreboard players enable @a reboot //允许修改
/setblock x1 y1 z1 minecraft:redstone_torch
/scoreboard objectives setdisplay sidebar reboot
/scoreboard players tag @a[tag=applicant] remove applicant
//在漏斗计时器后
/scoreboard players set #final_reboot reboot 1
/scoreboard players operation #final_reboot reboot *= @a reboot //将所有玩家的分数乘到#final_reboot上
/scoreboard players test #final_reboot reboot 1 1 //判断#final_reboot的分数是否在1到1之间
/setblock x2 y2 z2 redstone_torch //条件制约的连锁命令方块,只有上面的判断通过才会触发此命令方块重启,不通过则无提示,也可以用比较器接个非门提示重启不通过。此命令方块同时激活一个漏斗计时器
/scoreboard objectives remove reboot //删除投票用的计分项。由于是否重启都需要进行这步操作,我选择将此脉冲命令方块单独接在上一个漏斗计时器上
//在x2 y2 z2处
/tellraw @a ["",{"text":"==================================\n","color":"yellow"},{"text":"【公告】","color":"light_purple","bold":true},{"text":"服务器将在30秒后重启,请做好准备","color":"none","bold":false},{"text":"\n==================================","color":"yellow"}]
//在漏斗计时器后
/stop //前接活塞短脉冲发生器
注释:
命令方块种类:
每段电路的起始命令方块都是【红石控制,不受制约】的脉冲命令方块;所有它们后面的电路都是【保持开启,条件制约】的连锁命令方块。
活塞短脉冲发生器:
漏斗计时器:
漏斗中的物品数量×2÷2.5=计时器的秒数
红石火把的好处:
因为使用比较器时,直到下一次命令执行失败之前,比较器会一直保持输出状态,而不是形成脉冲。故采用能被活塞推掉的红石火把,当被放置时延迟触发活塞推掉红石火把。
关于防误触:
防误触指的是防止前一个人的重启申请处理完毕前有第二个人按下提出重启的按钮。/setblock未加参数时,会先检查目标处的方块和命令里指定的方块是否一样,如果一样就会跳过,所以只需要在第一个红石火把处接一个时间足够长的延迟启动活塞即可阻止这段延时内命令方块被再次激活,但此延迟不得大于计算电路前的漏斗计时器和重启电路前的漏斗计时器的计时长度之和。