diff --git a/docs/.vitepress/sidebar.ts b/docs/.vitepress/sidebar.ts index d3a3df6..5f7cd24 100644 --- a/docs/.vitepress/sidebar.ts +++ b/docs/.vitepress/sidebar.ts @@ -33,6 +33,10 @@ export const sidebar: DefaultTheme.Sidebar = { { text: "顶层语句", link: "/zh/quickstart/02base/04top-statements", + }, + { + text: "原生命令", + link: "/zh/quickstart/02base/05original-command", } ], }, @@ -59,6 +63,10 @@ export const sidebar: DefaultTheme.Sidebar = { { text: "内联函数", link: "/zh/quickstart/04function/03inline-function", + }, + { + text: "编译期函数", + link: "/zh/quickstart/04function/04compiletime-function", } ], }, @@ -73,9 +81,13 @@ export const sidebar: DefaultTheme.Sidebar = { text: "类的成员", link: "/zh/quickstart/05class/02member", }, + { + text: "单例", + link: "/zh/quickstart/05class/03object", + }, { text: "继承和抽象", - link: "/zh/quickstart/05class/03inheritance-abstract", + link: "/zh/quickstart/05class/04inheritance-abstract", } ], }, @@ -166,6 +178,10 @@ export const sidebar: DefaultTheme.Sidebar = { { text: "JavaVar", link: "/zh/quickstart/11mni/03javavar", + }, + { + text: "注解", + link: "/zh/quickstart/11mni/04annotation", } ], }, @@ -235,11 +251,11 @@ export const sidebar: DefaultTheme.Sidebar = { link: "/en/quickstart/05class/01define-and-instantiate", }, { - text: "类的成员", + text: "Member of class ", link: "/en/quickstart/05class/02member", }, { - text: "继承和抽象", + text: "Inheritance and abstraction", link: "/en/quickstart/05class/03inheritance-abstract", } ], @@ -248,7 +264,7 @@ export const sidebar: DefaultTheme.Sidebar = { text: "Interface", "items": [ { - text: "定义和实现接口", + text: "Define and implement ", link: "/en/quickstart/06interface/01define-and-implement", } ], diff --git a/docs/en/index.md b/docs/en/index.md index 5e36610..e3c2cbe 100644 --- a/docs/en/index.md +++ b/docs/en/index.md @@ -11,8 +11,8 @@ hero: text: QuickStart link: /en/quickstart/index - theme: alt - text: Overview - link: /en/overview + text: GitHub + link: https://github.com/MinecraftFunctionPlusPlus/MCFPP features: - title: Ultimate Experience diff --git a/docs/index.md b/docs/index.md index de2bba3..b7885d8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,8 +11,8 @@ hero: text: 快速开始 link: /zh/quickstart/index - theme: alt - text: 语法总览 - link: /zh/overview + text: GitHub + link: https://github.com/MinecraftFunctionPlusPlus/MCFPP features: - title: 极致体验 @@ -20,6 +20,6 @@ features: - title: 跨版本编译 details: 一份代码,多版本支持,无需担心Mojang的一周一改 - title: 无缝集成 - details: 强大的MNI框架,基于数据包编译期更多的可能 + details: 强大的MNI框架,基于数据包编译期,提供更多的可能 --- diff --git a/docs/zh/index.md b/docs/zh/index.md index 284fe71..0b7f5a9 100644 --- a/docs/zh/index.md +++ b/docs/zh/index.md @@ -11,8 +11,8 @@ hero: text: 快速开始 link: /zh/quickstart/index - theme: alt - text: 语法总览 - link: /zh/overview + text: GitHub + link: https://github.com/MinecraftFunctionPlusPlus/MCFPP features: - title: 极致体验 diff --git a/docs/zh/quickstart/01project/02config-file.md b/docs/zh/quickstart/01project/02config-file.md index 156d9f4..b239f7a 100644 --- a/docs/zh/quickstart/01project/02config-file.md +++ b/docs/zh/quickstart/01project/02config-file.md @@ -4,4 +4,27 @@ lastUpdated: true # 配置文件 -TODO +MCFPP的工程配置文件是一个json文件,一般存放在这个工程的根目录下。它的Json格式如下: + +```json +{ + //项目文件的路径列表。使用通配符选择所有文件 + "files": [ + "src/main/mcfpp/**" + ], + //项目的源代码目录。文件的命名空间根据文件相对于源代码目录的相对路径决定 + "sourcePath": "src/main/mcfpp", + //数据包的描述。是一个原始JSON文本 + "description": "", + //数据包的默认命名空间,将会决定数据包中storage等数据的命名空间 + "namespace": "test", + //数据包的输出路径。数据包、库文件将会输出在此目录下 + "targetPath": "src/main/resources/lib", + //是否 *不* 生成数据包。默认为false + "noDatapack": false, + //是否 *忽略* 标准库。默认为false。如果为true,将不会引用mcfpp的标准库。 + "ignoreStdLib": false, + //是否是库。默认为false。库不需要拥有一个入口函数 + "isLib": false +} +``` diff --git a/docs/zh/quickstart/02base/01variables.md b/docs/zh/quickstart/02base/01variables.md index 407ae20..7c3a9d4 100644 --- a/docs/zh/quickstart/02base/01variables.md +++ b/docs/zh/quickstart/02base/01variables.md @@ -32,9 +32,9 @@ int b = i * 6; |dict|表示一个字典|`{"a":1,"b":2,"c":3}`| |map|字典的更高级包装,拥有比字典更多的功能|同上| |string|表示一个字符串|`"mcfpp"`,`"qwq"`| -|jtext|表示一个Json原始文本|`"mcfpp"`,`{"text":"mcfpp","color":"#114514"}`| +|text|表示一个Json原始文本|`"mcfpp"`,`{"text":"mcfpp","color":"#114514"}`| |entity|表示一个实体。储存了一个实体的UUID|略| -|selector|表示一个目标选择器|`@a`,`@p[limit=6]`| +|selector|表示一个目标选择器|`@a`,`@p`| 以下是对类型的简要介绍,可以逐一展开查看: @@ -43,43 +43,43 @@ int b = i * 6; ::: ::: details float -**float**类型是MCFPP中表示一个单精度浮点数的类型。它可以是正数、负数、零,也可以是十进制、科学计数法等。MCFPP的浮点数运算依赖[小豆的数学库完成](https:#github.com/xiaodou8593/math2.0)。浮点数的运算为纯粹的记分板运算,因此占用量不会很大。 +表示MCFPP中的一个浮点数。它的精度和单精度浮点数相当。它可以是正数、负数、零,也可以是十进制、科学计数法等。MCFPP的浮点数运算依赖[小豆的数学库完成](https:#github.com/xiaodou8593/math2.0)。浮点数的运算为纯粹的记分板运算,因此占用量不会很大。 ::: ::: details bool -**bool**类型是MCFPP中表示一个布尔型数据的类型。它只有两个值:`true`和`false`。bool类型的数据会被储存为一个记分板变量,因此它的大小和记分板的大小一样。 +表示一个布尔型数据。它只有两个值:`true`和`false`。bool类型的数据会被储存为一个记分板变量,因此它的大小和记分板的大小一样。 ::: ::: details nbt -**nbt**类型表示一个NBT数据。不过实际上,NBT类型的数据更多情况下只是储存了一个NBT路径,因此把它们称作NBT指针也不足为过。值得注意的是,**nbt**类型的变量是大多数基本类型的基础,例如`list`,`map`等都依托NBT数据的操作实现。 +表示一个NBT数据。不过实际上,NBT类型的数据更多情况下只是储存了一个NBT路径,因此把它们称作NBT指针也不足为过。值得注意的是,**nbt**类型的变量是大多数基本类型的基础,例如`list`,`map`等都依托NBT数据的操作实现。 ::: ::: details list -**list**类型表示一个列表。`list`类型实现了java中`ArrayList`的大多数方法,详细可以参考标准库的API。`list`会被储存为一个NBT列表。 +表示一个列表。`list`类型实现了java中`ArrayList`的大多数方法,详细可以参考标准库的API。`list`会被储存为一个NBT列表。 ::: ::: details dict -**dict**类型表示一个字典,被储存为一个NBT复合标签。受MC的限制,`dict`类型只能进行基本的键值对插入和删除操作,无法进行遍历操作。你可以使用`map`来进行更多的操作。 +表示一个字典,被储存为一个NBT复合标签。受MC的限制,`dict`类型只能进行基本的键值对插入和删除操作,无法进行遍历操作。你可以使用`map`来进行更多的操作。 ::: ::: details map -**map**类型是`dict`类型的更高级包装,拥有比`dict`更多的功能。`map`类型实现了java中`HashMap`的大多数方法,详细可以参考标准库的API。但是值得注意的是,`map`的更高级包装意味着`map`会拥有比`dict`更多的开销。 +`dict`类型的更高级包装,拥有比`dict`更多的功能。`map`类型实现了java中`HashMap`的大多数方法,详细可以参考标准库的API。但是值得注意的是,`map`的更高级包装意味着`map`会拥有比`dict`更多的开销。 ::: ::: details string -TODO +表示一个字符串,即NBT中的string标签。 ::: -::: details jtext -TODO +::: details text +表示一个原始JSON文本,相较于`string`类型,`text`类型可以包含更多的格式信息,例如颜色、粗体等。`text`类型的数据会被储存为一个NBT复合标签。 ::: ::: details entity -TODO +表示单个实体。储存为一个UUID整数型NBT数组。 ::: ::: details selector -TODO +表示一个目标选择器。储存为一个字符串。 ::: ## var关键字 @@ -98,7 +98,7 @@ var i; # [!code error] #错误,缺少初始化表达式 ## 变量修饰符 -变量修饰符可以用来表示变量的类型,包括`dynamic`,`const`,`import` +变量修饰符可以用来表示变量的类型,包括`dynamic`,`const` - dynamic diff --git a/docs/zh/quickstart/02base/05original-command.md b/docs/zh/quickstart/02base/05original-command.md new file mode 100644 index 0000000..98eda5c --- /dev/null +++ b/docs/zh/quickstart/02base/05original-command.md @@ -0,0 +1,31 @@ +--- +lastUpdated: true +--- + +# 原生命令 + +MCFPP支持Minecraft原生命令的使用。有两种方法可以使用原生命令: + +## 使用`/`插入命令 + +以`/`开头的语句将会被认为是一个原生命令。例如: + +```mcfpp +func test(){ + /summon minecraft:armor_stand ~ ~ ~ +} +``` + +将会直接在test函数中插入一个summon命令。 + +## 使用`insert`函数 + +`insert`函数可以将一个字符串插入到当前位置。例如: + +```mcfpp +func test(){ + insert("summon minecraft:armor_stand ~ ~ ~"); +} +``` + +将会将`insert`参数中的原文插入到test函数中。值得注意的是,`insert`函数的参数是一个字符串,因此你可以在其中插入任何内容,这同时意味着编译器不会对命令格式进行任何检查。 diff --git a/docs/zh/quickstart/03namespace/01namespace.md b/docs/zh/quickstart/03namespace/01namespace.md index 621dbf6..3245428 100644 --- a/docs/zh/quickstart/03namespace/01namespace.md +++ b/docs/zh/quickstart/03namespace/01namespace.md @@ -18,20 +18,4 @@ func test(){ # test:test函数 一个文件中只能声明一次命名空间。 -同样的,你也可以在项目配置文件中声明这个命名空间。 - -```json -{ - "file":[ - "*" - "D:/workspace/mcfpp/project/*" - ], - "version":"1.19.4", - "include":[ - "D:/workspace/mcfpp/another_project.json" - ], - "targetPath":"./out", - //工程的默认命名空间。可选,默认为default // [!code focus] - "namespace":"mcfpp" // [!code focus] -} -``` +若没有声明命名空间,文件的命名空间将会由文件路径相对于源代码路径的相对路径决定。例如,假设源代码目录为`src/main/mcfpp`,那么文件`src/main/mcfpp/test/test.mcfpp`的命名空间将会是`test.test`。源代码路径通过工程配置文件中的`sourcePath`决定。 diff --git a/docs/zh/quickstart/04function/02static-params.md b/docs/zh/quickstart/04function/02static-params.md index 9d66799..b4a2847 100644 --- a/docs/zh/quickstart/04function/02static-params.md +++ b/docs/zh/quickstart/04function/02static-params.md @@ -2,7 +2,7 @@ lastUpdate: true --- -# static关键字 +# static关键字可能更改 `static`关键字用于声明一个静态参数。静态参数表示,在参数传递的过程中,是传递的参数本身而不是参数的值,因此在函数中对参数的修改会影响外部的变量。例如: diff --git a/docs/zh/quickstart/04function/04compiletime-function.md b/docs/zh/quickstart/04function/04compiletime-function.md index e69de29..034cf2b 100644 --- a/docs/zh/quickstart/04function/04compiletime-function.md +++ b/docs/zh/quickstart/04function/04compiletime-function.md @@ -0,0 +1,7 @@ +--- +lastUpdate: true +--- + +# 编译期函数 + +TODO diff --git a/docs/zh/quickstart/05class/01define-and-instantiate.md b/docs/zh/quickstart/05class/01define-and-instantiate.md index 56c1cd8..fd3493f 100644 --- a/docs/zh/quickstart/05class/01define-and-instantiate.md +++ b/docs/zh/quickstart/05class/01define-and-instantiate.md @@ -25,7 +25,6 @@ class Person{ } ``` - ## 类的定义 作为一个面向对象的编程语言,MCFPP有完善的面向对象的语法和功能。它的语法和Java/C#的语法非常相似,所以,如果你有相关的基础的话,你应该可以很轻松地上手。 @@ -45,14 +44,31 @@ class ClassName{ 一般情况下,你可以使用`ClassName(参数列表)`来创建一个对象的实例。比如本篇开头的示例`Person`类可以用`Person p = Person("Alumopper",16)`来创建。在MCFPP中,你并不需要`new`关键字。它被省略掉了。 -## 类的初始化器 +## 类的初始化器 在创建类的时候,你可以使用类初始化器来对类的某些成员变量初始化,例如对于上文中的`Person`,有: ```mcfpp -Person p = Person("Alumopper",16){ +Person p = Person("Alumopper",16)[ sex = "女" -}; +]; +``` + +这样,`p`的`sex`成员变量就被初始化为`"女"`了。 + +::: tip + +### 不仅仅是类的初始化 + +事实上,类初始化器可以用在任何地方,而不只是在类的初始化的时候。比如 + +```mcfpp +func main(){ + Test t = Test(); + t = t[a = 100]; + print(t.toText()); +} ``` -这样,`p`的`sex`成员变量就被初始化为`"女"`了。 \ No newline at end of file +在这个例子中,类的初始化器实际上是域操作器。`t = t[a = 100]`将t中的a赋值为100。 +::: diff --git a/docs/zh/quickstart/05class/03inheritance-abstract.md b/docs/zh/quickstart/05class/03inheritance-abstract.md deleted file mode 100644 index fe59ad4..0000000 --- a/docs/zh/quickstart/05class/03inheritance-abstract.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -lastUpdate: true ---- - -# 继承和抽象 - -MCFPP中,类支持继承和抽象。继承是指一个类可以派生出一个或多个子类,子类可以继承父类的属性和方法。抽象是指一个类可以定义抽象方法,子类必须实现这些抽象方法。 - -## 继承 - -继承是指一个类可以派生出一个或多个子类,子类可以继承父类的属性和方法。继承的语法如下: - -```mcfpp -class Parent{ - protect int a; - func test(){ - print("Parent"); - print(a); - } -} - -class Child: Parent{ - int b; - override func test(){ - print("Child"); - print(super.a); - } -} -``` - -使用`:`关键字可以声明一个类继承自另一个类。利用`super`关键字,子类可以访问父类的属性和方法。使用`protected`关键字可以声明受保护的属性,子类可以访问父类的受保护属性。使用`override`关键字可以重写父类的方法。 - -## 抽象 - -一个类可以定义抽象方法,子类必须实现这些抽象方法。抽象方法没有方法体,只有方法签名。抽象方法的定义语法如下: - -```mcfpp -abstract class A{ - abstract func test(); -} - -class B: A{ - override func test(){ - print("Hello, World!"); - } -} -``` - -使用`abstract`关键字可以声明一个抽象类或一个抽象方法。抽象类的子类必须实现抽象方法,否则会编译错误。 \ No newline at end of file diff --git a/docs/zh/quickstart/05class/03object.md b/docs/zh/quickstart/05class/03object.md new file mode 100644 index 0000000..7ca516e --- /dev/null +++ b/docs/zh/quickstart/05class/03object.md @@ -0,0 +1,49 @@ +--- +lastUpdate: true +--- + +# 单例 + +## 定义 + +使用`object class`声明一个单例的类对象。单例是一种特殊的类,只有一个实例。在其他方面,单例和普通类没有区别。 + +```mcfpp +object class Singleton { + // 成员 + int value = 0; + + // 方法 + func setValue(int v) { + value = v + } +} + +//使用 +Singleton.setValue(10) +``` + +## 伴随对象 + +如果声明了一个和类同名的单例,那么我们称这个单例为类的伴随对象。 + +```mcfpp +class Person { + + int id = 0; + + constructor() { + this.id = Person.nextId(); + } +} + +object class Person { + + private int id = 0; + + int nextId() { + id = id + 1; + return id; + } +} +``` diff --git a/docs/zh/quickstart/05class/04inheritance-abstract.md b/docs/zh/quickstart/05class/04inheritance-abstract.md new file mode 100644 index 0000000..5d385ba --- /dev/null +++ b/docs/zh/quickstart/05class/04inheritance-abstract.md @@ -0,0 +1,45 @@ +--- +lastUpdate: true +--- + +# 继承和抽象 + +MCFPP中,类支持继承和抽象。 + +## 继承 + +使用`:`关键字可以声明一个类继承自另一个类。利用`super`关键字,子类可以访问父类的属性和方法。使用`override`关键字可以重写父类的方法。 + +```mcfpp +class Parent{ + protect int a; + func test(){ + print("Parent"); + print(a); + } +} + +class Child: Parent{ + int b; + override func test(){ + print("Child"); + print(super.a); + } +} +``` + +## 抽象 + +使用`abstract`关键字可以声明一个抽象类或一个抽象方法。可以在抽象类中定义抽象方法,而它的非抽象子类必须实现这些抽象方法。抽象方法没有方法体,只有方法签名。 + +```mcfpp +abstract class A{ + abstract func test(); +} + +class B: A{ + override func test(){ + print("Hello, World!"); + } +} +``` diff --git a/docs/zh/quickstart/06interface/01define-and-implement.md b/docs/zh/quickstart/06interface/01define-and-implement.md index eb2375d..d5f1d67 100644 --- a/docs/zh/quickstart/06interface/01define-and-implement.md +++ b/docs/zh/quickstart/06interface/01define-and-implement.md @@ -42,11 +42,11 @@ class ClassName: Interface1, Interface2, ...{ ```mcfpp interface Interface1{ - func method1() -> void; + func method1(); } interface Interface2: Interface1{ - func method2() -> void; + func method2(); } ``` diff --git a/docs/zh/quickstart/11mni/01mni-framework.md b/docs/zh/quickstart/11mni/01mni-framework.md index 8670cf8..241275c 100644 --- a/docs/zh/quickstart/11mni/01mni-framework.md +++ b/docs/zh/quickstart/11mni/01mni-framework.md @@ -18,44 +18,34 @@ func print(any a) = top.mcfpp.lang.System.print; //print函数在java中的具体实现 package top.mcfpp.lang; -//略去import函数 +import org.jetbrains.annotations.NotNull; +import top.mcfpp.annotations.InsertCommand; +import top.mcfpp.annotations.MNIRegister; +import top.mcfpp.command.Command; +import top.mcfpp.core.lang.*; +import top.mcfpp.lib.ScoreChatComponent; +import top.mcfpp.model.function.Function; +import top.mcfpp.util.NBTUtil; +import top.mcfpp.util.ValueWrapper; public class System extends MNIMethodContainer { - - @NotNull - @Override - public Function4[], Var[], CanSelectMember, ValueWrapper>, java.lang.Void> getMNIMethod(@NotNull String name) { - return methods.get(name); - } - - static HashMap[], Var[], CanSelectMember, ValueWrapper>, java.lang.Void>> methods; - - static { - methods = new HashMap<>(); - //实现print函数 - methods.put("print", (vars, vars2, canSelectMember, varValueWrapper) -> { - //只会有一个参数哦 - var value = vars2[0]; - if (value instanceof MCInt) print((MCInt) value); - else print(value); - return null; - }); + + @InsertCommand + @MNIRegister(normalParams = {"any a"}) + public static void print(@NotNull Var value){ + Function.Companion.addCommand("tellraw @a " + "\"" + value + "\""); } @InsertCommand + @MNIRegister(normalParams = {"int i"}) public static void print(@NotNull MCInt var) { if (var instanceof MCIntConcrete varC) { //是确定的,直接输出数值 Function.Companion.addCommand("tellraw @a " + varC.getValue()); }else { - Function.Companion.addCommand("tellraw @a " + new JsonTextNumber(var).toJson()); + Function.Companion.addCommand("tellraw @a " + new ScoreChatComponent(var).toCommandPart()); } } - - @InsertCommand - public static void print(@NotNull Var var){ - Function.Companion.addCommand("tellraw @a " + "\"" +var + "\""); - } } ``` diff --git a/docs/zh/quickstart/11mni/02mni-framework-implementation.md b/docs/zh/quickstart/11mni/02mni-framework-implementation.md index 6d9a89d..09b6b86 100644 --- a/docs/zh/quickstart/11mni/02mni-framework-implementation.md +++ b/docs/zh/quickstart/11mni/02mni-framework-implementation.md @@ -22,101 +22,137 @@ func print(int i) = top.mcfpp.lang.System.print; ## 实现 -`System`类被称为**MNI实现类**,`print`函数的具体逻辑就是在这个类中实现的。MNI的实现类必须继承`MNIMethodContainer`类: +`System`类被称为**MNI实现类**,`print`函数的具体逻辑就是在这个类中实现的。通过使用`@MNIRegister`注解,我们可以将一个Java函数注册为MNI实现函数。这个注解的源码如下,它的参数在注释中已经有详细的解释。 -```kotlin -package top.mcfpp.model.function +```java +package top.mcfpp.annotations; + +//import ... + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface MNIRegister { + + /** + * 只读参数。格式是类型+空格+参数名 + */ + String[] readOnlyParams() default {}; + + /** + * 普通参数。格式是类型+空格+参数名 + */ + String[] normalParams() default {}; -typealias MNIMethod = (Array?>, Array?>, CanSelectMember?, ValueWrapper>) -> Void + /** + * 调用者类型。默认为void + */ + String caller() default "void"; -abstract class MNIMethodContainer{ + /** + * 函数的返回类型。默认为void + */ + String returnType() default "void"; - abstract fun getMNIMethod(name: String): MNIMethod + /** + * 是否重写了父类中的函数。默认为false + */ + boolean override() default false; } ``` -其中,定义了一个名为`getMNIMethod`的抽象方法,它的参数是一个函数名,即在之前声明native方法的时候,在等号后面的部分,类名.函数名中的函数名。方法需要根据传入的函数名,返回一个`MNIMethod`函数。 +而具体实现用的这个Java函数的参数顺序,遵循:`只读参数 + 普通参数 + 调用者 + ValueWrapper<返回值类型>`的原则。 -而`MNIMethod`是一个lambda函数类型,它接受四个参数: +我们回到刚刚的例子: -* `Array?> readonlyArgs`:传入函数的泛型参数数组。参数的顺序和定义一致。 +```mcfpp +func print(any a) = top.mcfpp.lang.System.print; +``` -* `Array?> normalArgs`:传入函数的普通参数数组。参数的顺序和定义一致。 +```java + //... -* `CanSelectMember? caller`:这个函数的调用者。比如对于`a.test()`,变量`a`就是调用者。如果调用者不存在,比如对于全局函数,那么这个参数就是`null` + @MNIRegister(normalParams = {"any a"}) + public static void print(@NotNull Var value){ + Function.Companion.addCommand("tellraw @a " + "\"" + value + "\""); + } -* `ValueWrapper> returnVar`:这个参数即为函数的返回值。它的成员变量`value`即为函数的返回值对应的变量,可以通过修改value达到返回某个值的目的。如果函数没有返回值,可以不用管这个参数。 + //... +``` -在MNI调用执行Native函数的过程中,将会自动调用`getMNIMethod`方法,根据函数名获取到对应的函数,传入上述四个参数,然后执行这个函数。 +`print`函数有一个`any`类型的变量,因此注解中,我们使用`normalParams = {"any a"}`来声明这个参数。而在具体实现中,我们需要接受一个普通参数。在这里,我们用所有变量类的基类`Var`类,来表示任意类型的变量都可以被接收。 -一般来说,我们会在MNI实现类中定义一个静态的`HashMap`,用于存储所有的MNI函数。这个`HashMap`的key是函数名,value是对应的`MNIMethod`函数。在`getMNIMethod`方法中,我们只需要根据传入的函数名,从`HashMap`中获取到对应的函数即可,例如对于`System`类,我们的实现是这样的: +我们看一个稍微复杂一些的例子: ```java -package top.mcfpp.lang; -//略去import函数 + @MNIRegister(caller = "DataObject", returnType = "text", override = true) + public static void toText(DataTemplateObject caller, ValueWrapper returnValue) throws IOException { + var l = new ListChatComponent(); + if(caller instanceof DataTemplateObjectConcrete callerC){ + l.getComponents().add(new PlainChatComponent(SNBTUtil.toSNBT(callerC.getValue()))); + }else { + l.getComponents().add(new NBTChatComponent(caller.toNBTVar(), false, null)); + } + returnValue.setValue(new JsonTextConcrete(l, "re")); + } -public class System extends MNIMethodContainer { +``` - @NotNull - @Override - public Function4[], Var[], CanSelectMember, ValueWrapper>, java.lang.Void> getMNIMethod(@NotNull String name) { - return methods.get(name); - } +这是`toText`函数,类似于java中的`toString`方法,旨在将任意类型转换为可以打印在聊天栏的原始Json文本。这个函数没有参数,调用者是`DataObject`,返回值是`text`类型。因此在Java方法的参数中,我们先写一个`DataTemplateObject caller`用于接收调用者,然后再写一个`ValueWrapper returnValue`用于处理返回值。 - static HashMap[], Var[], CanSelectMember, ValueWrapper>, java.lang.Void>> methods; +:::tip +`Function.addCommand`函数用于向当前正在编译的mcf函数的末尾添加一条命令 - static { - methods = new HashMap<>(); - //实现print函数 - methods.put("print", (vars, vars2, canSelectMember, varValueWrapper) -> { - //具体逻辑在这里实现 - }); - } -} +`ValueWrapper`是一个包装类,用于包装返回值。 + +```kotlin +package top.mcfpp.util + +class ValueWrapper(var value: T) ``` -其中,我们在`System`类中定义了一个`HashMap`,并在静态代码块中初始化了`print`函数的实现。现在,我们来具体实现这个函数。 +使用`getValue`和`setValue`来修改其中的值。 -```java +`xxxConcrete`这种命名的类表示是xxx类型变量的编译器可追踪版本,就是编译器知道这个变量里面的值是什么。在标准库的实现中随处可见这种分类处理,为的是尽可能地优化性能。 +::: + +## 注入 + +`CompoundData`类拥有成员方法`getNativeFromClass(cls: Class<*>)`,用于向当前类型中注入来自类`cls`中的所有方法。 + +```kotlin +open class MCInt : MCNumber { + //... - static { - //... - //实现print函数 - methods.put("print", (vars, vars2, canSelectMember, varValueWrapper) -> { - //只会有一个参数哦 - var value = vars2[0]; - if (value instanceof MCInt) print((MCInt) value); - else print(value); - return null; - }); - } + companion object { + val data = CompoundData("int","mcfpp") - @InsertCommand - public static void print(@NotNull MCInt var) { - if (var instanceof MCIntConcrete varC) { - //是确定的,直接输出数值 - Function.Companion.addCommand("tellraw @a " + varC.getValue()); - }else { - Function.Companion.addCommand("tellraw @a " + new JsonTextNumber(var).toJson()); + init { + data.initialize() + data.extends(MCAny.data) + data.getNativeFromClass(MCIntData::class.java) } } - @InsertCommand - public static void print(@NotNull Var var){ - Function.Companion.addCommand("tellraw @a " + "\"" +var + "\""); - } - //... -``` -首先,我们获取到了传入`print`的参数。由于`print`函数只有一个普通参数,因此我们直接使用`var2[0]`就可以获取到这个传入的参数了。此后,我们使用`instanceof`关键字判断这个参数的类型,如果是`MCInt`类型,那么我们就调用`print(MCInt var)`函数。在不同类型对应的函数中,我们再进行具体的实现。 +} -:::tip -`Function.addCommand`函数用于向当前正在编译的mcf函数的末尾添加一条命令 -::: +此外,你也可以在mcfpp代码中使用注解`@From<类的完全限定名>`,来向这个类或者数据模板中注入方法。 + +```mcfpp +@From +data Area{ + int startX; + int startY; + int startZ; + int endX; + int endY; + int endZ; +} +``` ## 调用 diff --git a/docs/zh/quickstart/11mni/04annotation.md b/docs/zh/quickstart/11mni/04annotation.md new file mode 100644 index 0000000..8f243bd --- /dev/null +++ b/docs/zh/quickstart/11mni/04annotation.md @@ -0,0 +1,35 @@ +--- +lastUpdate: true +--- + +# 注解WIP + +你可以在类、数据模板、方法声明的最前方使用@+名字+只读参数列表的方式来为它们添加注解。注解是MNI框架的一部分,只存在于编译阶段。 + +## MNI实现 + +```java +//继承DataTemplateAnnotation,表示这是数据模板才能使用的注解 +public class Example extends DataTemplateAnnotation { + + @SuppressWarnings("unused") + public Example(String className) { + super("Example", "mcfpp.annotation"); + //RESOVLE_FIELD表示解析成员阶段,在这个阶段完成后将注解注册到编译器中 + Project.INSTANCE.getStageProcessor()[Project.INSTANCE.getRESOVLE_FIELD()].add(() -> { + GlobalField.INSTANCE.getLocalNamespaces().get("mcfpp.annotation").getField().addAnnotation("Example",this.getClass(), false); + return null; + }); + } + + //当编译器在注解解析阶段遇到这个注解的时候,会对这个注解修饰的数据模板做什么 + @Override + public void forDataObject(@NotNull DataTemplate data) { + System.out.println(data.getNamespaceID()); + } +} +``` + +## mcfpp声明 + +WIP