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