Skip to content

Commit 66af547

Browse files
committed
数据模板和NBT相关
1 parent ddf8b13 commit 66af547

22 files changed

+373
-7
lines changed

docs/en/quickstart/02base/01variables.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
lastUpdated: true
33
---
44

5-
# Variable
5+
# Variable
66

7-
## Declaration of variables
7+
## Declaration of variables
88

99
Same as other languages, you can declare some variables in MCFPP for store, transfer and process data.
1010

docs/zh/quickstart/08nbt/01nbt.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
lastUpdate: true
3+
---
4+
5+
# NBT
6+
7+
在Minecraft中,NBT最重要的数据类型之一。NBT作为一种树状结构的数据类型,可以存储各种各样的数据,例如整数、浮点数、字符串、数组、列表、复合数据等。在MCFPP中,NBT是一种内置的数据类型,可以直接使用。
8+
9+
## NBT数据类型的基本使用
10+
11+
在MCFPP中,NBT数据类型的类型标识符为`nbt`。你可以使用一般的SNBT语法来创建NBT数据,例如:
12+
13+
```mcfpp
14+
nbt value1 = "Hello, World!";
15+
16+
nbt number = 42;
17+
18+
nbt list = [1,2,3];
19+
20+
nbt uuid = [I;0,0,0,1]
21+
22+
nbt itemStack = {
23+
"Count": 1,
24+
"Item": "minecraft:stone",
25+
"tag": {
26+
"display": {
27+
"Name": "Stone"
28+
}
29+
}
30+
};
31+
```
32+
33+
你可以使用`[]`索引来访问复杂NBT数据中的成员。例如:
34+
35+
```mcfpp
36+
nbt itemStack = {
37+
"Count": 1,
38+
"Item": "minecraft:stone",
39+
"tag": {
40+
"display": {
41+
"Name": "Stone"
42+
}
43+
}
44+
};
45+
46+
print(itemStack["tag"]["display"]["Name"]);
47+
48+
nbt list = [1,2,3];
49+
50+
print(list[0]);
51+
```
52+
53+
编译器不会检查索引是否合法。即使索引对应的数据不存在,编译器也将正常拼接NBT路径。在后续的`list`,`dict`,`map`类型中,也是同理的。
54+
55+
除了一种情况,就是编译器知道这个nbt类型的值。此时nbt将会尝试检查数据是否合法,但是并不会报错,而是会给出警告。数据包依然会正常生成。
56+
57+
## NBT数据类型的转换
58+
59+
在MCFPP中,任何数据类型都能被转换为NBT。但是NBT并不能转换为任何数据类型。在编译过程中,编译器会尝试跟踪nbt变量的NBT类型,并由此判断是否能够转换为其他数据类型。
60+
61+
```mcfpp
62+
int i = 5;
63+
nbt n = i; #合法,隐式转换永远成功
64+
int p = (int)n; #合法,编译器已知n是一个int类型的NBT数据
65+
66+
func test(nbt n){
67+
int i = (int)n; #非法,编译器无法确定作为函数参数传入的n是否为int类型的数据
68+
}
69+
```

docs/zh/quickstart/08nbt/02list.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
lastUpdate: true
3+
---
4+
5+
# 列表
6+
7+
NBT支持列表这种基本数据类型,MCFPP将其抽象了出来,作为一种单独的类型提供。
8+
9+
## 基本使用
10+
11+
使用`list<type T>`类型标识符定义一个列表。其中类型参数`T`表示这个列表中存储的元素类型。
12+
13+
```mcfpp
14+
list<int> l = []; #创建一个空列表
15+
l.add(1); #向列表中添加一个元素
16+
l.add(2);
17+
l.add(3);
18+
print(l); #输出[1,2,3]
19+
print(l[0]); #输出1
20+
21+
l.removeAt(1); #从列表中移除索引为1的元素
22+
```
23+
24+
列表的传递为值传递,而不是引用传递。事实上,所有基于纯NBT的数据类型都是值传递。
25+
26+
```mcfpp
27+
28+
list<int> l = [1,2,3];
29+
list<int> l2 = l;
30+
l2.add(4);
31+
print(l); #输出[1,2,3]
32+
print(l2); #输出[1,2,3,4]
33+
```
34+
35+
## 列表的操作
36+
37+
MCFPP标准库提供了一系列的列表操作函数。
38+
39+
| 函数名 | 参数 | 返回值 | 作用 |
40+
| --- | --- | --- | --- |
41+
| `add` | `T element` | `void` | 向列表中添加一个元素 |
42+
| `addAll` | `list<T> elements` | `void` | 向列表中添加一组元素 |
43+
| `insert` | `int index, T element` | `void` | 在指定位置插入一个元素 |
44+
| `removeAt` | `int index` | `void` | 移除指定位置的元素 |
45+
| `indexOf` | `T element` | `int` | 返回指定元素的索引 |
46+
| `lastIndexOf` | `T element` | `int` | 返回指定元素的最后一个索引 |
47+
| `contains` | `T element` | `bool` | 判断列表中是否包含指定元素 |
48+
| `clear` | `void` | `void` | 清空列表 |
49+
50+
## 列表的遍历<Badge type="tip" text="未来特性" />
51+
52+
使用`foreach`循环可以简单地遍历列表中的所有元素。
53+
54+
```mcfpp
55+
list<int> l = [1,2,3];
56+
foreach(i in l){
57+
print(i);
58+
}
59+
```

