| 原理 其实主要原理就在下面三张图中:
 
  
  
  py脚本如下:
 
 原理上来讲很容易实现,所以本数据包主要内容体现在如何让计算保持一定精度,尤其是仅运用储存上限为2147483647的计分板运算| 复制代码import sys
import math
o = (0.5,4,-3.5)
p = (0.5,8,6.5)
g = -0.02
f = 0.08
t = 20
dx = p[0] - o[0]
dy = p[1] - o[1]
dz = p[2] - o[2]
x = f * dx / (1 - math.pow(1 - f, t))
y = (f * dy - g * t) / (1 - math.pow(1 - f, t)) + g / f - g
z = f * dz / (1 - math.pow(1 - f, t))
print ("{Motion:[", x, ",", y, ",", z, "]}")
 | 
 
 
 
 
 变量储存规则介绍变量规则,以免一会儿大家看混淆
 主要分为两类,常量和变量:
 常量如物理常量'g'和'f',以及常数-1、0、1、10……储存在计分板"con"中;
 变量主要是过程量'a'、'b'、'c'等等就不列举了。
 三维变量中ox、oy、oz和tx、ty、tz还有m0、m1、m2因为与实体NBT存储有关,另开了计分板。
 
第一步:获取物理常量 (motionit:getparam)原理是穷举,用到了实体标签:
 例如tags/entity_types/mincart.json
 
 穷举的命令则是:| 复制代码{
    "replace": false,
    "values": [
        "minecraft:boat",
        "minecraft:minecart",
        "minecraft:tnt_minecart",
        "minecraft:chest_minecart",
        "minecraft:furnace_minecart",
        "minecraft:hopper_minecart",
        "minecraft:spawner_minecart",
        "minecraft:command_block_minecart"
    ]
}
 | 
 这里的'g'和'f'我们用一位整数替代两位小数。| 复制代码# boat & minecart : g = -0.04, f = 0.05
