公告
由于静态博客的局限性,该网站已停止维护,原有的文章将迁移至该位置。
由于静态博客的局限性,该网站已停止维护,原有的文章将迁移至该位置。
下文中
指令名:/summoningex (op)
(其中op的类型为area
或summon
)
提供了对召唤区域(Summoning Area)的操作
格式:/summoningex area (op)
(其中op的类型为define
,list
,query
,remove
,show
或hide
)
用于定义和命名召唤区域
格式:/summoningex area define (x1), (y1), (z1), (x2), (y2), (x2) as #(name) [colored (colorop) (colorval) [in (dim)]]/[in (dim)]
定义了召唤区域的位置(以(x1, y1, z1)与(x2, y2, z2)两个方块坐标(BlockPos)为顶点)
注意x1, y1, z1, x2, y2, z2为整数且x1, x2之间,y1, y2之间与z1, z2之间没有严格的大小限制(也就是说x1既可以大于x2,又可以等于或小于x2)
x1与x2,y1与y2,z1与z2都相同时表示了一个但方块的召唤区域
定义了召唤区域的名称(指令中的”#”号不可省略且不能为中文)
当color传入custom时,colorval应传入一个[0, 16777215]间的十进制整数,表示了召唤区域的RGB颜色值
当color传入preset时,colorval应传入原版的一种染料颜色(DyeColor),该颜色表示了召唤区域的颜色(但这个颜色的饱和度最大值被限制在了88%)
若不指定颜色则会随机为召唤区域分配一个颜色
相关代码
染料颜色的获取(getDyeColor(CommandContext
1 | public static int getIntDyeColor(CommandContext<CommandSourceStack> context, String name) { |
颜色的随机分配
1 | private static int randomColor(RandomSource random) { |
定义了召唤区域所在的维度
若不指定维度则会使用当前所在维度
/summoningex area define 0 100 0 10 110 10 as #Example colored custom 16777215 in minecraft:overworld
在主世界定义了一个名为Example,两个顶点分别为(0,100,0),(10,110,10)两个方块坐标,颜色为白色的召唤区域/summoningex area define 20 100 20 25 90 25 as #Example2
在指令使用者所在维度定义了一个名为Example2,两个顶点分别为(20,100,20),(25,90,25),颜色随机的召唤区域
用于列出指定维度内所有的召唤区域
格式:/summoningex area list [in (dim)]
定义了被用来列出召唤区域的维度
若不指定维度则会使用当前所在维度
/summoningex area list in minecraft:the_nether
列出了下界所有的召唤区域
用于在指定维度内查询指定名称的召唤区域
格式:/summoningex area query local/global (op)
(op将在下文中说明)
当使用local时,op为召唤区域名,用于在指令使用者所在维度内查询指定名称的的召唤区域
当使用global时,op为维度+召唤区域名,用于在输入的维度内查询指定名称的的召唤区域
注意使用global时不会在输入召唤区域名时提供建议(Suggestion)
/summoningex area query local #Example
在指令使用者所在维度查询了名为Example的召唤区域/summoningex area query global minecraft:overworld #Example2
在主世界查询了名为Example2的召唤区域
用于在指定维度内移除指定名称的召唤区域
格式:/summoningex area remove all/global/local (op)
(op将在下文中说明)
此时op为completely
或in (dim)
,也可以省略op
当op为completely
时,将会移除所有维度内所有的召唤区域
当op为in (dim)
时(dim为维度),将会移除指定维度内所有的召唤区域
当op省略时,将会移除指令使用者所在维度内所有的召唤区域
local与global的含义与query中大致相同,此处不再阐述
/summoningex area remove local #Example
在指令使用者所在维度移除了名为Example的召唤区域/summoningex area remove all in minecraft:the_end
移除了末地所有的召唤区域
以长方体边框显示所有的召唤区域(召唤区域默认隐藏)
当在使用指令/summoningex area show
后,如果添加了新的维度,则可能需要重新使用指令
隐藏所有的召唤区域
提供了在召唤区域(长方体)的底面召唤指定数量实体的操作(召唤的实体将在召唤区域的底面随机分布)
格式:/summoningex summon (entity) inside #(name) [count (cnt) [nbt (nbt)]]
指定了所召唤实体的类型(同原版/summon
指令的第一个参数)
召唤区域的名称(这里只能使用指令使用者所在维度的召唤区域)
指定了召唤实体的数量(最大为2000)
若不指定则默认召唤一个实体
指定了召唤的实体的NBT(对每个召唤的实体使用该NBT的副本)
与原版/summon
指令相同,当传入NBT时,Mob类型实体的finalizeSpawn方法将不会被调用
/summoningex summon minecraft:pig inside #Example count 10
在指令使用者所在维度中名为Example的召唤区域内召唤了10只猪/summoningex summon minecraft:iron_golem inside #Example2 count 5 nbt {Health:1}
在指令使用者所在维度中名为Example2的召唤区域内召唤了5个生命值为1的铁傀儡
本Mod提供了一个新的实体选择器(IEntitySelectorType)(默认为@b,可在配置文件内修改)
该实体选择器可以选中所有(或满足一定条件的)与指定召唤区域相交(指碰撞箱相交)的实体
/@b(#(name))[op]
召唤区域的名称(这里只能使用指令使用者所在维度的召唤区域)
与原版实体选择器@e
相同
/kill @b(#Example)
杀死指令使用者所在维度中名为Example的召唤区域(下文简记为召唤区域Example)内的所有实体/effect give @b(#Example)[type=!minecraft:player] minecraft:wither 45
将45秒的凋零效果应用于召唤区域Example内所有不为玩家的实体
/summon
指令相同,Mod的所有指令的执行权限为2高中学习压力较大(高一的暑假就只放30多天,这个Mod是暑假抽时间做的),并且两周回家一次,因此开学后可能不会频繁地维护Mod,但我会尽量不停更,也许也会为Mod增加一些内容233
在世界边境附近调试Mod实体时,偶然发现了这样的问题(图中激光渲染的位置出现异常偏移)
这是怎么回事呢?
在Minecraft的Mod开发中,开发者们可能常使用以下的代码辅助世界的渲染:
1 | Vector3d projectedView = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); |
这样做的好处显而易见——可以在渲染中用绝对坐标替换相对坐标。
不过使用这样的方式,有时也会导致一些问题,先从float和double的有效数字分析
下表为float和double的一些属性比较
属性 | float | double |
---|---|---|
符号位/bit | 1 | 1 |
指数位/bit | 8 | 11 |
尾数位/bit | 23 | 52 |
占用内存空间 | 4 Byte (32bit) | 8 Byte (64bit) |
由此可知float的有效数字位数为6~7位,而double则为15~16位
以下是MatrixStack类中translate方法的源代码
1 | public void translate(double x, double y, double z) { |
可以发现,此方法内做了一个强制类型转换,将双精度的double转换为了单精度的float!
在World(SRG名,1.16.5)类中,有如下的私有静态方法
1 | private static boolean isInWorldBoundsHorizontal(BlockPos pos) { |
由此可知,MC的世界是60000001x60000001格的,这会使得当坐标足够大时,用float表示坐标会使float的小数部分丢失,从而发现了问题所在
在未解决bug时,由于直接在translate中传入世界真实坐标,导致强制类型转换,进而导致double后面的小数部分丢失
translate时,传入激光起始位置的坐标与玩家坐标的差,使数字变小,以确保float的小数部分保留
1 | Vector3d cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); |
最后效果如下图所示
激光渲染的位置的异常偏移消失了!