docs/zh/quickstart/08nbt/03dict.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
lastUpdate: true
3+
---
4+
5+
# 字典
6+
7+
字典类型对应MCFPP中的复合标签类型。它是一个键值对的集合,键必须为字符串类型,而值可以是任意类型。
8+
9+
## 基本使用
10+
11+
使用`dict`类型标识符定义字典类型的变量。使用复合标签来为字典进行赋值。
12+
13+
```mcfpp
14+
dict playerData = {
15+
"Alumopper" : {
16+
"level" : 1,
17+
"exp" : 0
18+
},
19+
"Xiao2" : {
20+
"level" : 2,
21+
"exp" : 100
22+
},
23+
"CR_019" : {
24+
"level" : 3,
25+
"exp" : 200
26+
}
27+
}
28+
29+
print(playerData["Alumopper"]["level"]); #输出1
30+
31+
print(playerData["CR_017"]); #非法,但是不报错
32+
33+
playerData["CR_017"] = {
34+
"level" : 4,
35+
"exp" : 300
36+
}; # 添加一个新的键值对
37+
38+
```
39+
40+
## 字典的操作
41+
42+
字典不能被遍历,也不能获取关于键值的列表。MCFPP提供了一些基本的字典操作。
43+
44+
| 函数名 | 参数 | 返回值 | 作用 |
45+
| --- | --- | --- | --- |
46+
| `containsKey` | `string key` | `bool` | 判断字典中是否包含指定键 |
47+
| `merge` | `dict dict` | `void` | 合并两个字典 |
48+
| `remove` | `string key` | `void` | 移除指定键的键值对 |