execute as @s[type=#motionit:minecart] run scoreboard players set g con -4
execute as @s[type=#motionit:minecart] run scoreboard players set f con 5
 | 
第二步:获取1-(1-f)^t (motionit:pow/x)原来想法是递归运算pow(),因为舍的位数太多,结果是运行不超过十次必得到0,因此舍弃了(仍保留在数据包中,函数为oppow.mcfunction和oppowc.mcfunction,毕竟方法是正确的)。
 后来果断穷举了,因为f的值是恒定的常数,所以分为0、1、2、5四种情况穷举,脚本如下:
 
 | 复制代码import sys
import math
f = 0.01
m = 0
ml = 0
tl = 0
for t in range(1000):
    m = int((1-pow((1-f),t))*10000)
    if m != ml or t == 999:
        if tl == t - 1 : print("execute as @s[scores={t=%s}] run scoreboard players set p con %s" %(tl, ml))
        else : print("execute as @s[scores={t=%s..%s}] run scoreboard players set p con %s" %(tl, t, ml))
        ml = m
        tl = t
 | 
第三步:计算坐标差 (motionit:relativeswitch、motionit:relativeconfirm)motionit:relativeswitch:
 
 先计算整数位的差值,根据差值的大小动态保留差值的位数,将差值限定到5位数(y=0是个特例)| 复制代码# distance rounding
execute store result score x1 var run data get entity @s Pos[0] 1000
execute store result score y1 var run data get entity @s Pos[1] 1000
execute store result score z1 var run data get entity @s Pos[2] 1000
scoreboard players operation @s m0 = @s tx
scoreboard players operation @s m1 = @s ty
scoreboard players operation @s m2 = @s tz
scoreboard players operation x2 var = @s tx
scoreboard players operation y2 var = @s ty
scoreboard players operation z2 var = @s tz
scoreboard players operation x2 var -= x1 var
scoreboard players operation y2 var -= y1 var
scoreboard players operation z2 var -= z1 var
scoreboard players operation x2 var /= 1000 con
scoreboard players operation y2 var /= 1000 con
scoreboard players operation z2 var /= 1000 con
scoreboard players operation x3 var = x2 var
scoreboard players operation y3 var = y2 var
scoreboard players operation z3 var = z2 var
execute if score x2 var < 0 con run scoreboard players operation x2 var *= neg con
execute if score y2 var < 0 con run scoreboard players operation y2 var *= neg con
execute if score z2 var < 0 con run scoreboard players operation z2 var *= neg con
# flexibly standardize decimal place format
#   calculate relatively to improve accuracy
execute if score x2 var >= 10000 con run scoreboard players operation @s m0 = x3 var
execute if score x2 var >= 1000 con if score x2 var < 10000 con run execute store result score x1 var run data get entity @s Pos[0] 10
execute if score x2 var >= 1000 con if score x2 var < 10000 con run scoreboard players operation @s m0 /= 100 con
execute if score x2 var >= 100 con if score x2 var < 1000 con run execute store result score x1 var run data get entity @s Pos[0] 100
execute if score x2 var >= 100 con if score x2 var < 1000 con run scoreboard players operation @s m0 /= 10 con
execute if score x2 var >= 10 con if score x2 var < 100 con run execute store result score x1 var run data get entity @s Pos[0] 1000
execute if score x2 var >= 1 con if score x2 var < 10 con run execute store result score x1 var run data get entity @s Pos[0] 10000
execute if score x2 var >= 1 con if score x2 var < 10 con run scoreboard players operation @s m0 *= 10 con
execute if score x2 var < 1 con run execute store result score x1 var run data get entity @s Pos[0] 100000
execute if score x2 var < 1 con run scoreboard players operation @s m0 *= 100 con
execute if score y2 var >= 10000 con run scoreboard players operation @s m1 = y3 var
execute if score y2 var >= 1000 con if score y2 var < 10000 con run execute store result score y1 var run data get entity @s Pos[1] 10
execute if score y2 var >= 1000 con if score y2 var < 10000 con run scoreboard players operation @s m1 /= 100 con
execute if score y2 var >= 100 con if score y2 var < 1000 con run execute store result score y1 var run data get entity @s Pos[1] 100
execute if score y2 var >= 100 con if score y2 var < 1000 con run scoreboard players operation @s m1 /= 10 con
execute if score y2 var >= 10 con if score y2 var < 100 con run execute store result score y1 var run data get entity @s Pos[1] 1000
execute if score y2 var >= 1 con if score y2 var < 10 con run execute store result score y1 var run data get entity @s Pos[1] 10000
execute if score y2 var >= 1 con if score y2 var < 10 con run scoreboard players operation @s m1 *= 10 con
execute if score y2 var < 1 con run execute store result score y1 var run data get entity @s Pos[1] 100000
execute if score y2 var < 1 con run scoreboard players operation @s m1 *= 100 con
execute if score z2 var >= 10000 con run scoreboard players operation @s m2 = z3 var
execute if score z2 var >= 1000 con if score z2 var < 10000 con run execute store result score z1 var run data get entity @s Pos[2] 10
execute if score z2 var >= 1000 con if score z2 var < 10000 con run scoreboard players operation @s m2 /= 100 con
execute if score z2 var >= 100 con if score z2 var < 1000 con run execute store result score z1 var run data get entity @s Pos[2] 100
execute if score z2 var >= 100 con if score z2 var < 1000 con run scoreboard players operation @s m2 /= 10 con
execute if score z2 var >= 10 con if score z2 var < 100 con run execute store result score z1 var run data get entity @s Pos[2] 1000
execute if score z2 var >= 1 con if score z2 var < 10 con run execute store result score z1 var run data get entity @s Pos[2] 10000
execute if score z2 var >= 1 con if score z2 var < 10 con run scoreboard players operation @s m2 *= 10 con
execute if score z2 var < 1 con run execute store result score z1 var run data get entity @s Pos[2] 100000
execute if score z2 var < 1 con run scoreboard players operation @s m2 *= 100 con
# get difference
scoreboard players operation @s m0 -= x1 var
scoreboard players operation @s m1 -= y1 var
scoreboard players operation @s m2 -= z1 var
#tellraw @a ["",{"text":"x2 = "},{"score":{"name":"x2","objective":"var"},"color":"red"},{"text":", y2 = "},{"score":{"name":"y2","objective":"var"},"color":"blue"},{"text":", z2 = "},{"score":{"name":"z2","objective":"var"},"color":"green"}]
#tellraw @a ["",{"text":"m0 = "},{"score":{"name":"@s","objective":"m0"},"color":"red"},{"text":", m1 = "},{"score":{"name":"@s","objective":"m1"},"color":"blue"},{"text":", m2 = "},{"score":{"name":"@s","objective":"m2"},"color":"green"}]
 | 
motionit:relativeconfirm:
 
 上标签,表示保留多少位,以便于后续的赋值处理。| 复制代码# mark decimal places
execute if score x2 var >= 10000 con run tag @s add acy0
execute if score x2 var >= 1000 con if score x2 var < 10000 con run tag @s add acx1
execute if score x2 var >= 100 con if score x2 var < 1000 con run tag @s add acx2
execute if score x2 var >= 10 con if score x2 var < 100 con run tag @s add acx3
execute if score x2 var >= 1 con if score x2 var < 10 con run tag @s add acx4
execute if score x2 var < 1 con run tag @s add acx5
execute if score y2 var >= 10000 con run tag @s add acy0
execute if score y2 var >= 1000 con if score y2 var < 10000 con run tag @s add acy1
execute if score y2 var >= 100 con if score y2 var < 1000 con run tag @s add acy2
execute if score y2 var >= 10 con if score y2 var < 100 con run tag @s add acy3
execute if score y2 var >= 1 con if score y2 var < 10 con run tag @s add acy4
execute if score y2 var > 0 con if score y2 var < 1 con run tag @s add acy5
execute if score y2 var = 0 con run tag @s add acy4
execute if score z2 var >= 10000 con run tag @s add acz0
execute if score z2 var >= 1000 con if score z2 var < 10000 con run tag @s add acz1
execute if score z2 var >= 100 con if score z2 var < 1000 con run tag @s add acz2
execute if score z2 var >= 10 con if score z2 var < 100 con run say 1
execute if score z2 var >= 10 con if score z2 var < 100 con run tag @s add acz3
execute if score z2 var >= 1 con if score z2 var < 10 con run tag @s add acz4
execute if score z2 var < 1 con run tag @s add acz5
 | 
水平方向 (motionit:opx、motionit:opz)以opx为例:
 
 可以说就是把图中公式用四则运算表示了一遍。| 复制代码# f * m0 / p
scoreboard players operation a var = f con
scoreboard players operation a var *= 1000 con
tellraw @a ["",{"text":"p = "},{"score":{"name":"p","objective":"con"},"color":"yellow"}]
tellraw @a ["",{"text":"m0 = "},{"score":{"name":"a","objective":"var"},"color":"yellow"}]
scoreboard players operation a var *= @s m0
scoreboard players operation a var /= p con
scoreboard players operation @s m0 = a var
#tellraw @a ["",{"text":"m0 = "},{"score":{"name":"a","objective":"var"},"color":"yellow"}]
 | 
竖直方向(motionit:opy)
 除了表示公式外,还要协调位数,所以竖直方向处理更特殊,这边我就不解释怎么协调得了,看看就行。| 复制代码# f * m1 - g * t / p
scoreboard players operation a var = f con
scoreboard players operation a var *= @s m1
scoreboard players operation b var = g con
scoreboard players operation b var *= @s t
execute if score y2 var >= 1000 con if score y2 var < 10000 con run scoreboard players operation b var *= 10 con
execute if score y2 var >= 100 con if score y2 var < 1000 con run scoreboard players operation b var *= 100 con
execute if score y2 var >= 10 con if score y2 var < 100 con run scoreboard players operation b var *= 1000 con
execute if score y2 var >= 1 con if score y2 var < 10 con run scoreboard players operation b var *= 10000 con
execute if score y2 var > 0 con if score y2 var < 1 con run scoreboard players operation b var *= 100000 con
execute if score y2 var = 0 con run scoreboard players operation b var *= 10000 con
scoreboard players operation a var -= b var
scoreboard players operation a var /= p con
scoreboard players operation a var *= 100 con
#tellraw @a ["",{"text":"f * m1 - g * t / p = "},{"score":{"name":"c","objective":"var"},"color":"yellow"}]
# g / f - g
scoreboard players operation c var = g con
scoreboard players operation c var *= 10000 con
scoreboard players operation c var /= f con
scoreboard players operation d var = g con
scoreboard players operation d var *= 100 con
scoreboard players operation c var -= d var
# set
scoreboard players operation a var += c var
scoreboard players operation @s m1 = a var
#tellraw @a ["",{"text":"g / f - g = "},{"score":{"name":"c","objective":"var"},"color":"yellow"}]
 | 
总流程 (motionit:calculate)
 把上面一套流程按顺序走了一遍,计算所得的Motion用(m0,m1,m2)表示。| 复制代码# avoid momentum loss
data merge entity @s {NoGravity:1b}
# get g & f
execute as @s run function motionit:getparam
# flexible accurancy
#   get mx/y/z
execute as @s run function motionit:relativeswitch
execute as @s run function motionit:relativeconfirm
#   exhaustive method to get constant : p = (1 - (1 - f) ^ t)
execute if score f con = 0 con run function motionit:pow/0
execute if score f con = 1 con run function motionit:pow/1
execute if score f con = 2 con run function motionit:pow/2
execute if score f con = 5 con run function motionit:pow/5
#   f * mx / p  or  f * mz / p 
execute as @s run function motionit:opx
execute as @s run function motionit:opz
#   ( f * my - gt ) / p + g / f - g
execute as @s run function motionit:opy
scoreboard players set g con 0
scoreboard players set f con 0
 | 
赋值 (motionit:go)
 还原位数,然后赋值给Motion。| 复制代码# assign values to motion
execute as @s[tag=acx0] store result entity @s Motion[0] double 0.1 run scoreboard players get @s m0
execute as @s[tag=acx1] store result entity @s Motion[0] double 0.01 run scoreboard players get @s m0
execute as @s[tag=acx2] store result entity @s Motion[0] double 0.001 run scoreboard players get @s m0
execute as @s[tag=acx3] store result entity @s Motion[0] double 0.0001 run scoreboard players get @s m0
execute as @s[tag=acx4] store result entity @s Motion[0] double 0.00001 run scoreboard players get @s m0
execute as @s[tag=acx5] store result entity @s Motion[0] double 0.000001 run scoreboard players get @s m0
execute as @s[tag=acy0] store result entity @s Motion[1] double 1 run scoreboard players get @s m1
execute as @s[tag=acy1] store result entity @s Motion[1] double 0.1 run scoreboard players get @s m1
execute as @s[tag=acy2] store result entity @s Motion[1] double 0.01 run scoreboard players get @s m1
execute as @s[tag=acy3] store result entity @s Motion[1] double 0.001 run scoreboard players get @s m1
execute as @s[tag=acy4] store result entity @s Motion[1] double 0.0001 run scoreboard players get @s m1
execute as @s[tag=acy5] store result entity @s Motion[1] double 0.00001 run scoreboard players get @s m1
execute as @s[tag=acz0] store result entity @s Motion[2] double 0.1 run scoreboard players get @s m2
execute as @s[tag=acz1] store result entity @s Motion[2] double 0.01 run scoreboard players get @s m2
execute as @s[tag=acz2] store result entity @s Motion[2] double 0.001 run scoreboard players get @s m2
execute as @s[tag=acz3] store result entity @s Motion[2] double 0.0001 run scoreboard players get @s m2
execute as @s[tag=acz4] store result entity @s Motion[2] double 0.00001 run scoreboard players get @s m2
execute as @s[tag=acz5] store result entity @s Motion[2] double 0.000001 run scoreboard players get @s m2
# avoid momentum loss
data merge entity @s {NoGravity:0b}
 | 
这里涉及到失重,原因是为了修复一个莫名其妙的动量亏损。也就是说重力状态下,通过命令修改的Motion值会在第二刻突然减弱,而初始化生成实体时设定的Motion不受影响。
 
UIUI的具体细节就不讲了,射线等老技术自己翻翻源码也就明白了。
 
 |