JustMCF
Improve Minecraft JE data pack mcfunction and let it be short and pretty
Install / Use
/learn @XiLaiTL/JustMCFREADME
JustMCF
<details><summary>目录</summary> <!-- TOC -->- JustMCF
JustMCF是一个简化mcfunction工程的项目。使用JustMCF,你不但可以使用原版的命令,还可以使用项目设计的简化命令,可以使你的命令更加简洁高效。
以下几个方面是JustMCF进行简化或者增强的部分
- 数据操作简化——对记分板运算、NBT操作进行大幅度简化,并支持表达式形式运算记分板!
- 命名空间省略——修改默认省略情况下的命名空间。(原来默认只能是Minecraft)
- 注释增强——支持行内注释、块注释!(TODO:根据注释信息生成函数帮助信息)
- 逻辑控制流简化——对execute进行大幅度简化!单文件定义多个、嵌套定义函数!支持逻辑表达式、条件语句、循环语句、列表遍历语句!
- 命令聚合——将如scoreboard操作、bossbar操作这类的系列命令聚合到一个块里。
- 命令对象化——像调用对象的方法那样调用命令,打开书写命令的新思路!
- 选择器增强——更加方便的选择器语法、支持换行!
- 支持脚本——直接在文件内定义JavaScript脚本,支持脚本生成命令!
- 进阶函数——提供带有参数的函数封装。(TODO:引入支持库函数如random等)
这个项目未完成的功能:
- [ ] 提供vscode language server用于自动补全和语法高亮
- [ ] 类型检查(类型设置、modify set from、函数类型、for循环类型)
- [ ] 支持JSON文本组件简化
- [ ] 多minecraft版本的支持
谁适合使用本项目?
如果是命令老手——
- 苦于命令与NBT过于冗长、无法换行的创作者——JustMCF大幅度简化了execute、data、scoreboard这三个最常用的命令,并提供NBT换行的支持(TODO:项目完成全部命令的解析支持后,将支持所有命令中涉及到的NBT的换行,目前仅局限于已简化的命令的换行)。
- 苦于需要外部程序文件进行命令穷举、导致逻辑思路分开的创作者——JustMCF直接提供文件内脚本支持,让思路不会断片。
- 苦于每次都要新开函数文件,多个函数文件的分隔导致思维混乱的创作者——JustMCF直接提供单文件定义多个函数的支持,并支持嵌套定义函数。
- 苦于Minecraft命令书写无法形成逻辑链的创作者——JustMCF提供了条件、循环语句、进阶函数封装等特性,让逻辑更加清晰。
- 希望尝试新的抽象思路,新的逻辑组织方式的创作者——JustMCF希望提供interface+func进行命令组织的方式,进一步进行思路的抽象。
如果是习惯了原版命令的创作者——
- JustMCF直接支持使用原版命令,无缝衔接使用JustMCF的单文件多函数、进阶函数封装、条件、循环语句等特性!
- JustMCF支持中性简化,如果认为过渡简化导致不习惯,请看execute的案例:简化幅度较小的支持
如果是命令新手——
- 还是先不要用JustMCF,因为一旦使用了JustMCF,你就会陷入JustMCF带来的魔力之中,直接脱离原版命令苦海。
快速开始
安装
本项目需要首先安装Node.js。
如果已经安装完成,请打开命令行(在Windows下可以是命令提示符cmd、powershell;在Linux下可以是shell、zsh;在macOS下可以是终端Terminal)输入node -v,验证是否已经配置好Path变量,如果显示安装的Node.js版本号,则证明安装完成。请继续在命令行中输入:
npm install -g just-mcf
如果您已经安装,需要更新版本,则请输入:
npm update -g just-mcf
在您的工作文件夹中打开命令行窗口(或者打开命令行窗口cd到工作文件夹中)。
初始化项目
设置JustMCF项目的一些编译选项。
mcf init
初始化完成后,将在工作文件夹中创建mcf.mcmeta文件,这里包含JustMCF项目的各种设置。具体配置项请见附录:配置项介绍。
项目文件结构
JustMCF项目文件以.mcf为后缀,一个.mcf文件可以生成多个.mcfunction文件。
JustMCF项目支持一个mcf.mcmeta文件,用于存放有关数据包兼容性的信息以及JustMCF的设置、自动生成的uuid列表等等。
通常一个数据包的文件结构为:
folder_name
|-pack.mcmeta
|-pack.png
|-data
|-namespace
|-functions
|-tags
|-func ->.mcf文件存放的地方
|-export.mcf ->例如这样一个mcf文件
|-mcf.mcmeta ->存放项目冲突信息的地方(使用的假名、uuid、记分板名)
编译项目
将JustMCF项目输出为Minecraft JE 数据包。
mcf build [<source_path>] [-o <target_path>]
# 或
mcf build [<source_path>] [--output <target_path>]
其中[]标记的部分是可选的。
<source_path> 编译的源地址,不填写则为当前命令行执行目录。
<target_path> 编译的目的地址,不填写则为执行目录的兄弟output文件夹。例如执行目录为/foo/test,则目的地址为/foo/test_output。
路径都可以添加相对地址,用./索引到执行目录的子文件或文件夹,用../索引到执行目录的同级文件夹,例如mcf build -o .即输出到执行目录,当然这是不推荐的;mcf build -o ../output即输出到执行目录的兄弟文件夹output中。
一般来说,源地址填写工作路径,目的地址填写.minecraft/saves/datapacks/下的文件夹,这样子输出后可以直接reload查看运行情况以方便调试。
可以编写一个bat文件放在工作文件夹下,内容就填写:
mcf build -o xxxx/.minecraft/saves/datapacks/test
pause
调整全局设置
设置命令行的全局参数。
mcf conf
目前可以设置命令行的语言和编译缺少参数时是否进行询问。
最佳实践
这里以一段视线追踪代码为例:
仅仅增强原版命令
选择仅仅使用JustMCF增强的以下功能:单文件多function、可以换行的execute、选择器、nbt、json文本。
在传统风格1中,仅仅使用了单文件多function的特性,把同一个逻辑单元的function写到一起来。这个单.mcf文件最终会被解析成4个.mcfunction文件
<details><summary> 传统风格1 </summary>
func teen:begin{
execute as @a at @s anchored eyes positioned ^ ^ ^ run function teen:before
}
func teen:before{
function teen:ray
tag @s ret
}
func teen:ray{
scoreboard players set #find_entity bool 0
execute as @e[dx=0,dy=0,dz=0] positioned ~-1 ~-1 ~-1 if entity @s[dx=0,dy=0,dz=0] run scoreboard players set #find_entity bool 1
execute if block ~ ~ ~ #through if score #find_entity bool matches 0 positioned ^ ^ ^0.1 run function teen:ray
execute unless entity @s[tag=find] run function teen:find
}
func teen:find{
tag @s add find
tellraw @s "Find it!"
}
</details>
在传统风格2中,使用了exec的换行支持与回调式书写函数的特性,把同一个逻辑单元的function整合到一起。
<details><summary> 传统风格2 </summary>
func teen:ray{
scoreboard players set #find_entity bool 0
exec{ as @e[dx=0,dy=0,dz=0] positioned ~-1 ~-1 ~-1 if entity @s[dx=0,dy=0,dz=0]} run
scoreboard players set #find_entity bool 1
exec{
if block ~ ~ ~ #through
if score #find_entity bool matches 0
positioned ^ ^ ^0.1
} run func teen:ray
exec{ unless entity @s[tag=find] } run func teen:find{
tag @s add find
tellraw @s "Find it!"
}
}
func teen:begin{
exec{ as @a at @s anchored eyes positioned ^ ^ ^} run func teen:before{
func teen:ray
tag @s ret
}
}
</details>
简洁风格一瞥
乍看一眼什么都看不懂,再慢慢看发现语法挺简单的:)。
<details><summary> 简洁风格 </summary>
namsp [func = teen]{
func begin{
{ as @s at @