docs/zh/quickstart/08nbt/04map.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
---
2+
lastUpdate: true
3+
---
4+
5+
# MAP
6+
7+
为了弥补Minecraft原版NBT中复合标签在操作上的不便利,MCFPP封装了一种新的数据结构:`map``map`是一种键值对的数据结构,它的键只能是字符串,而值只能是同一种类型。
8+
9+
## 基本使用
10+
11+
使用`map<type T>`来声明一个`map`。和`dict`一样,在`map`中,可以使用`[]`来访问键值对。
12+
13+
```mcfpp
14+
map<int> m = {
15+
"a": 1,
16+
"b": 2,
17+
"c": 3
18+
};
19+
20+
print(m["a"]); #输出1
21+
22+
m["d"] = 4; #添加一个新的键值对
23+
```
24+
25+
## map的操作
26+
27+
MCFPP标准库提供了一系列的`map`操作函数。
28+
29+
| 函数名 | 参数 | 返回值 | 作用 |
30+
| --- | --- | --- | --- |
31+
| `clear` | `void` | `void` | 清空`map` |
32+
| `containsKey` | `string key` | `bool` | 判断`map`中是否包含指定键 |
33+
| `containsValue` | `T value` | `bool` | 判断`map`中是否包含指定值 |
34+
| `isEmpty` | `void` | `bool` | 判断`map`是否为空 |
35+
| `getKeys` | `void` | `list<string>` | 获取`map`中所有的键 |
36+
| `getValues` | `void` | `list<T>` | 获取`map`中所有的值 |
37+
| `remove` | `string key` | `void` | 移除指定键的键值对 |
38+
| `merge` | `map<T> map` | `void` | 合并两个`map` |
39+
| `size` | `void` | `int` | 获取`map`的大小 |
40+
41+
## map的遍历<Badge type="tip" text="未来特性" />
42+
43+
使用`foreach`循环可以简单地遍历`map`中的所有键值对。
44+
45+
```mcfpp
46+
map<int> m = {
47+
"a": 1,
48+
"b": 2,
49+
"c": 3
50+
};
51+
52+
foreach(k, v in m){
53+
print(k + ": " + v);
54+
}
55+
56+
foreach(k in m.getKeys()){
57+
print(k + ": " + m[k]);
58+
}
59+
60+
foreach(v in m.getValues()){
61+
print(v);
62+
}
63+
```
64+
65+
:::tip Tip
66+
`dict`仅由复合标签组成相比,`map`的结构更为复杂。通常来说,一个`map`由三个部分组成,即一个键的列表,一个值的列表,以及键值构成的复合标签。这种结构意味着,在写入的时候,`map`的开销将会比`dict`更高。但是这种结构同样也为`map`带来了更多的功能。
67+
68+
具体来说,以下面的代码为例:
69+
70+
```mcfpp
71+
map m = {};
72+
73+
m["qwq"] = "pwp";
74+
m["owo"] = "uwu";
75+
m["nya"] = "meow";
76+
```
77+
78+
在存储的时候,`map`的结构如下:
79+
80+
```js
81+
namespace.stack_frame:[
82+
{
83+
m:{
84+
key:["qwq","owo","nya"], //键列表
85+
value:["pwp","uwu","meow"], //值列表
86+
data:{
87+
"qwq":"pwp","owo":"uwu","nya":"meow" //键值对,相当于一个dict
88+
}
89+
}
90+
}
91+
]
92+
```
93+
94+
:::

docs/zh/quickstart/08template/01define-and-instantiate.md

Lines changed: 0 additions & 3 deletions
This file was deleted.

docs/zh/quickstart/08template/02template-parameters.md

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
lastUpdate: true
3+
---
4+
5+
# 数据模板
6+
7+
数据模板(Data Template)是一种类似于类的数据结构。数据模板完全基于NBT数据结构,但是和普通的NBT不同的是,数据模板规定了NBT的结构,或者说规定了NBT中有哪些成员,因此编译器能够在访问数据结构成员的时候进行检查。
8+
9+
## 定义
10+
11+
使用`data`关键字来定义一个数据模板。例如:
12+
13+
```mcfpp
14+
# 定义
15+
data Test{
16+
int a; # 一个整数
17+
nbt b; # 任意的NBT值
18+
}
19+
20+
func main(){
21+
# 创建对象
22+
Test t = Test();
23+
t.a = 5;
24+
t.b = {
25+
"key": "value"
26+
};
27+
28+
# 或者直接写入值
29+
Test t2 = {
30+
"a": 5,
31+
"b": {
32+
"key": "value"
33+
}
34+
};
35+
}
36+
```
37+
38+
使用`.`来访问一个数据模板中的成员。
39+
40+
```mcfpp
41+
print(t.a);
42+
print(t.b);
43+
```
44+
45+
和类一样,你可以在数据模板中定义一些方法。
46+
47+
```mcfpp
48+
data Test{
49+
int a;
50+
nbt b;
51+
52+
func print(){
53+
print(this.a);
54+
print(this.b);
55+
}
56+
}
57+
```
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
lastUpdate: true
3+
---
4+
5+
# 数据模板的嵌套
6+
7+
如果一个数据模板中,有另一个数据模板类型的变量作为成员,那么就可以实现数据模板的嵌套。
8+
9+
## 基本使用
10+
11+
```mcfpp
12+
data A{
13+
int valueA;
14+
}
15+
16+
data B{
17+
int valueB;
18+
A dataA;
19+
}
20+
21+
func main(){
22+
//创建对象
23+
B b = B();
24+
A a = A();
25+
a.valueA = 5;
26+
b.valueB = 5;
27+
b.dataA = A();
28+
29+
//或者直接赋值
30+
B qwq = {
31+
"valueB": 5,
32+
"dataA": {
33+
"valueA": 5
34+
}
35+
};
36+
37+
//访问
38+
print(b.valueB);
39+
print(b.dataA.valueA);
40+
}
41+
```
42+
43+
当然,使用自身类型作为数据模板的成员是不被允许的。

0 commit comments

Comments
 (0)