From fac4a4cd231bc5939b127fe8431e2aa45282bc63 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Wed, 24 Apr 2024 21:13:10 +0800
Subject: [PATCH 01/87] Update README.md
---
README.md | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/README.md b/README.md
index 07c79632a..93ec6e470 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,28 @@
-# NeoForged Documentation
+# NeoForge 文档
-This repository is used to store documentation on NeoForge, the Minecraft modding API. It also contains documentation on NeoGradle, a Gradle plugin for developing NeoForge and mods using NeoForge.
+此存储库用于存储有关NeoForge的文档,NeoForge是Minecraft模组开发的API。它还包含有关NeoGradle的文档,NeoGradle是一个用于开发NeoForge和使用NeoForge的模组的Gradle插件。
-The documentation is built using [Docusaurus 2](https://docusaurus.io)
+该文档使用[Docusaurus 2](https://docusaurus.io)构建
-## Contributing
+## 贡献
-You can read the [contribution guidelines on the docs](https://docs.neoforged.net/contributing/).
+您可以在[文档贡献指南](https://docs.neoforged.net/contributing/)中阅读贡献指南
-If you wish to contribute to the documentation, fork and clone this repository.
+如果您希望为文档做出贡献,请 fork 并 clone 此存储库。
-You can run the following commands if you wish to preview the documentation website locally through the live development server. Most changes are reflected live without having to restart the server.
+如果您想通过实时开发服务器在本地预览文档网站,可以运行以下命令。大多数更改都会实时反馈,无需重新启动服务器。
```bash
npm install
npm run start
```
-### Building
+### 构建
-If you wish to build a static version of the documentation which can be deployed, you can run the following command:
+如果您希望构建可部署的静态版本的文档,您可以运行以下命令:
```
npm run build
```
-This command generates static content into the `build` directory and can be served using any static contents hosting service.
+此命令会生成静态内容到`build`目录,并可以使用任何静态内容托管服务来提供服务。
From 29e29382ef87a6541315e108344cafeb5fe7f3bf Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Wed, 24 Apr 2024 22:01:21 +0800
Subject: [PATCH 02/87] Update accesstransformers.mdx
---
docs/advanced/accesstransformers.mdx | 125 +++++++++++++--------------
1 file changed, 62 insertions(+), 63 deletions(-)
diff --git a/docs/advanced/accesstransformers.mdx b/docs/advanced/accesstransformers.mdx
index b8a625ff0..070244e03 100644
--- a/docs/advanced/accesstransformers.mdx
+++ b/docs/advanced/accesstransformers.mdx
@@ -3,21 +3,21 @@ import TabItem from '@theme/TabItem';
# Access Transformers
-Access Transformers (ATs for short) allow for widening the visibility and modifying the `final` flags of classes, methods, and fields. They allow modders to access and modify otherwise inaccessible members in classes outside their control.
+Access Transformers (简称 ATs) 允许开发者扩大类、方法和字段的可见性,以及修改其`final`属性。这些工具使得模组开发者能够访问和修改通常无法访问的类成员。
-The [specification document][specs] can be viewed on the NeoForged GitHub.
+[规范文档][specs]可以在NeoForged的GitHub上查看。
-## Adding ATs
+## 添加 ATs
-Adding an Access Transformer to your mod project is as simple as adding a single line into your `build.gradle`:
+将 Access Transformer 添加到您的 mod 项目与在 `build.gradle` 中添加一行代码一样简单:
-Access Transformers need to be declared in both `build.gradle` and `mods.toml`:
+Access Transformers 需要在 `build.gradle` 和 `mods.toml` 中声明:
```groovy
-// In build.gradle:
-// This block is where your mappings version is also specified
+// 在 build.gradle 中:
+// 此部分也是指定映射版本的地方
minecraft {
accessTransformers {
file('src/main/resources/META-INF/accesstransformer.cfg')
@@ -26,14 +26,14 @@ minecraft {
```
```toml
-# In mods.toml:
+# 在 mods.toml 中:
[[accessTransformers]]
file="META-INF/accesstransformer.cfg"
```
-AT files can be anywhere specified by the lines above, though NeoForge will default to searching for `META-INF/accesstransformer.cfg` if no other file is specified.
+AT 文件可以位于上面几行指定的任何位置,但如果没有指定其他文件,NeoForge 将默认搜索`META-INF/accesstransformer.cfg`。
-Additionally, multiple AT files can be specified and will be applied in order. This can be useful for larger mods with multiple packages.
+此外,可以指定多个 AT 文件并按顺序应用。 这对于具有多个软件包的大型模组非常有用。
```groovy
// In build.gradle:
@@ -54,103 +54,102 @@ file="accesstransformer_main.cfg"
file="accesstransformer_additions.cfg"
```
-After adding or modifying any Access Transformer, the Gradle project must be refreshed for the transformations to take effect.
+添加或修改任何访问转换器后,必须刷新Gradle项目,以便使更改生效。
-Adding an Access Transformer to your mod project is as simple as adding a single line into your `build.gradle`:
+在你的模组项目中添加一个 AT 也很简单,只需在`build.gradle`中添加一行代码:
```groovy
-// This block is where your mappings version is also specified
+// 这一部分也是你指定映射版本的地方
minecraft {
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
}
```
-During development, the AT file can be anywhere specified by the line above. However, when loading in a non-development environment, NeoForge will only search for the exact path of `META-INF/accesstransformer.cfg` in your JAR file.
+在开发环境中,AT文件可以放在上述指定的任何位置。然而,在非开发环境中加载时,NeoForge只会搜索你的JAR文件中 `META-INF/accesstransformer.cfg` 的确切路径。
-After adding or modifying the Access Transformer, the Gradle project must be refreshed for the transformations to take effect.
+添加或修改访问转换器后,必须刷新Gradle项目,以便使更改生效。
-## Comments
+## 注释
-All text after a `#` until the end of the line will be treated as a comment and will not be parsed.
+`#` 之后直到行尾的所有文本都将被视为注释并且不会被解析。
-## Access Modifiers
+## 访问控制修饰符
-Access modifiers specify to what new member visibility the given target will be transformed to. In decreasing order of visibility:
+访问控制修饰符指明目标将被转换到的新的成员的可见性。按可见性递减的顺序排列如下:
-* `public` - visible to all classes inside and outside its package
-* `protected` - visible only to classes inside the package and subclasses
-* `default` - visible only to classes inside the package
-* `private` - visible only to inside the class
+* `public` - 对包内外的所有类可见
+* `protected` - 只对包内的类和子类可见
+* `default` - 只对包内的类可见
+* `private` - 只对类的内部可见
-A special modifier `+f` and `-f` can be appended to the aforementioned modifiers to either add or remove respectively the `final` modifier, which prevents subclassing, method overriding, or field modification when applied.
+特殊修饰符`+f`和`-f`可以分别添加到上述的修饰符之后,用以添加或移除`final`修饰符,当应用时可防止子类化、方法覆盖或字段修改。
:::danger
-Directives only modify the method they directly reference; any overriding methods will not be access-transformed. It is advised to ensure transformed methods do not have non-transformed overrides that restrict the visibility, which will result in the JVM throwing an error.
+指令只修改直接引用的方法;任何覆盖的方法都不会被转换。建议确保转换的方法没有未转换覆盖的方法,否则这会限制其可见性,并可能导致 JVM 报错。
-Examples of methods that can be safely transformed are `private` methods, `final` methods (or methods in `final` classes), and `static` methods.
+可以安全转换的方法示例包括`private`方法、`final`方法(或`final`类中的方法)以及`static`方法。
:::
-## Targets and Directives
+## 目标和指令
-### Classes
-To target classes:
+### 类
+定位类的格式如下:
```
```
-Inner classes are denoted by combining the fully qualified name of the outer class and the name of the inner class with a `$` as separator.
+内部类通过组合外部类的完全限定名和内部类名,使用`$`作为分隔符来表示。
-### Fields
-To target fields:
+### 字段
+定位字段的格式如下:
```
```
-### Methods
-Targeting methods require a special syntax to denote the method parameters and return type:
+### 方法
+定位方法需要特殊的语法来表示方法参数和返回类型:
```
()
```
-#### Specifying Types
-
-Also called "descriptors": see the [Java Virtual Machine Specification, SE 8, sections 4.3.2 and 4.3.3][jvmdescriptors] for more technical details.
-
-* `B` - `byte`, a signed byte
-* `C` - `char`, a Unicode character code point in UTF-16
-* `D` - `double`, a double-precision floating-point value
-* `F` - `float`, a single-precision floating-point value
-* `I` - `integer`, a 32-bit integer
-* `J` - `long`, a 64-bit integer
-* `S` - `short`, a signed short
-* `Z` - `boolean`, a `true` or `false` value
-* `[` - references one dimension of an array
- * Example: `[[S` refers to `short[][]`
-* `L;` - references a reference type
- * Example: `Ljava/lang/String;` refers to `java.lang.String` reference type _(note the use of slashes instead of periods)_
-* `(` - references a method descriptor, parameters should be supplied here or nothing if no parameters are present
- * Example: `(I)Z` refers to a method that requires an integer argument and returns a boolean
-* `V` - indicates a method returns no value, can only be used at the end of a method descriptor
- * Example: `()V` refers to a method that has no arguments and returns nothing
-
-## Examples
-
+#### 指定类型
+
+也称为"描述符":有关更多技术细节,请参见[Java虚拟机规范,SE 8,第4.3.2节和4.3.3节]。
+
+* `B` - `byte`, 有符号字节
+* `C` - `char`, Unicode字符代码点,使用UTF-16编码
+* `D` - `double`, 双精度浮点值
+* `F` - `float`, 单精度浮点值
+* `I` - `integer`,32位整数
+* `J` - `long`,64位整数
+* `S` - `short`,有符号短整数
+* `Z` - `boolean`,`true`或`false`值
+* `[` - 表示数组的一个维度
+ * 示例: `[[S` 表示 `short[][]`
+* `L;` - 表示引用类型
+ * 示例: `Ljava/lang/String;` 表示 `java.lang.String` 引用类型 _(注意使用斜线而非点)_
+* `(` - 表示方法描述符,参数应在此处提供,如果没有参数则不提供
+ * 示例: `(I)Z` 表示一个需要整型参数并返回布尔值的方法
+* `V` - 表示方法不返回值,只能在方法描述符的末尾使用
+ * 示例: `()V` 表示一个没有参数并且不返回任何结果的方法
+
+## 示例
```
-# Makes public the ByteArrayToKeyFunction interface in Crypt
+# 将Crypt中的ByteArrayToKeyFunction接口公开
public net.minecraft.util.Crypt$ByteArrayToKeyFunction
-# Makes protected and removes the final modifier from 'random' in MinecraftServer
+# 将MinecraftServer中的'random'字段设为protected并移除final修饰
protected-f net.minecraft.server.MinecraftServer random
-# Makes public the 'makeExecutor' method in Util,
-# accepting a String and returns an ExecutorService
+# 将Util中的'makeExecutor'方法公开,
+# 接受一个String并返回一个ExecutorService
public net.minecraft.Util makeExecutor(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService;
-# Makes public the 'leastMostToIntArray' method in UUIDUtil,
-# accepting two longs and returning an int[]
+# 将UUIDUtil中的'leastMostToIntArray'方法公开,
+# 接受两个long并返回一个int数组
public net.minecraft.core.UUIDUtil leastMostToIntArray(JJ)[I
```
From aa0697fff859835d565e5f179927058975ffb2c0 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Wed, 24 Apr 2024 22:04:20 +0800
Subject: [PATCH 03/87] Update accesstransformers.mdx
---
docs/advanced/accesstransformers.mdx | 62 ++++++++++++++++------------
1 file changed, 36 insertions(+), 26 deletions(-)
diff --git a/docs/advanced/accesstransformers.mdx b/docs/advanced/accesstransformers.mdx
index 070244e03..829efaf09 100644
--- a/docs/advanced/accesstransformers.mdx
+++ b/docs/advanced/accesstransformers.mdx
@@ -3,9 +3,9 @@ import TabItem from '@theme/TabItem';
# Access Transformers
-Access Transformers (简称 ATs) 允许开发者扩大类、方法和字段的可见性,以及修改其`final`属性。这些工具使得模组开发者能够访问和修改通常无法访问的类成员。
+Access Transformers (简称 ATs) 允许开发者扩大类、方法和字段的可见性,以及修改其 `final` 属性。这些工具使得模组开发者能够访问和修改通常无法访问的类成员。
-[规范文档][specs]可以在NeoForged的GitHub上查看。
+[规范文档][specs]可以在 NeoForged 的 GitHub 上查看。
## 添加 ATs
@@ -31,7 +31,7 @@ minecraft {
file="META-INF/accesstransformer.cfg"
```
-AT 文件可以位于上面几行指定的任何位置,但如果没有指定其他文件,NeoForge 将默认搜索`META-INF/accesstransformer.cfg`。
+AT 文件可以位于上面几行指定的任何位置,但如果没有指定其他文件,NeoForge 将默认搜索 `META-INF/accesstransformer.cfg`。
此外,可以指定多个 AT 文件并按顺序应用。 这对于具有多个软件包的大型模组非常有用。
@@ -54,11 +54,11 @@ file="accesstransformer_main.cfg"
file="accesstransformer_additions.cfg"
```
-添加或修改任何访问转换器后,必须刷新Gradle项目,以便使更改生效。
+添加或修改任何访问转换器后,必须刷新 Gradle 项目,以便使更改生效。
-在你的模组项目中添加一个 AT 也很简单,只需在`build.gradle`中添加一行代码:
+在你的模组项目中添加一个 AT 也很简单,只需在 `build.gradle` 中添加一行代码:
```groovy
// 这一部分也是你指定映射版本的地方
@@ -67,9 +67,9 @@ minecraft {
}
```
-在开发环境中,AT文件可以放在上述指定的任何位置。然而,在非开发环境中加载时,NeoForge只会搜索你的JAR文件中 `META-INF/accesstransformer.cfg` 的确切路径。
+在开发环境中,AT 文件可以放在上述指定的任何位置。然而,在非开发环境中加载时,NeoForge 只会搜索你的 JAR 文件中 `META-INF/accesstransformer.cfg` 的确切路径。
-添加或修改访问转换器后,必须刷新Gradle项目,以便使更改生效。
+添加或修改访问转换器后,必须刷新 Gradle 项目,以便使更改生效。
@@ -86,70 +86,80 @@ minecraft {
* `default` - 只对包内的类可见
* `private` - 只对类的内部可见
-特殊修饰符`+f`和`-f`可以分别添加到上述的修饰符之后,用以添加或移除`final`修饰符,当应用时可防止子类化、方法覆盖或字段修改。
+特殊修饰符 `+f` 和 `-f` 可以分别添加到上述的修饰符之后,用以添加或移除 `final` 修饰符,当应用时可防止子类化、方法覆盖或字段修改。
:::danger
指令只修改直接引用的方法;任何覆盖的方法都不会被转换。建议确保转换的方法没有未转换覆盖的方法,否则这会限制其可见性,并可能导致 JVM 报错。
-可以安全转换的方法示例包括`private`方法、`final`方法(或`final`类中的方法)以及`static`方法。
+可以安全转换的方法示例包括 `private` 方法、`final` 方法(或 `final` 类中的方法)以及 `static` 方法。
:::
## 目标和指令
### 类
+
定位类的格式如下:
+
```
```
-内部类通过组合外部类的完全限定名和内部类名,使用`$`作为分隔符来表示。
+
+内部类通过组合外部类的完全限定名和内部类名,使用 `$` 作为分隔符来表示。
### 字段
+
定位字段的格式如下:
+
```
```
### 方法
+
定位方法需要特殊的语法来表示方法参数和返回类型:
+
```
()
```
#### 指定类型
-也称为"描述符":有关更多技术细节,请参见[Java虚拟机规范,SE 8,第4.3.2节和4.3.3节]。
+也称为"描述符":有关更多技术细节,请参见 [Java 虚拟机规范,SE 8,第 4.3.2 节和 4.3.3 节][jvmdescriptors]。
-* `B` - `byte`, 有符号字节
-* `C` - `char`, Unicode字符代码点,使用UTF-16编码
-* `D` - `double`, 双精度浮点值
-* `F` - `float`, 单精度浮点值
-* `I` - `integer`,32位整数
-* `J` - `long`,64位整数
+* `B` - `byte`,有符号字节
+* `C` - `char`,Unicode 字符代码点,使用 UTF-16 编码
+* `D` - `double`,双精度浮点值
+* `F` - `float`,单精度浮点值
+* `I` - `integer`,32 位整数
+* `J` - `long`,64 位整数
* `S` - `short`,有符号短整数
-* `Z` - `boolean`,`true`或`false`值
+* `Z` - `boolean`,`true` 或 `false` 值
* `[` - 表示数组的一个维度
* 示例: `[[S` 表示 `short[][]`
* `L;` - 表示引用类型
- * 示例: `Ljava/lang/String;` 表示 `java.lang.String` 引用类型 _(注意使用斜线而非点)_
+ * 示例: `Ljava/lang/String;` 表示 `java.lang.String` 引
+
+用类型 _(注意使用斜线而非点)_
* `(` - 表示方法描述符,参数应在此处提供,如果没有参数则不提供
- * 示例: `(I)Z` 表示一个需要整型参数并返回布尔值的方法
+ * 示例: `(I)Z` 表示一个需要整型参数并返回布尔值的方法
* `V` - 表示方法不返回值,只能在方法描述符的末尾使用
* 示例: `()V` 表示一个没有参数并且不返回任何结果的方法
## 示例
+
```
-# 将Crypt中的ByteArrayToKeyFunction接口公开
+# 将 Crypt 中的 ByteArrayToKeyFunction 接口公开
public net.minecraft.util.Crypt$ByteArrayToKeyFunction
-# 将MinecraftServer中的'random'字段设为protected并移除final修饰
+# 将 MinecraftServer 中的 'random' 字段设为 protected 并移除 final 修饰
protected-f net.minecraft.server.MinecraftServer random
-# 将Util中的'makeExecutor'方法公开,
-# 接受一个String并返回一个ExecutorService
+# 将 Util 中的 'makeExecutor' 方法公开,
+# 接受一个 String 并返回一个 ExecutorService
public net.minecraft.Util makeExecutor(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService;
-# 将UUIDUtil中的'leastMostToIntArray'方法公开,
-# 接受两个long并返回一个int数组
+# 将 UUIDUtil 中的 'leastMostToIntArray' 方法公开,
+# 接受两个 long 并返回一个 int 数组
public net.minecraft.core.UUIDUtil leastMostToIntArray(JJ)[I
```
From 61e61361150882ac30f9e08e9311e9b954cff0ea Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 10:06:00 +0800
Subject: [PATCH 04/87] Update index.md
---
neogradle/docs/index.md | 32 ++++++++++++++------------------
1 file changed, 14 insertions(+), 18 deletions(-)
diff --git a/neogradle/docs/index.md b/neogradle/docs/index.md
index 85e36cf2e..8bf750c2b 100644
--- a/neogradle/docs/index.md
+++ b/neogradle/docs/index.md
@@ -1,48 +1,44 @@
----
-sidebar_position: 0
----
-
-NeoGradle Documentation
+NeoGradle 文档
=========================
-:::caution
-Please note that this documentation may not be up to date considering the recent creation of NeoForged.
+:::注意
+请注意,鉴于NeoForged的最近创建,本文档可能不是最新的。
-Until NeoGradle releases its first version, you should refer to ForgeGradle documentation. The ForgeGradle documentation for versions 6 and 5 has been archived here.
+在NeoGradle发布其首个版本之前,您应该参考ForgeGradle的文档。版本6和5的ForgeGradle文档已存在这里。
:::
-This is the official documentation for [ForgeGradle], a [Gradle] plugin for developing [MinecraftForge] and mods using MinecraftForge.
+这是[ForgeGradle]官方文档,一个用于使用MinecraftForge开发[MinecraftForge]和mods的[Gradle]插件。
-This documentation is _only_ for ForgeGradle, **this is not a Java, Groovy, or Gradle tutorial**.
+这份文档 _仅_ 适用于ForgeGradle,**这不是Java、Groovy或Gradle教程**。
-If you would like to contribute to the docs, read [Contributing to the Docs][contributing].
+如果您想为文档贡献内容,请阅读[为文档做贡献][contributing]。
-Adding the Plugin
+添加插件
-----------------
-ForgeGradle uses Gradle 8; it can be added using the `plugins` block in the `build.gradle` by adding the following information to the `settings.gradle`:
+ForgeGradle 使用 Gradle 8;它可以通过在 `build.gradle` 的 `plugins` 区块中添加以下信息到 `settings.gradle` 来添加:
```gradle
-// In settings.gradle
+// 在 settings.gradle 中
pluginManagement {
repositories {
// ...
- // Add the MinecraftForge maven
+ // 添加 MinecraftForge maven
maven { url = 'https://maven.minecraftforge.net/' }
}
}
plugins {
- // Add toolchain resolver
+ // 添加工具链解析器
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
}
```
```gradle
-// In build.gradle
+// 在 build.gradle 中
plugins {
- // Add the ForgeGradle plugin
+ // 添加 ForgeGradle 插件
id 'net.minecraftforge.gradle' version '[6.0,6.2)'
// ...
From e29f5f519a3105cb79c135687eec6e2440f6411b Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 10:10:34 +0800
Subject: [PATCH 05/87] Update 5.x_to_6.0.md
---
neogradle/docs/5.x_to_6.0.md | 62 ++++++++++++++++++------------------
1 file changed, 31 insertions(+), 31 deletions(-)
diff --git a/neogradle/docs/5.x_to_6.0.md b/neogradle/docs/5.x_to_6.0.md
index c727abdb1..dfb47d272 100644
--- a/neogradle/docs/5.x_to_6.0.md
+++ b/neogradle/docs/5.x_to_6.0.md
@@ -1,92 +1,92 @@
-# ForgeGradle 5 -> 6 Migration Primer
+# ForgeGradle 5到6迁移指南
-This is a high level, non-exhaustive overview on how to migrate your buildscript from ForgeGradle 5 to 6.
+这是一个从ForgeGradle 5迁移到6的高层次、非详尽的概览。
-## Add Foojay Toolchains Plugin
+## 添加 Foojay 工具链插件
-Gradle now uses the [Foojay Toolchains Plugin](https://github.com/gradle/foojay-toolchains) to manage the Java toolchain. The plugin must be added to the `settings.gradle[.kts]`:
+Gradle 现在使用 [Foojay 工具链插件](https://github.com/gradle/foojay-toolchains) 来管理 Java 工具链。该插件必须添加到 `settings.gradle[.kts]` 中:
-With Gradle DSL:
+使用 Gradle DSL:
```gradle
-// In settings.gradle
+// 在 settings.gradle 中
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0'
}
```
-With Kotlin DSL:
+使用 Kotlin DSL:
```kotlin
-// In settings.gradle.kts
+// 在 settings.gradle.kts 中
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
}
```
-## Update Gradle to 8.1.1
+## 更新 Gradle 至 8.1.1
-First, you need to update your Gradle Wrapper to use 8.1.1. You can find additional information regarding the migration process from 7 to 8 on [Gradle's migration guide](https://docs.gradle.org/current/userguide/upgrading_version_7.html).
+首先,你需要更新你的 Gradle Wrapper 使用 8.1.1 版本。你可以在 [Gradle迁移指南](https://docs.gradle.org/current/userguide/upgrading_version_7.html) 上找到有关从 7 到 8 版本迁移的更多信息。
-This can be done in one of two ways:
+这可以通过以下两种方式之一完成:
### `gradle wrapper`
-The preferred option is to use the `gradle wrapper` command with the `--gradle-version` option.
+首选的选项是使用 `gradle wrapper` 命令与 `--gradle-version` 选项。
```bash
-# Inside root directory of the gradle project
+# 在gradle项目的根目录内
./gradlew wrapper --gradle-version=8.1.1
```
### gradle-wrapper.properties
-This method is not recommended, and it should only be used if the `gradlew wrapper` command above fails.
+这种方法不推荐,仅当上面的 `gradlew wrapper` 命令失败时使用。
-Update the version in the `distributionUrl` property within `gradle/wrapper/gradle-wrapper.properties`. Afterwards run `./gradlew wrapper`.
+更新 `gradle/wrapper/gradle-wrapper.properties` 内的 `distributionUrl` 属性中的版本。之后运行 `./gradlew wrapper`。
```properties
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
```
-## Update ForgeGradle Plugin Version
+## 更新 ForgeGradle 插件版本
-After updating Gradle, update the `ForgeGradle` version in your `build.gradle[.kts]` to `[6.0,6.2)`:
+更新 Gradle 后,在你的 `build.gradle[.kts]` 中更新 `ForgeGradle` 版本到 `[6.0,6.2)`:
-With Gradle DSL:
+使用 Gradle DSL:
```gradle
-// In build.gradle
+// 在 build.gradle 中
plugins {
id 'net.minecraftforge.gradle' version '[6.0,6.2)'
}
```
-With Kotlin DSL:
+使用 Kotlin DSL:
```kotlin
-// In build.gradle.kts
+// 在 build.gradle.kts 中
plugins {
id("net.minecraftforge.gradle") version "[6.0,6.2)"
}
```
-## Remove `forceExit` from Run Configurations
+## 从运行配置中移除 `forceExit`
-ForgeGradle has now removed the `forceExit` property in run configurations. Changes to run tasks only apply to the current project and not any subprojects.
+ForgeGradle 现在已经移除了运行配置中的 `forceExit` 属性。对运行任务的更改仅适用于当前项目而不适用于任何子项目。
-### Minor Additions, Changes, Removals
+### 小的添加、更改、移除
-### Reobfuscated Classpath Inheritance
+### 重混淆类路径继承
-If you were using `classpath.from` within a `reobf*` task configuration to declare extra libraries, the `reobf*` task needed to take into account; it should be migrated to the `libraries.from` property instead.
+如果你在 `reobf*` 任务配置中使用了 `classpath.from` 来声明额外库,必须要考虑的 `reobf*` 任务;它应该迁移至 `libraries.from` 属性而不是。
-### Eclipse Launcher Groups
+### Eclipse 启动器组
-If ForgeGradle is setup such that Eclipse should run the Gradle tasks before starting the game, you must execute the run configuration from the `Launch Group` folder. This is only true if new properties are enabled within the `minecraft` block.
+如果设置了 ForgeGradle 使 Eclipse 在开始游戏之前运行 Gradle 任务,你必须从 `Launch Group` 文件夹执行运行配置。如果在 `minecraft` 块中启用了新属性,这只是正确的。
-![Eclipse launch groups demo](/img/eclipse_launch_groups.png)
+![Eclipse 启动器组演示](/img/eclipse_launch_groups.png)
-### Removal of `resources` and `classes` in ModConfig
+### 在 ModConfig 中移除 `resources` 和 `classes`
-The properties `resources` and `classes` within the `mods` block of a run configuration have been removed from ForgeGradle 6.
+在 ForgeGradle 6中,运行配置的 `mods` 块内的 `resources` 和 `classes` 属性已被移除。
From 7dc792270e53b2d8a3243a62043b132e1013ad12 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 10:12:26 +0800
Subject: [PATCH 06/87] Update advanced.md
---
neogradle/docs/configuration/advanced.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/neogradle/docs/configuration/advanced.md b/neogradle/docs/configuration/advanced.md
index d5537bb96..3c15496d9 100644
--- a/neogradle/docs/configuration/advanced.md
+++ b/neogradle/docs/configuration/advanced.md
@@ -1,15 +1,15 @@
-Advanced Configurations
+高级配置
=======================
-ForgeGradle contains a few specific or nuanced configuration techniques depending on the complexity of your build project.
+ForgeGradle 包含了一些特定的或细微的配置技术,这些技术取决于构建项目的复杂性。
-Reobfuscating Source Sets
+重混淆源集
-------------------------
-By default, the `reobf*` abd `rename*` tasks only contain files on the main source set's classpath. To reobfuscate files on a different classpath, they need to be added to the `libraries` property within the task.
+默认情况下,`reobf*` 和 `rename*` 任务只包含主源集类路径上的文件。要重混淆不同类路径上的文件,需要将它们添加到任务中的 `libraries` 属性。
```gradle
-// Adds another source set's classpath to 'reobf' task.
+// 将另一个源集的类路径添加到 'reobf' 任务。
tasks.withType('reobfJar') {
libraries.from sourceSets.api.classpath
}
From a9d264ce4f27687ae392b6a86c99f15cc90d5287 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 10:39:19 +0800
Subject: [PATCH 07/87] Update index.mdx
---
neogradle/docs/configuration/index.mdx | 76 +++++++++++++-------------
1 file changed, 37 insertions(+), 39 deletions(-)
diff --git a/neogradle/docs/configuration/index.mdx b/neogradle/docs/configuration/index.mdx
index 66c25d9fe..c7d6b933b 100644
--- a/neogradle/docs/configuration/index.mdx
+++ b/neogradle/docs/configuration/index.mdx
@@ -1,36 +1,35 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-ForgeGradle Configurations
+ForgeGradle 配置
==========================
-ForgeGradle has numerous configurations that can change how the development environment is configured. Most configurations are set using the `minecraft` block; however, some others can be specified within the `dependencies` block or modify the built `jar`, such as `reobfJar`.
+ForgeGradle 提供了众多配置选项,以便改变开发环境的配置方式。大部分的配置通过 `minecraft` 代码块设置,但一些其他配置可以在 `dependencies` 代码块内指定,或修改构建的 `jar`,例如 `reobfJar`。
-Enabling Access Transformers
+启用 Access Transformer
----------------------------
-
-[Access Transformers][at] can widen the visibility or modify the `final` flag of Minecraft classes, methods, and fields.
+[Access Transformer][at]可以扩大 Minecraft 类、方法和字段的可见性或修改它们的 `final` 标志。
-
-To enable Access Transformers in the production environment, you can set `accessTransformers` to the configuration file in question:
+
+要在开发环境中启用 Access Transformer ,您可以在 `minecraft` 代码块中设置 `accessTransformers` 到相关的配置文件:
```gradle
minecraft {
// ...
- // Add an Access Transformer file relative to the project's directory
+ // 添加一个AT文件,相对于项目目录
accessTransformers {
file('src/main/resources/META-INF/accesstransformer.cfg')
- // Multiple files can be specified and are applied in order
+ // 可以指定多个文件,按顺序应用
file('src/main/resources/accesstransformer_extras.cfg')
}
}
```
-In production, NeoForge will search for Access Transformer files as specified in `mods.toml`, or at `META-INF/accesstransformer.cfg` if none are specified:
+在开发环境中,NeoForge 会根据 `mods.toml` 中指定的搜索AT文件,或者在没有指定的情况下搜索 `META-INF/accesstransformer.cfg`:
```toml
[[accessTransformers]]
@@ -43,48 +42,48 @@ file="accesstransformer_extras.cfg"
-
-To enable Access Transformers in the production environment, you can set `accessTransformer` to the configuration file in question:
+
+要在开发环境中启用AT,您可以将 `accessTransformer` 设置到相关配置文件:
```gradle
minecraft {
// ...
- // Add an access transformer file relative to the project's directory
+ // 添加一个AT文件,相对于项目目录
accessTransformer = project.file('src/main/resources/META-INF/accesstransformer.cfg')
}
```
:::caution
-While the Access Transformer in the development environment can be read from anywhere the user specifies, in production, the file will only be read from `META-INF/accesstransformer.cfg`.
+虽然在开发环境中的AT可以从用户指定的任何位置读取,在开发环境中,文件只能从 `META-INF/accesstransformer.cfg` 读取。
:::
-Human-Readable Mappings
+人类可读映射
-----------------------
-Minecraft's source code is obfuscated. As such, all classes, methods, and fields have machine-generated names with no package structures. Function-local variable names, meanwhile, are turned into a snowman (`☃`) due to how the Local Variable Table is stored. It is difficult to create mods using obfuscated names as reverse engineering them is tedious, may change between versions, and may be invalid in the language itself but not in the bytecode.
+Minecraft 的源代码是混淆的。因此,所有的类、方法和字段都有机器生成的名称,没有包结构。与此同时,函数本地变量名称被转换为雪人(`☃`),因为本地变量表的存储方式。使用这些混淆名称创建模组非常困难,因为给它们做逆向工程既繁琐,又可能在版本之间发生变化,且可能在语言本身中无效,但在字节码中有效。
-To address the last two issues, Forge fuzzily maps each class, method, field, and parameter to a unique identifier, known as the SRG name, via the [ForgeAutoRenamingTool][fart]. SRG mappings are used in production when the game is being run by the user client.
+为了解决这最后两个问题,Forge 通过 [ForgeAutoRenamingTool][fart] (Forge 自动重命名工具),模糊地将每个类、方法、字段和参数映射到一个唯一的标识符,即 SRG 名称。当用户客户端运行游戏时,会使用 SRG 映射。
-To allow easier development, ForgeGradle allows the user to choose a mapping set to apply on top of SRG mappings, which we will refer to as human-readable mappings. ForgeGradle knows how to convert the mod jar to SRG mappings for use in production via the `reobf*` task.
+为了简化开发,ForgeGradle 允许用户选择一个映射集来应用在 SRG 映射之上,我们将其称为人类可读映射。ForgeGradle 知道如何通过 `reobf*` 任务将模组 jar 转换为 SRG 映射,以便在生产中使用。
-The mapping set used can be specified by setting the `mappings` field in the `minecraft` block. The `mappings` field takes in two arguments: `channel` which is the type of the mapping set, and `version` which is the version of the mapping set to apply.
+可以通过在 `minecraft` 块中设置 `mappings` 字段来指定所使用的映射集。`mappings` 字段接受两个参数:`channel` 是映射集的类型,而 `version` 是要应用的映射集的版本。
-Currently, there are three default mapping sets built into ForgeGradle:
+目前,ForgeGradle 内置了三套默认的映射集:
-* `official` - This uses the mapping set provided by Mojang. These mappings do not have parameter names and only exist from 1.14 onward.
-* `stable` - This uses a mapping set generated by MCP. These are typically incomplete and no longer exist as of 1.17.
-* `snapshot` - This also is a mapping set generated by MCP, similar to a nightly build of a program. These are also typically incomplete and no longer exist as of 1.17.
+* `official` - 使用 Mojang 提供的映射集。这些映射没有参数名称,只从 1.14 版本开始存在。
+* `stable` - 使用由 MCP 生成的映射集。这些通常不完整,并且从 1.17 版本开始就不再存在。
+* `snapshot` - 这也是 MCP 生成的映射集,类似于程序的每日版构建。这些也通常不完整,并从 1.17 版本开始就不再存在。
:::info
-The class names used in production are from `stable` prior to 1.17 and from `official` from 1.17 onwards.
+生产中使用的类名称来自 1.17 版本之前的 `stable` 映射集,从 1.17 版本开始则来自 `official` 映射集。
:::
```gradle
mappings {
- // Sets the mappings to use those from Mojang for Minecraft 1.19.4.
+ // 设置映射 使用 Mojang 提供的 Minecraft 1.19.4 版本映射。
mappings channel: 'official', version: '1.19.4'
// ...
@@ -93,50 +92,49 @@ mappings {
### Parchment
-Parchment is an official project maintained by ParchmentMC which provides open, community-sourced parameter names and javadocs on top of the `official` mapping set. You can learn how setup and use the parchment mapping set on [their website][parchment].
+Parchment 是 ParchmentMC 维护的官方项目,它在 `official` 映射集之上提供了开放的、社区来源的参数名称和 javadocs。你可以在[它们的网站][parchment]上了解如何设置和使用 Parchment 映射集。
-Preparing Run Tasks
+准备运行任务
-------------------
-Run tasks (`run*`) have two separate pipelines depending on whether they are executed through `gradlew` or a run configuration. By default, there are two tasks that prepare the workspace for execution:
+运行任务(`run*`)有两个独立的处理流程,这取决于它们是通过 `gradlew` 还是通过运行配置执行的。默认情况下,有两个任务负责准备工作区以执行游戏:
-First, there are `prepare*` tasks which are executed before `run*` tasks and ensure that mapping files are prepared for the game. The `prepare*Compile` task is typically only executed as a dependency of `run*` tasks to make sure that the game is compiled before it is run.
+首先,有 `prepare*` 任务,这些任务在 `run*` 任务之前执行,以确保游戏的映射文件已准备好。`prepare*Compile` 任务通常只作为 `run*` 任务的依赖项执行,以确保在运行游戏之前先将游戏编译好。
-If your IDE is either Eclipse or IntelliJ IDEA, the run configuration can be configured to execute the `prepare*` tasks before starting the game by setting `enableEclipsePrepareRuns` or `enableIdeaPrepareRuns`, respectively, to `true`. This will allow you to invoke custom Gradle tasks before your IDE launches the game.
+如果你使用的 IDE 是 Eclipse 或 IntelliJ IDEA,可以通过分别将 `enableEclipsePrepareRuns` 或 `enableIdeaPrepareRuns` 设置为 `true` 来配置运行配置,在启动游戏之前执行 `prepare*` 任务。这将允许你在 IDE 启动游戏之前调用自定义的 Gradle 任务。
```gradle
minecraft {
// ...
- // Enable the 'prepare*' task for run configurations
+ // 启用运行配置的 'prepare*' 任务
enableEclipsePrepareRuns true
enableIdeaPrepareRuns true
}
```
-### Copy IDE Resources
+### 复制 IDE 资源
-The `copyIdeResources` property can be used to copy resources configured by the `processResources` task to the IDE's resource output directories. This allows IDE run configurations that do not invoke Gradle (IntelliJ configured to use the IDEA runner or Eclipse) to use buildscript configurable resources. Usually, you need to enable this property when you are replacing values in files like the `mods.toml`.
-This only applies to Eclipse and IntelliJ IDEA via the `copyEclipseResources` and `copyIntellijResources` tasks, respectively.
+`copyIdeResources` 属性可以用来将 `processResources` 任务配置的资源复制到 IDE 的资源输出目录。这允许不调用 Gradle 的 IDE 运行配置(配置为使用 IDEA 运行器的 IntelliJ 或 Eclipse)使用由构建脚本配置的资源。通常,在你需要在像 `mods.toml` 这样的文件中替换值时,你需要启用这个属性。
+这只适用于通过 `copyEclipseResources` 任务和 `copyIntellijResources` 任务,分别应用于 Eclipse 和 IntelliJ IDEA。
```gradle
minecraft {
// ...
- // Copies the files from 'processResources' to the IDE's resource output directories
+ // 从 'processResources' 任务复制文件到 IDE 的资源输出目录
copyIdeResources true
}
```
-### Run Configuration Folders
-
-Run configurations can be sorted into folders if the `generateRunFolders` is set to `true`. This reads the `folderName` property set in the specific [run configuration][run] to determine the organizational structure.
+### 运行配置文件夹
+如果将 `generateRunFolders` 设置为 `true`,则可以将运行配置排序到文件夹中。这会读取特定 [运行配置][run] 中设置的 `folderName` 属性来确定组织结构
```gradle
minecraft {
// ...
- // When true, run configurations will be grouped into folders by their 'folderName'
+ // 当设置为 true 时,运行配置将根据它们的 'folderName' 被分组到文件夹中
generateRunFolders true
}
```
From 09c1ee6f3a4224fabce1fbc92743137ba5c4938e Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 10:48:06 +0800
Subject: [PATCH 08/87] Update runs.md
---
neogradle/docs/configuration/runs.md | 112 ++++++++++++++-------------
1 file changed, 57 insertions(+), 55 deletions(-)
diff --git a/neogradle/docs/configuration/runs.md b/neogradle/docs/configuration/runs.md
index f06f90a04..6c797928e 100644
--- a/neogradle/docs/configuration/runs.md
+++ b/neogradle/docs/configuration/runs.md
@@ -1,126 +1,128 @@
-Run Configurations
+运行配置
==================
-Run configurations define how an instance of the game is going to run. This includes arguments, working directories, task names, etc. Run configurations are defined within the `minecraft.runs` block. While no runs are configured by default, [Forge][userdev] does provide the configurations `client`, `server`, `data`, or `gameTestServer`.
+运行配置定义了如何运行游戏实例。这包括参数、工作目录、任务名称等。运行配置在 `minecraft.runs` 块内定义。虽然默认情况下没有配置任何运行配置,但 [Forge][userdev] 提供了 `client`、`server`、`data` 或 `gameTestServer` 等配置。
```gradle
minecraft {
// ...
runs {
- // Configure runs here
+ // 在此配置运行
}
}
```
-Run configurations can be added similar to any `NamedDomainObjectContainer` using closures.
+可以使用闭包类似于任何 `NamedDomainObjectContainer` 来添加运行配置。
```gradle
-// Inside the minecraft block
+// 在 minecraft 块内
runs {
- // Creates or configures the run configuration named 'client'
+ // 创建或配置名为 'client' 的运行配置
client {
- // Configure run
+ // 配置运行
}
}
```
-The following configurations properties are available:
+以下配置属性是可用的:
```gradle
-// Inside the runs block
+// 在 runs 块内
client {
- // The name of the Gradle run tasks,
- // Defaults to 'runX' where X is the container name
+ // Gradle 运行任务的名称,
+ // 默认为 'runX',其中 X 是容器名称
taskName 'runThing'
- // Sets the entrypoint of the program to launch
- // Forge sets userdev main to be 'cpw.mods.bootstraplauncher.BootstrapLauncher'
+ // 设置要启动的程序的入口点
+ // Forge 设置 userdev 主要为 'cpw.mods.bootstraplauncher.BootstrapLauncher'
main 'com.example.Main'
- // Sets the working directory of the config
- // Defaults to './run'
+ // 设置配置的工作目录
+ // 默认为 './run'
workingDirectory 'run'
- // Sets the name of the module for IntelliJ IDEA to configure for its runs
- // Defaults to '.main'
+ // 设置 IntelliJ IDEA 的模块名称,用于配置其运行
+ // 默认为 '.main'
ideaModule 'example.main'
- // Sets the name of the folder that the run configuration should be added to
- // Defaults to the name of the project
+ // 设置将运行配置添加到的文件夹名称
+ // 默认为项目的名称
folderName 'example'
- // Sets whether this should run a Minecraft client
- // If not specified, checks the following
- // - Is there an environment property 'thing' that contains 'client'
- // - Does the configuration name contain 'client'
- // - Is main set to 'mcp.client.Start'
- // - Is main set to 'net.minecraft.client.main.Main'
+ // 设置是否运行 Minecraft 客户端
+ // 如果未指定,检查以下内容:
+ // - 是否存在包含 'client' 的环境属性 'thing'
+ // - 配置名称是否包含 'client'
+ // - main 是否设置为 'mcp.client.Start'
+ // - main 是否设置为 'net.minecraft.client.main.Main'
client true
- // Set the parent of this configuration to inherit from
+ // 设置此配置的父配置以继承
parent runs.example
- // Sets the children of this configuration
+ // 设置此配置的子配置
children runs.child
- // Merges this configuration and specifies whether to overwrite existing properties
+ // 合并此配置并指定是否覆盖现有属性
merge runs.server, true
- // If not false, will merge the arguments of the parent with this configuration
+ // 如果不为 false,将合并父配置的参数到此配置
inheritArgs false
- // If not false, will merge the JVM arguments of the parent with this configuration
+ // 如果不为 false,将合并父配置的 JVM 参数到此配置
inheritJvmArgs false
- // Adds a sourceset to the classpath
- // If none is specified, adds sourceSet.main
+ // 添加一个源集到类路径
+ // 如果未指定,默认添加 sourceSet.main
source sourceSets.api
- // Sets an environment property for the run
- // Value will be interpreted as a file or a string
+ // 为运行设置一个环境属性
+ // 值将被解释为文件或字符串
environment 'envKey', 'value'
- // Sets a system property
- // Value will be interpreted as a file or a string
+ // 设置一个系统属性
+ // 值将被解释为文件或字符串
property 'propKey', 'value'
- // Sets an argument to be passed into the application
- // Can specify multiple with 'args'
+ // 设置传递给应用程序的参数
+ // 可以使用 'args' 指定多个
arg 'hello'
- // Sets a JVM argument
- // Can specify multiple with 'jvmArgs'
+ // 设置一个 JVM 参数
+ // 可以使用 'jvmArgs' 指定多个
jvmArg '-Xmx2G'
- // Sets a token
- // Currently, the following tokens are being used:
+ // 设置一个令牌
+ // 目前,正在使用以下令牌:
// - runtime_classpath
// - minecraft_classpath
token 'tokenKey', 'value'
- // Sets a token that's lazily initialized
- // Should usually be used instead of 'token', for example when the token resolves Gradle configurations
+ // 设置一个延迟初始化的令牌
+ // 通常应该使用 'token' 替代,例如当令牌解析 Gradle 配置时
lazyToken('lazyTokenKey') {
'value'
}
- // If true, compile all projects instead of for the current task
- // This is only used by IntelliJ IDEA
- buildAllProjects false
+ // 如果为 true,则编译所有项目而不仅仅是
+ ```gradle
+// 如果为 true,则编译所有项目,而不是仅当前任务
+// 这仅被 IntelliJ IDEA 使用
+buildAllProjects false
}
```
:::tip
-You can see a list of all configured userdev properties within the [MinecraftForge buildscript][buildscript].
+你可以在 [MinecraftForge 构建脚本][buildscript] 中查看所有配置的 userdev 属性的列表。
:::
-Mod Configurations
-------------------
+Mod 配置
+--------
-A mod in the current environment can be added using the `mods` block within a Run configuration. Mod blocks are also `NamedDomainObjectContainer`s.
+在当前环境中可以使用 Run 配置内的 `mods` 块添加mod。Mod 块也是 `NamedDomainObjectContainer`。
```gradle
-// Inside the runs block
+// 在 runs 块内
client {
// ...
@@ -129,12 +131,12 @@ client {
// ...
}
- // Configures the 'example' mod
+ // 配置 'example' mod
example {
- // Add a source set to a mod's sources
+ // 向 mod 的源添加源集
source sourceSets.main
- // Merges this configuration and specifies whether to overwrite existing properties
+ // 合并此配置并指定是否覆盖现有属性
merge mods.other_mod, true
}
}
From 7ffb5c8f0f63bd8ada8d73fb39618039c88e1115 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 10:52:07 +0800
Subject: [PATCH 09/87] Update index.md
---
neogradle/docs/dependencies/index.md | 68 ++++++++++++++++------------
1 file changed, 39 insertions(+), 29 deletions(-)
diff --git a/neogradle/docs/dependencies/index.md b/neogradle/docs/dependencies/index.md
index 35dfdee7b..851670d61 100644
--- a/neogradle/docs/dependencies/index.md
+++ b/neogradle/docs/dependencies/index.md
@@ -1,48 +1,51 @@
-Dependencies
-============
+依赖项
+====
-Dependencies are not only used to develop interoperability between mods or add additional libraries to the game, but it also determines what version of Minecraft to develop for. This will provide a quick overview on how to modify the `repositories` and `dependencies` block to add dependencies to your development environment.
+依赖项不仅用于开发模组间的互操作性或向游戏添加额外的库,而且还决定了要为哪个版本的Minecraft进行开发。这将提供如何修改 `repositories` 和 `dependencies` 块以将依赖项添加到您的开发环境的快速概述。
-> This will not explain Gradle concepts in depth. It is highly recommended to read the [Gradle Dependency Management guide][guide] before continuing.
+> 这将不会深入解释 Gradle 概念。强烈建议在继续之前阅读 [Gradle 依赖管理指南][guide]。
`minecraft`
-----------
-The `minecraft` dependency specifies the version of Minecraft to use and must be included in the `dependencies` block. Any artifact, except artifacts which have the group `net.minecraft`, will apply any patches provided with the dependency. This typically only specifies the `net.minecraftforge:forge` artifact.
+`minecraft` 依赖项指定了要使用的 Minecraft 版本,并且必须包含在 `dependencies` 块中。任何非 `net.minecraft` 组的工件都将应用随依赖项提供的任何补丁。这通常只指定 `net.minecraftforge:forge` 工件。
```gradle
dependencies {
- // Version of Forge artifact is in the form '-'
- // 'mc_version' is the version of Minecraft to load (e.g., 1.19.4)
- // 'forge_version' is the version of Forge wanted for that Minecraft version (e.g., 45.0.23)
- // Vanilla can be compiled against using 'net.minecraft:joined:' instead
+ // Forge 工件的版本形式为 '-'
+ // 'mc_version' 是要加载的 Minecraft 版本(例如,1.19.4)
+ // 'forge_version' 是该 Minecraft 版本所需的 Forge 版本(例如,45.0.23)
+ // Vanilla 可以使用 'net.minecraft:joined:' 来编译
minecraft 'net.minecraftforge:forge:1.19.4-45.0.23'
}
```
-Mod Dependencies
-----------------
+Mod 依赖项
+----------
-In a typical development environment, Minecraft is deobfuscated to intermediate mappings, used in production, and then transformed into whatever [human-readable mappings][mappings] the modder specified. Mod artifacts, when built, are obfuscated to production mappings (SRG), and as such, are unable to be used directly as a Gradle dependency.
+在典型的开发环境中,Minecraft 被反混淆到中间映射中,用于生产,然后转换为模组制作者指定的任何[人类可读映射][mappings]。构建的 Mod 工件被混淆到生产映射(SRG)中,因此不能直接用作 Gradle 依赖项。
-As such, all mod dependencies need to be wrapped with `fg.deobf` before being added to the intended configuration.
+因此,所有 Mod 依赖项在添加到预期配置之前都需要用 `fg.deobf` 包装。
+
+[guide]: https://docs.gradle.org/current/userguide/dependency_management.html
+[mappings]: https://github.com/MinecraftForge/MCPConfig
```gradle
dependencies {
- // Assume we have already specified the 'minecraft' dependency
+ // 假设我们已经指定了 'minecraft' 依赖项
- // Assume we have some artifact 'examplemod' that can be obtained from a specified repository
+ // 假设我们有一些可以从指定仓库获得的工件 'examplemod'
implementation fg.deobf('com.example:examplemod:1.0')
}
```
-### Local Mod Dependencies
+### 本地 Mod 依赖项
-If the mod you are trying to depend on is not available on a maven repository (e.g., [Maven Central][central], [CurseMaven], [Modrinth]), you can add a mod dependency using a [flat directory] instead:
+如果你试图依赖的 mod 不在 maven 仓库中可用(例如,[Maven Central][central]、[CurseMaven]、[Modrinth]),你可以使用 [flat directory] 来添加 mod 依赖项:
```gradle
repositories {
- // Adds the 'libs' folder in the project directory as a flat directory
+ // 将项目目录中的 'libs' 文件夹添加为扁平目录
flatDir {
dir 'libs'
}
@@ -51,16 +54,16 @@ repositories {
dependencies {
// ...
- // Given some :::
- // with an extension
- // Artifacts in flat directories will be resolved in the following order:
+ // 给定某些 :::
+ // 带有扩展名
+ // 扁平目录中的工件将按以下顺序解析:
// - -.
// - --.
// - .
// - -.
- // If a classifier is explicitly specified
- // artifacts with the classifier will take priority:
+ // 如果明确指定了分类器
+ // 带有分类器的工件将优先:
// - examplemod-1.0-api.jar
// - examplemod-api.jar
// - examplemod-1.0.jar
@@ -70,24 +73,31 @@ dependencies {
```
:::note
-The group name can be anything but must not be empty for flat directory entries as they are not checked when resolving the artifact file.
+组名可以是任何东西,但对于扁平目录条目必须非空,因为在解析工件文件时不会检查它们。
:::
-Non-Minecraft Dependencies
---------------------------
+非 Minecraft 依赖项
+--------------------
+
+非 Minecraft 依赖项
+-------------------
-Non-Minecraft dependencies are not loaded by Forge by default in the development environment. To get Forge to recognize the non-Minecraft dependency, they must be added to the `minecraftLibrary` configuration. `minecraftLibrary` works similarly to the `implementation` configuration within Gradle, being applied during compile time and runtime.
+Forge 在开发环境中默认不加载非 Minecraft 的依赖项。要让 Forge 识别非 Minecraft 依赖项,它们必须被添加到 `minecraftLibrary` 配置中。`minecraftLibrary` 的工作方式与 Gradle 中的 `implementation` 配置类似,在编译时间和运行时间都会应用。
```gradle
dependencies {
// ...
- // Assume there is some non-Minecraft library 'dummy-lib'
+ // 假设有一些非 Minecraft 库 'dummy-lib'
minecraftLibrary 'com.dummy:dummy-lib:1.0'
}
```
-> Non-Minecraft dependencies added to the development environment will not be included in built artifact by default! You must use [Jar-In-Jar][jij] to include the dependencies within the artifact on build.
+> 默认情况下,添加到开发环境中的非 Minecraft 依赖项不会包含在构建的工件中!你必须使用 [Jar-In-Jar][jij] 在构建时将依赖项包含在工件内。
+
+:::note
+你创建的 Mod 在分发时,必须确保所有的依赖项都遵循其相应的许可协议,并且你在你的模组中包含它们时也符合这些许可。
+:::
[guide]: https://docs.gradle.org/8.1.1/userguide/dependency_management.html
[mappings]: ../configuration/index.md#human-readable-mappings
From e5a191482adde26c27e13b282c3caefac31f976e Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 10:52:33 +0800
Subject: [PATCH 10/87] Update index.md
---
neogradle/docs/dependencies/index.md | 3 ---
1 file changed, 3 deletions(-)
diff --git a/neogradle/docs/dependencies/index.md b/neogradle/docs/dependencies/index.md
index 851670d61..6bee91df2 100644
--- a/neogradle/docs/dependencies/index.md
+++ b/neogradle/docs/dependencies/index.md
@@ -76,9 +76,6 @@ dependencies {
组名可以是任何东西,但对于扁平目录条目必须非空,因为在解析工件文件时不会检查它们。
:::
-非 Minecraft 依赖项
---------------------
-
非 Minecraft 依赖项
-------------------
From 9473b24a2f905e912e3172a9fce1e5f69e8853c1 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 11:01:03 +0800
Subject: [PATCH 11/87] Update jarinjar.md
---
neogradle/docs/dependencies/jarinjar.md | 68 ++++++++++++-------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/neogradle/docs/dependencies/jarinjar.md b/neogradle/docs/dependencies/jarinjar.md
index 6222a5fe0..eba23ac9b 100644
--- a/neogradle/docs/dependencies/jarinjar.md
+++ b/neogradle/docs/dependencies/jarinjar.md
@@ -1,102 +1,102 @@
Jar-in-Jar
==========
-Jar-in-Jar is a way to load dependencies for mods from within the jars of the mods. To accomplish this, Jar-in-Jar generates a metadata json within `META-INF/jarjar/metadata.json` on build containing the artifacts to load from within the jar.
+Jar-in-Jar 是一种从 Mod 的 jar 内部加载依赖项的方法。为了实现这一点,Jar-in-Jar 在构建时会在 `META-INF/jarjar/metadata.json` 中生成一个包含将从 jar 内部加载的工件的元数据 json 文件。
-Jar-in-Jar is a completely optional system which can be enabled using `jarJar#enable` before the `minecraft` block. This will include all dependencies from the `jarJar` configuration into the `jarJar` task. You can configure the task similarly to other jar tasks:
+Jar-in-Jar 是一个完全可选的系统,可以使用 `jarJar#enable` 在 `minecraft` 块之前启用。这将包括所有来自 `jarJar` 配置的依赖项进入 `jarJar` 任务。您可以类似于其他 jar 任务来配置该任务:
```gradle
-// In build.gradle
+// 在 build.gradle 中
-// Enable the Jar-in-Jar system for your mod
+// 为您的 mod 启用 Jar-in-Jar 系统
jarJar.enable()
-// Configure the 'jarJar' task
-// 'all' is the default classifier
+// 配置 'jarJar' 任务
+// 'all' 是默认的分类器
tasks.named('jarJar') {
// ...
}
```
-Adding Dependencies
--------------------
+添加依赖项
+-------
-You can add dependencies to be included inside your jar using the `jarJar` configuration. As Jar-in-Jar is a negotiation system, all versions should supply a supported range.
+您可以使用 `jarJar` 配置将依赖项添加到您的 jar 内部。由于 Jar-in-Jar 是一个协商系统,所有版本都应提供一个支持的范围。
```gradle
-// In build.gradle
+// 在 build.gradle 中
dependencies {
- // Compiles against and includes the highest supported version of examplelib
- // between 2.0 (inclusive) and 3.0 (exclusive)
+ // 编译时使用 examplelib 的最高支持版本
+ // 区间在 2.0(含)和 3.0(不含)之间
jarJar(group: 'com.example', name: 'examplelib', version: '[2.0,3.0)')
}
```
-If you need to specify an exact version to include rather than the highest supported version in the range, you can use `jarJar#pin` within the dependency closure. In these instances, the artifact version will be used during compile time while the pinned version will be bundled inside the mod jar.
+如果您需要指定一个确切的版本来包含,而不是范围内的最高支持版本,您可以在依赖项闭包内使用 `jarJar#pin`。在这些情况下,编译时将使用工件版本,而固定版本将被打包在 mod jar 内部。
```gradle
-// In build.gradle
+// 在 build.gradle 中
dependencies {
- // Compiles against the highest supported version of examplelib
- // between 2.0 (inclusive) and 3.0 (exclusive)
+ // 编译时使用 examplelib 的最高支持版本
+ // 区间在 2.0(含)和 3.0(不含)之间
jarJar(group: 'com.example', name: 'examplelib', version: '[2.0,3.0)') {
- // Includes examplelib 2.8.0
+ // 包含 examplelib 2.8.0
jarJar.pin(it, '2.8.0')
}
}
```
-You can additionally pin a version range while compiling against a specific version instead:
+您还可以在编译时针对特定版本,同时固定一个版本范围:
```gradle
-// In build.gradle
+// 在 build.gradle 中
dependencies {
- // Compiles against examplelib 2.8.0
+ // 针对 examplelib 2.8.0 编译
jarJar(group: 'com.example', name: 'examplelib', version: '2.8.0') {
- // Includes the highest supported version of examplelib
- // between 2.0 (inclusive) and 3.0 (exclusive)
+ // 包含 examplelib 的最高支持版本
+ // 在 2.0(含)到 3.0(不含)之间
jarJar.pin(it, '[2.0,3.0)')
}
}
```
-### Using Runtime Dependencies
+### 使用运行时依赖项
-If you would like to include the runtime dependencies of your mod inside your jar, you can invoke `jarJar#fromRuntimeConfiguration` within your buildscript. If you decide to use this option, it is highly suggested to include dependency filters; otherwise, every single dependency -- including Minecraft and Forge -- will be bundled in the jar as well. To support more flexible statements, the `dependency` configuration has been added to the `jarJar` extension and task. Using this, you can specify patterns to include or exclude from the configuration:
+如果您想将您的模组的运行时依赖项包含在您的 jar 中,可以在您的构建脚本中调用 `jarJar#fromRuntimeConfiguration`。如果您决定使用此选项,强烈建议包含依赖项过滤器;否则,每一个依赖项 —— 包括 Minecraft 和 Forge —— 也将被打包到 jar 中。为了支持更灵活的声明,`dependency` 配置已被添加到 `jarJar` 扩展和任务中。使用它,您可以指定要从配置中包含或排除的模式:
```gradle
-// In build.gradle
+// 在 build.gradle 中
-// Add runtime dependencies to jar
+// 添加运行时依赖项到 jar
jarJar.fromRuntimeConfiguration()
// ...
jarJar {
- // Include or exclude dependencies here from runtime configuration
+ // 在此处从运行时配置中包括或排除依赖项
dependencies {
- // Exclude any dependency which begins with 'com.google.gson.'
+ // 排除任何以 'com.google.gson.' 开头的依赖项
exclude(dependency('com.google.gson.*'))
}
}
```
:::tip
-It is generally recommended to set at least one `include` filter when using `#fromRuntimeConfiguration`.
+通常建议在使用 `#fromRuntimeConfiguration` 时设置至少一个 `include` 过滤器。
:::
-Publishing a Jar-in-Jar to Maven
---------------------------------
+发布 Jar-in-Jar 到 Maven
+------------------------
-For archival reasons, ForgeGradle supports publishing Jar-in-Jar artifacts to a maven of choice, similar to how the [Shadow plugin][shadow] handles it. In practices, this is not useful or recommended.
+出于存档的原因,ForgeGradle 支持将 Jar-in-Jar 工件发布到选择的 Maven,类似于 [Shadow 插件][shadow] 的处理方式。实际上,这并不常用也不推荐。
```gradle
-// In build.gradle (has 'maven-publish' plugin)
+// 在 build.gradle 中(已安装 'maven-publish' 插件)
publications {
mavenJava(MavenPublication) {
- // Add standard java components and Jar-in-Jar artifact
+ // 添加标准的 java 组件和 Jar-in-Jar 工件
from components.java
jarJar.component(it)
From 57ece8ac15e0d7fdb7b227d9983b6059ffe5df5f Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 11:07:04 +0800
Subject: [PATCH 12/87] Update index.md
---
docs/blockentities/index.md | 103 +++++++++++++++---------------------
1 file changed, 42 insertions(+), 61 deletions(-)
diff --git a/docs/blockentities/index.md b/docs/blockentities/index.md
index 89ef2b872..a45c9abc2 100644
--- a/docs/blockentities/index.md
+++ b/docs/blockentities/index.md
@@ -1,142 +1,123 @@
-Block Entities
-======
+## 注册方块实体
-`BlockEntities` are like simplified `Entities` that are bound to a Block.
-They are used to store dynamic data, execute tick based tasks, and dynamic rendering.
-Some examples from vanilla Minecraft would be handling of inventories on chests, smelting logic on furnaces, or area effects on beacons.
-More advanced examples exist in mods, such as quarries, sorting machines, pipes, and displays.
+方块实体的创建和移除是动态的,因此它们本身不是注册对象。要创建一个`BlockEntity`,你需要扩展`BlockEntity`类。相应地,另一个对象被注册以方便创建和引用动态对象的*类型*。对于`BlockEntity`,这些类型被称为`BlockEntityType`。
-:::note
-`BlockEntities` aren't a solution for everything and they can cause lag when used wrongly.
-When possible, try to avoid them.
-:::
-
-## Registering
-
-Block Entities are created and removed dynamically and as such are not registry objects on their own.
-
-In order to create a `BlockEntity`, you need to extend the `BlockEntity` class. As such, another object is registered instead to easily create and refer to the *type* of the dynamic object. For a `BlockEntity`, these are known as `BlockEntityType`s.
-
-A `BlockEntityType` can be [registered][registration] like any other registry object. To construct a `BlockEntityType`, its builder form can be used via `BlockEntityType$Builder#of`. This takes in two arguments: a `BlockEntityType$BlockEntitySupplier` which takes in a `BlockPos` and `BlockState` to create a new instance of the associated `BlockEntity`, and a varargs of `Block`s which this `BlockEntity` can be attached to. Building the `BlockEntityType` is done by calling `BlockEntityType$Builder#build`. This takes in a `Type` which represents the type-safe reference used to refer to this registry object in a `DataFixer`. Since `DataFixer`s are an optional system to use for mods, this can be passed as `null`.
+`BlockEntityType`可以像其他注册对象一样被[注册][registration]。使用`BlockEntityType.Builder#of`来构建`BlockEntityType`,它接受两个参数:一个`BlockEntityType.BlockEntitySupplier`,它接受一个`BlockPos`和`BlockState`来创建新的`BlockEntity`实例,以及一个可变数量的`Block`,这些方块可以附加到此`BlockEntity`。
```java
-// For some DeferredRegister> REGISTER
+// 对于某个DeferredRegister> REGISTER
public static final RegistryObject> MY_BE = REGISTER.register("mybe", () -> BlockEntityType.Builder.of(MyBE::new, validBlocks).build(null));
-// In MyBE, a BlockEntity subclass
+// 在MyBE中,一个BlockEntity子类
public MyBE(BlockPos pos, BlockState state) {
super(MY_BE.get(), pos, state);
}
```
-## Creating a `BlockEntity`
+## 创建方块实体
-To create a `BlockEntity` and attach it to a `Block`, the `EntityBlock` interface must be implemented on your `Block` subclass. The method `EntityBlock#newBlockEntity(BlockPos, BlockState)` must be implemented and return a new instance of your `BlockEntity`.
+要创建一个`BlockEntity`并将其附加到一个`Block`,你的`Block`子类必须实现`EntityBlock`接口。必须实现方法`EntityBlock#newBlockEntity(BlockPos, BlockState)`并返回你的`BlockEntity`的新实例。
-## Storing Data within your `BlockEntity`
+## 存储你的方块实体内的数据
-In order to save data, override the following two methods:
+为了保存数据,覆盖以下两个方法:
```java
BlockEntity#saveAdditional(CompoundTag tag)
BlockEntity#load(CompoundTag tag)
```
-These methods are called whenever the `LevelChunk` containing the `BlockEntity` gets loaded from/saved to a tag.
-Use them to read and write to the fields in your block entity class.
+这些方法在包含`BlockEntity`的`LevelChunk`从标签加载/保存时调用。使用这些方法读写你的方块实体类中的字段。
:::note
-Whenever your data changes, you need to call `BlockEntity#setChanged`; otherwise, the `LevelChunk` containing your `BlockEntity` might be skipped while the level is saved.
+每当你的数据发生变化时,你需要调用`BlockEntity#setChanged`;否则,在级别保存时可能会跳过包含你的`BlockEntity`的`LevelChunk`。
:::
:::danger
-It is important that you call the `super` methods!
+调用`super`方法非常重要!
-The tag names `id`, `x`, `y`, `z`, `ForgeData` and `ForgeCaps` are reserved by the `super` methods.
+标签名`id`、`x`、`y`、`z`、`ForgeData`和`ForgeCaps`由`super`方法保留。
:::
-## Ticking `BlockEntities`
+## `BlockEntities` 的定时器
-If you need a ticking `BlockEntity`, for example to keep track of the progress during a smelting process, another method must be implemented and overridden within `EntityBlock`: `EntityBlock#getTicker(Level, BlockState, BlockEntityType)`. This can implement different tickers depending on which logical side the user is on, or just implement one general ticker. In either case, a `BlockEntityTicker` must be returned. Since this is a functional interface, it can just take in a method representing the ticker instead:
+如果你需要一个定时的方块实体,例如跟踪熔炼过程中的进度,那么必须在`EntityBlock`内实现并覆盖另一个方法:`EntityBlock#getTicker(Level, BlockState, BlockEntityType)`。这可以实现不同的定时器,取决于用户所在的逻辑侧,或者只实现一个通用定时器。无论哪种情况,都必须返回一个`BlockEntityTicker`。由于这是一个功能接口,它可以仅采用表示定时器的方法:
```java
-// Inside some Block subclass
+// 在某个Block子类内
@Nullable
@Override
public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) {
return type == MyBlockEntityTypes.MYBE.get() ? MyBlockEntity::tick : null;
}
-// Inside MyBlockEntity
+// 在MyBlockEntity内
public static void tick(Level level, BlockPos pos, BlockState state, MyBlockEntity blockEntity) {
- // Do stuff
+ // 执行任务
}
```
:::note
-This method is called each tick; therefore, you should avoid having complicated calculations in here. If possible, you should make more complex calculations every X ticks. (The amount of ticks in a second may be lower then 20 (twenty) but won't be higher)
+这个方法每个tick都会被调用;因此,你应该避免在这里进行复杂的计算。如果可能,你应该每X个ticks进行更复杂的计算。(一秒钟内的ticks数量可能低于20
+
+,但不会更高)
:::
-## Synchronizing the Data to the Client
+## 将数据同步到客户端
-There are three ways of syncing data to the client: synchronizing on chunk load, on block updates, and with a custom network message.
+有三种方法可以将数据同步到客户端:在LevelChunk加载时同步,在方块更新时同步,以及使用自定义网络消息同步。
-### Synchronizing on LevelChunk Load
+### 在LevelChunk加载时同步
-For this you need to override
+为此,你需要覆盖
```java
BlockEntity#getUpdateTag()
IForgeBlockEntity#handleUpdateTag(CompoundTag tag)
```
-Again, this is pretty simple, the first method collects the data that should be sent to the client,
-while the second one processes that data. If your `BlockEntity` doesn't contain much data, you might be able to use the methods out of the [Storing Data within your `BlockEntity`][storing-data] section.
+第一个方法收集应该发送到客户端的数据,而第二个方法处理这些数据。如果你的`BlockEntity`不包含太多数据,你可能可以使用[存储你的方块实体内的数据][storing-data]部分中的方法。
:::caution
-Synchronizing excessive/useless data for block entities can lead to network congestion. You should optimize your network usage by sending only the information the client needs when the client needs it. For instance, it is more often than not unnecessary to send the inventory of a block entity in the update tag, as this can be synchronized via its [`AbstractContainerMenu`][menu].
+同步过多/无用的方块实体数据可能导致网络拥塞。你应该优化你的网络使用,只在客户端需要时发送客户端需要的信息。例如,通常没有必要在更新标签中发送方块实体的库存,因为这可以通过其[`AbstractContainerMenu`][menu]同步。
:::
-### Synchronizing on Block Update
+### 在方块更新时同步
-This method is a bit more complicated, but again you just need to override two or three methods.
-Here is a tiny example implementation of it:
+这种方法有点复杂,但你只需覆盖两个或三个方法。这里是它的一个小示例实现:
```java
@Override
public CompoundTag getUpdateTag() {
CompoundTag tag = new CompoundTag();
- //Write your data into the tag
+ // 将你的数据写入标签
return tag;
}
@Override
public Packet getUpdatePacket() {
- // Will get tag from #getUpdateTag
+ // 从#getUpdateTag获取标签
return ClientboundBlockEntityDataPacket.create(this);
}
-// Can override IForgeBlockEntity#onDataPacket. By default, this will defer to the #load.
+// 可以覆盖IForgeBlockEntity#onDataPacket。默认情况下,这将推迟到#load。
```
-The static constructors `ClientboundBlockEntityDataPacket#create` takes:
+静态构造函数`ClientboundBlockEntityDataPacket#create`接受:
-* The `BlockEntity`.
-* An optional function to get the `CompoundTag` from the `BlockEntity`. By default, this uses `BlockEntity#getUpdateTag`.
+* `BlockEntity`。
+* 一个可选的函数,从`BlockEntity`获取`CompoundTag`。默认情况下,这使用`BlockEntity#getUpdateTag`。
-Now, to send the packet, an update notification must be given on the server.
+现在,要发送数据包,服务器上必须给出更新通知。
```java
Level#sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags)
```
-The `pos` should be your `BlockEntity`'s position.
-For `oldState` and `newState`, you can pass the current `BlockState` at that position.
-`flags` is a bitmask that should contain `2`, which will sync the changes to the client. See `Block` for more info as well as the rest of the flags. The flag `2` is equivalent to `Block#UPDATE_CLIENTS`.
+`pos`应该是你的`BlockEntity`的位置。
+对于`oldState`和`newState`,你可以传递该位置当前的`BlockState`。
+`flags`是一个位掩码,应包含`2`,这将同步更改到客户端。有关更多信息以及其他标志,请参阅`Block`。标志`2`等同于`Block#UPDATE_CLIENTS`。
-### Synchronizing Using a Custom Network Message
+### 使用自定义网络消息同步
-This way of synchronizing is probably the most complicated but is usually the most optimized,
-as you can make sure that only the data you need to be synchronized is actually synchronized.
-You should first check out the [`Networking`][networking] section and especially [`SimpleImpl`][simple_impl] before attempting this.
-Once you've created your custom network message, you can send it to all users that have the `BlockEntity` loaded with `SimpleChannel#send(PacketDistributor$PacketTarget, MSG)`.
+这种同步方式可能是最复杂的,但通常是最优化的,因为你可以确保只有你需要同步的数据实际上被同步。你应该首先查看[`Networking`][networking]部分,特别是[`SimpleImpl`][simple_impl],然后再尝试这种方式。一旦你创建了自定义网络消息,你可以使用`SimpleChannel#send(PacketDistributor$PacketTarget, MSG)`将其发送给加载了`BlockEntity`的所有用户。
:::caution
-It is important that you do safety checks, the `BlockEntity` might already be destroyed/replaced when the message arrives at the player! You should also check if the chunk is loaded (`Level#hasChunkAt(BlockPos)`).
+进行安全检查非常重要,当消息到达玩家时,`BlockEntity`可能已经被销毁/替换!你还应该检查块是否已加载(`Level#hasChunkAt(BlockPos)`)。
:::
[registration]: ../concepts/registries.md#methods-for-registering
From 8d1bce514fd463c625d1540a4bf03b068e1d3e98 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 11:07:34 +0800
Subject: [PATCH 13/87] Update index.md
---
docs/blockentities/index.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/docs/blockentities/index.md b/docs/blockentities/index.md
index a45c9abc2..84a2627e0 100644
--- a/docs/blockentities/index.md
+++ b/docs/blockentities/index.md
@@ -57,9 +57,7 @@ public static void tick(Level level, BlockPos pos, BlockState state, MyBlockEnti
```
:::note
-这个方法每个tick都会被调用;因此,你应该避免在这里进行复杂的计算。如果可能,你应该每X个ticks进行更复杂的计算。(一秒钟内的ticks数量可能低于20
-
-,但不会更高)
+这个方法每个tick都会被调用;因此,你应该避免在这里进行复杂的计算。如果可能,你应该每X个ticks进行更复杂的计算。(一秒钟内的ticks数量可能低于20,但不会更高)
:::
## 将数据同步到客户端
From 3338c741f8c5990767f72059052b8ba219f0f8a1 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 11:14:19 +0800
Subject: [PATCH 14/87] Update ber.md
---
docs/blockentities/ber.md | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/docs/blockentities/ber.md b/docs/blockentities/ber.md
index 0196f965d..a83d801aa 100644
--- a/docs/blockentities/ber.md
+++ b/docs/blockentities/ber.md
@@ -1,28 +1,28 @@
BlockEntityRenderer
==================
-A `BlockEntityRenderer` or `BER` is used to render blocks in a way that cannot be represented with a static baked model (JSON, OBJ, B3D, others). A block entity renderer requires the block to have a `BlockEntity`.
+`BlockEntityRenderer` 或 `BER` 用于以无法用静态烘焙模型(JSON,OBJ,B3D,其他)表示的方式渲染块。块实体渲染器要求块有一个 `BlockEntity`。
-Creating a BER
+创建 BER
--------------
-To create a BER, create a class that inherits from `BlockEntityRenderer`. It takes a generic argument specifying the block's `BlockEntity` class. The generic argument is used in the BER's `render` method.
+要创建 BER,创建一个继承自 `BlockEntityRenderer` 的类。它需要一个泛型参数,指定块的 `BlockEntity` 类。泛型参数在 BER 的 `render` 方法中使用。
-Only one BER exists for a given `BlockEntityType`. Therefore, values that are specific to a single instance in the level should be stored in the block entity being passed to the renderer rather than in the BER itself. For example, an integer that increments every frame, if stored in the BER, will increment every frame for every block entity of this type in the level.
+对于给定的 `BlockEntityType`,只存在一个 BER。因此,应将特定于等级中的单个实例的值存储在传递给渲染器的块实体中,而不是在 BER 本身中。例如,每帧递增的整数,如果存储在 BER 中,将会在该类型的等级中的每一个块实体中每帧递增。
### `render`
-This method is called every frame in order to render the block entity.
+每一帧都会调用这个方法来渲染块实体。
-#### Parameters
-* `blockEntity`: This is the instance of the block entity being rendered.
-* `partialTick`: The amount of time, in fractions of a tick, that has passed since the last full tick.
-* `poseStack`: A stack holding four-dimensional matrix entries offset to the current position of the block entity.
-* `bufferSource`: A rendering buffer able to access a vertex consumer.
-* `combinedLight`: An integer of the current light value on the block entity.
-* `combinedOverlay`: An integer set to the current overlay of the block entity, usually `OverlayTexture#NO_OVERLAY` or 655,360.
+#### 参数
+* `blockEntity`:这是正在渲染的块实体的实例。
+* `partialTick`:自上一完整 tick以来已经过去的以 tick 的分数表示的时间。
+* `poseStack`:这是一个堆栈,可以持有四维矩阵条目,这些条目可以偏移到块实体的当前位置。
+* `bufferSource`:一个渲染缓冲区,能够访问顶点消费者。
+* `combinedLight`:块实体上当前光值的整数。
+* `combinedOverlay`:一个设置为块实体当前覆盖层的整数,通常是 `OverlayTexture#NO_OVERLAY` 或 655,360。
-Registering a BER
+注册 BER
-----------------
-In order to register a BER, you must subscribe to the `EntityRenderersEvent$RegisterRenderers` event on the mod event bus and call `#registerBlockEntityRenderer`.
+要注册 BER,你必须订阅模组事件总线上的 `EntityRenderersEvent$RegisterRenderers` 事件,并调用 `#registerBlockEntityRenderer`。
From 83f7291561175c86fafcf378499076603d05fdc1 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 12:27:41 +0800
Subject: [PATCH 15/87] Update index.md
---
neogradle/docs/gettingstarted/index.md | 58 +++++++++++++-------------
1 file changed, 28 insertions(+), 30 deletions(-)
diff --git a/neogradle/docs/gettingstarted/index.md b/neogradle/docs/gettingstarted/index.md
index f2a88690e..83d63d1db 100644
--- a/neogradle/docs/gettingstarted/index.md
+++ b/neogradle/docs/gettingstarted/index.md
@@ -1,42 +1,42 @@
-Getting Started with ForgeGradle
-================================
+开始使用ForgeGradle
+============================
-If you have never used ForgeGradle before, here is the minimum amount of information needed to get a development environment setup.
+如果你之前从未使用过ForgeGradle,这里是建立开发环境所需的最少的信息。
-#### Prerequisites
+#### 前提条件
-* An installation of the Java Development Kit (JDK)
+* Java开发工具包(JDK)的安装
-Minecraft Versions | Java Development Kit Version
-:---: | :---:
-1.12 - 1.16 | [JDK 8][jdk8]
-1.17 | [JDK 16][jdk16]
-1.18 - 1.19 | [JDK 17][jdk17]
+Minecraft版本 | Java开发工具包版本
+:---: | :---:
+1.12 - 1.16 | [JDK 8][jdk8]
+1.17 | [JDK 16][jdk16]
+1.18 - 1.19 | [JDK 17][jdk17]
-* Familiarity with an Integrated Development Environment (IDE)
- * It is preferable to use one with some form of Gradle integration
+* 熟悉集成开发环境(IDE)
+ * 最好使用具有某种形式的Gradle集成的IDE
-## Setting Up ForgeGradle
+## 设置ForgeGradle
-1. First download a copy of the [Modder Development Kit (MDK)][mdk] from MinecraftForge and extract the zip to an empty directory.
-1. Open the directory you extracted the MDK to within your IDE of choice. If your IDE integrates with Gradle, import it as a Gradle project.
-1. Customize your Gradle buildscript for your mod:
- 1. Set `archivesBaseName` to the desired mod id. Additionally, replace all occurrences of `examplemod` with the mod id as well.
- 1. Change the `group` to your desired package name. Make sure to follow existing [naming conventions][group].
- 1. Change the `version` number to reflect the current version of your mod. It is highly recommended to use [Forge's extension on semantic versioning][semver].
+1. 首先从MinecraftForge下载[模组开发套件(MDK)][mdk],将zip文件解压到一个空的目录中。
+1. 使用你选择的IDE打开MDK解压的目录。如果你的IDE有Gradle集成,将其作为Gradle项目导入。
+1. 自定义你的Gradle构建脚本以适应你的模组:
+ 1. 将`archivesBaseName`设置为所需的模组ID。此外,替换所有出现的`examplemod`为你的模组ID。
+ 1. 更改`group`为你想要的包名称。确保遵循现有的[命名约定][group]。
+ 1. 更改`version`号以反映你模组的当前版本。强烈推荐使用[Forge关于语义版本控制的扩展][semver]。
-:::caution
-Make sure that any changes to the mod id are reflected in the mods.toml and main mod class. See [Structuring Your Mod][structuring] on the Forge docs for more information.
+:::警告
+确保对模组ID的任何更改都反映在mods.toml和主要模组类中。有关更多信息,请查看Forge文档上的[构建你的模组][structuring]。
:::
-2. Reload or refresh your Gradle project using your IDE. If your IDE does not have Gradle integration, run the following from a shell in your project's directory:
+2. 使用IDE重新加载或刷新你的Gradle项目。如果你的IDE没有Gradle集成,运行以下命令在项目目录中的shell中:
```sh
./gradlew build --refresh-dependencies
```
-5. If your IDE is either Eclipse, IntelliJ IDEA, or Visual Studio Code, you can generate run configurations using one of the following commands, respectively:
+5. 如果你的IDE是Eclipse、IntelliJ IDEA或Visual Studio Code,你可以使用以下命令生成运行配置,分别是:
#### Eclipse
@@ -56,14 +56,13 @@ Make sure that any changes to the mod id are reflected in the mods.toml and main
./gradlew genVSCodeRuns
```
-You can the run the client, server, etc. using one of the generated run configurations.
+你可以使用生成的运行配置来运行客户端、服务器等。
-:::tip
-If your IDE is not listed, you can still run the configurations using `./gradlew run*` (e.g., `runClient`, `runServer`, `runData`). You can use these commands with the supported IDEs as well.
+:::小贴士
+如果你的IDE未列出,你仍然可以使用`./gradlew run*` (例如,`runClient`, `runServer`, `runData`)来运行配置。这些命令也可以在支持的IDE中使用。
:::
-Congratulations, now you have a development environment set up!
-
+恭喜你,现在你已经建立了一个开发环境!
[jdk8]: https://adoptium.net/temurin/releases/?version=8
[jdk16]: https://adoptium.net/temurin/releases/?version=16
@@ -71,5 +70,4 @@ Congratulations, now you have a development environment set up!
[mdk]: https://files.minecraftforge.net/
[group]: https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html
-[semver]: https://docs.minecraftforge.net/en/latest/gettingstarted/versioning/
-[structuring]: https://docs.minecraftforge.net/en/latest/gettingstarted/structuring/
+[semver]: https://
From a0667138aa4fcf868c578e63205d444a636eb022 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 12:31:04 +0800
Subject: [PATCH 16/87] Update index.md
---
.../version-5.x/docs/index.md | 27 ++++++-------------
1 file changed, 8 insertions(+), 19 deletions(-)
diff --git a/neogradle_versioned_docs/version-5.x/docs/index.md b/neogradle_versioned_docs/version-5.x/docs/index.md
index 2fdc85cba..5b01576ab 100644
--- a/neogradle_versioned_docs/version-5.x/docs/index.md
+++ b/neogradle_versioned_docs/version-5.x/docs/index.md
@@ -1,38 +1,27 @@
-ForgeGradle Documentation
+ForgeGradle文档
=========================
-This is the official documentation for [ForgeGradle], a [Gradle] plugin for developing [MinecraftForge] and mods using MinecraftForge.
+这是[ForgeGradle]的官方文档,ForgeGradle是一个用于使用MinecraftForge开发[MinecraftForge]和模组的[Gradle]插件。
-This documentation is _only_ for ForgeGradle, **this is not a Java, Groovy, or Gradle tutorial**.
+这份文档 _仅_ 针对ForgeGradle,**这不是Java、Groovy或Gradle教程**。
-If you would like to contribute to the docs, read [Contributing to the Docs][contributing].
+如果你想为文档做出贡献,请阅读[为文档做贡献][contributing]。
-Adding the Plugin
+添加插件
-----------------
-ForgeGradle can be added using the `plugins` block by adding the MinecraftForge maven to the available plugin repositories:
+通过在可用的插件仓库中添加MinecraftForge maven,可以使用`plugins`代码块添加ForgeGradle:
```gradle
-// In settings.gradle
+// 在settings.gradle文件中
pluginManagement {
repositories {
// ...
- // Add the MinecraftForge maven
+ // 添加MinecraftForge maven
maven { url = 'https://maven.minecraftforge.net/' }
}
}
-```
-
-```gradle
-// In build.gradle
-plugins {
- // Add the ForgeGradle plugin
- id 'net.minecraftforge.gradle' version '5.1.+'
-
- // ...
-}
-```
[ForgeGradle]: https://github.com/MinecraftForge/ForgeGradle
[Gradle]: https://gradle.org/
From a2670177b82475642cbe77ee5187e5890602be85 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 12:35:27 +0800
Subject: [PATCH 17/87] Update index.md
---
.../version-5.x/docs/configuration/index.md | 40 +++++++++----------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/neogradle_versioned_docs/version-5.x/docs/configuration/index.md b/neogradle_versioned_docs/version-5.x/docs/configuration/index.md
index 785e001f3..7c1443add 100644
--- a/neogradle_versioned_docs/version-5.x/docs/configuration/index.md
+++ b/neogradle_versioned_docs/version-5.x/docs/configuration/index.md
@@ -1,50 +1,50 @@
-ForgeGradle Configurations
+ForgeGradle配置
==========================
-ForgeGradle has numerous configurations that can change how the development environment is configured. Most configurations are set using the `minecraft` block; however, some others can be specified within the `dependencies` block or modify the built `jar`, such as `reobfJar`.
+ForgeGradle具有许多配置,可以改变开发环境的设置。大多数配置使用`minecraft`代码块设置;然而,还有一些可以在`dependencies`代码块中指定,或者修改构建好的`jar`文件,例如`reobfJar`。
-Enabling Access Transformers
+启用访问转换器
----------------------------
-[Access Transformers][at] can widen the visibility or modify the `final` flag of Minecraft classes, methods, and fields. To enable access transformers in the production environment, you can set `accessTransformer` to configuration file in question:
+[访问转换器][at]可以扩大Minecraft类、方法和字段的可见性或修改`final`标志。要在开发环境中启用访问转换器,可以设置`accessTransformer`到相关的配置文件:
```gradle
minecraft {
// ...
- // Add an access transformer file relative to the project's directory
+ // 添加一个相对于项目目录的访问转换器文件
accessTransformer = project.file('src/main/resources/META-INF/accesstransformer.cfg')
}
```
-:::caution
-While the access transformer in the development environment can be read from anywhere the user specifies, in production, the file will only be read from `META-INF/accesstransformer.cfg`.
+:::警告
+虽然开发环境中的访问转换器可以从用户指定的任何地方读取,在开发环境中,文件只能从`META-INF/accesstransformer.cfg`读取。
:::
-Human-Readable Mappings
+可读的映射
-----------------------
-Minecraft's source code is obfuscated. As such, all classes, methods, and fields have machine-generated names with no package structures. Function-local variable names, meanwhile, are turned into a snowman (`☃`) due to how the Local Variable Table is stored. It is difficult to create mods using obfuscated names as reverse engineering them is tedious, may change between versions, and may be invalid in the language itself but not in the bytecode.
+Minecraft的源代码是混淆的。因此,所有的类、方法和字段都有机器生成的名称,没有包结构。与此同时,函数局部变量名称由于Local Variable Table的存储方式,被转化为雪人(☃)。使用混淆名创建模组是困难的,因为给它们做逆向工程是乏味的,可能在版本之间变化,并且可能导致在语言本身中是无效的,但在字节码中不是。
-To address the last two issues, Forge fuzzily maps each class, method, field, and parameter to a unique identifier, known as the SRG name, via the [ForgeAutoRenamingTool][fart]. SRG mappings are used in production when the game is being run by the user client.
+为了解决后两个问题,Forge通过[ForgeAutoRenamingTool][fart]将每个类、方法、字段和参数模糊地映射到一个唯一的标识符,即SRG名称。SRG映射在用户客户端运行游戏时用于开发。
-To allow easier development, ForgeGradle allows the user to choose a mapping set to apply on top of SRG mappings, which we will refer to as human-readable mappings. ForgeGradle knows how to convert the mod jar to SRG mappings for use in production via the `reobf*` task.
+为了便于开发,ForgeGradle允许用户选择一个映射集,在SRG映射的基础上应用,这里我们称之为可读的映射。ForgeGradle知道如何将模组jar转换为用于开发的SRG映射,通过`reobf*`任务。
-The mapping set used can be specified by setting the `mappings` field in the `minecraft` block. The `mappings` field takes in two arguments: `channel` which is the type of the mapping set, and `version` which is the version of the mapping set to apply.
+可以通过在`minecraft`代码块中设置`mappings`字段来指定使用的映射集。`mappings`字段接受两个参数:`channel`,它是映射集的类型,以及`version`,它是要应用的映射集的版本。
-Currently, there are three default mapping sets built into ForgeGradle:
+目前,默认内置到ForgeGradle中有三个映射集:
-* `official` - This uses the mapping set provided by Mojang. These mappings do not have parameter names and only exist from 1.14 onward.
-* `stable` - This uses a mapping set generated by MCP. These are typically incomplete and no longer exist as of 1.17.
-* `snapshot` - This also is a mapping set generated by MCP, similar to a nightly build of a program. These are also typically incomplete and no longer exist as of 1.17.
+* `official` - 使用由Mojang提供的映射集。这些映射没有参数名称,且只存在于1.14及更高版本。
+* `stable` - 使用由MCP生成的映射集。这些通常是不完整的,从1.17版本开始就不再存在了。
+* `snapshot` - 也是由MCP生成的映射集,类似于程序的每日版本。这些也通常是不完整的,从1.17版本开始就不再存在了。
-:::note
-The class names used in production are from `stable` prior to 1.17 and from `official` from 1.17 onwards.
+:::注意
+开发中使用的类名来自1.17之前的`stable`,从1.17开始来自`official`。
:::
```gradle
mappings {
- // Sets the mappings to use those from Mojang for Minecraft 1.19.4.
+ // 设置映射,使用Mojang为Minecraft 1.19.4版本提供的映射。
mappings channel: 'official', version: '1.19.4'
// ...
@@ -53,7 +53,7 @@ mappings {
### Parchment
-Parchment is an official project maintained by ParchmentMC which provides open, community-sourced parameter names and javadocs on top of the `official` mapping set. You can learn how setup and use the parchment mapping set on [their website][parchment].
+Parchment是由ParchmentMC维护的官方项目,在`official`映射集的基础上提供开放的、社区来源的参数名称和javadocs。你可以在[他们的网站][parchment]上了解如何设置和使用parchment映射集。
[at]: https://docs.minecraftforge.net/en/latest/advanced/accesstransformers/
[fart]: https://github.com/MinecraftForge/ForgeAutoRenamingTool
From 9cb61b6ff15016bfc3fd77caf4368e2ccf6cbdee Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 12:37:08 +0800
Subject: [PATCH 18/87] Update runs.md
---
.../version-5.x/docs/configuration/runs.md | 110 +++++++++---------
1 file changed, 55 insertions(+), 55 deletions(-)
diff --git a/neogradle_versioned_docs/version-5.x/docs/configuration/runs.md b/neogradle_versioned_docs/version-5.x/docs/configuration/runs.md
index 083e8813f..74f79cef9 100644
--- a/neogradle_versioned_docs/version-5.x/docs/configuration/runs.md
+++ b/neogradle_versioned_docs/version-5.x/docs/configuration/runs.md
@@ -1,139 +1,139 @@
-Run Configurations
+运行配置
==================
-Run configurations define how an instance of the game is going to run. This includes arguments, working directories, task names, etc. Run configurations are defined within the `minecraft.runs` block. While no runs are configured by default, [Forge][userdev] does provide the configurations `client`, `server`, `data`, or `gameTestServer`.
+运行配置定义了一个游戏实例如何运行。这包括参数、工作目录、任务名等。运行配置在`minecraft.runs`块中定义。虽然默认情况下没有配置运行,但[Forge][userdev]确实提供了`client`、`server`、`data`、或`gameTestServer`的配置。
```gradle
minecraft {
// ...
runs {
- // Configure runs here
+ // 在此处配置运行
}
}
```
-Run configurations can be added similar to any `NamedDomainObjectContainer` using closures.
+运行配置可以使用闭包类似于任何`NamedDomainObjectContainer`进行添加。
```gradle
-// Inside the minecraft block
+// 在minecraft代码块内部
runs {
- // Creates or configures the run configuration named 'client'
+ // 创建或配置名为'client'的运行配置
client {
- // Configure run
+ // 配置运行
}
}
```
-The following configurations properties are available:
+以下是可用的配置属性:
```gradle
-// Inside the runs block
+// 在runs块内部
client {
- // The name of the Gradle run tasks,
- // Defaults to 'runX' where X is the container name
+ // Gradle运行任务的名称,
+ // 默认为`runX`,其中X是容器名称
taskName 'runThing'
- // Sets the entrypoint of the program to launch
- // Forge sets userdev main to be 'cpw.mods.bootstraplauncher.BootstrapLauncher'
+ // 设置要启动程序的入口点
+ // Forge将userdev main设置为'cpw.mods.bootstraplauncher.BootstrapLauncher'
main 'com.example.Main'
- // Sets the working directory of the config
- // Defaults to './run'
+ // 设置配置的工作目录
+ // 默认为'./run'
workingDirectory 'run'
- // Sets the name of the module for IntelliJ IDEA to configure for its runs
- // Defaults to '.main'
+ // 设置IntelliJ IDEA配置其运行的模块的名称
+ // 默认为'.main'
ideaModule 'example.main'
- // Sets whether this should run a Minecraft client
- // If not specified, checks the following
- // - Is there an environment property 'thing' that contains 'client'
- // - Does the configuration name contain 'client'
- // - Is main set to 'mcp.client.Start'
- // - Is main set to 'net.minecraft.client.main.Main'
+ // 设置是否应运行Minecraft客户端
+ // 如果未指定,检查以下内容
+ // - 是否存在一个环境属性'thing',包含'client'
+ // - 配置名称中是否包含'client'
+ // - main是否设置为'mcp.client.Start'
+ // - main是否设置为'net.minecraft.client.main.Main'
client true
- // Set the parent of this configuration to inherit from
+ // 设置此配置的父级以便继承
parent runs.example
- // Sets the children of this configuration
+ // 设置此配置的子配置
children runs.child
- // Merges this configuration and specifies whether to overwrite existing properties
+ // 合并此配置并指定是否覆盖现有属性
merge runs.server, true
- // If not false, will merge the arguments of the parent with this configuration
+ // 如果不为false,将父配置的参数合并到此配置中
inheritArgs false
- // If not false, will merge the JVM arguments of the parent with this configuration
+ // 如果不为false,将父配置的JVM参数合并到此配置中
inheritJvmArgs false
- // Adds a sourceset to the classpath
- // If none is specified, adds sourceSet.main
+ // 将源集添加到类路径中
+ // 如果未指定,添加sourceSet.main
source sourceSets.api
- // Sets an environment property for the run
- // Value will be interpreted as a file or a string
+ // 设置运行的环境属性
+ // 值将被解释为文件或字符串
environment 'envKey', 'value'
- // Sets a system property
- // Value will be interpreted as a file or a string
+ // 设置系统属性
+ // 值将被解释为文件或字符串
property 'propKey', 'value'
- // Sets an argument to be passed into the application
- // Can specify multiple with 'args'
+ // 设置传入应用程序的参数
+ // 可以使用'args'指定多个
arg 'hello'
- // Sets a JVM argument
- // Can specify multiple with 'jvmArgs'
+ // 设置JVM参数
+ // 可以使用'jvmArgs'指定多个
jvmArg '-Xmx2G'
- // Sets a token
- // Currently, the following tokens are being used:
+ // 设置标记
+ // 目前,正在使用以下的标记:
// - runtime_classpath
// - minecraft_classpath
token 'tokenKey', 'value'
- // Sets a token that's lazily initialized
- // Should usually be used instead of 'token', for example when the token resolves Gradle configurations
+ //设置延迟初始化的标记
+ // 应该通常用于替代'token',例如当标记解析Gradle配置时
lazyToken('lazyTokenKey') {
'value'
}
- // If not false, Gradle will stop once the process has finished
+ // 如果不为false,Gradle将在进程结束后停止
forceExit true
- // If true, compile all projects instead of for the current task
- // This is only used by IntelliJ IDEA
+ // 如果为true,编译所有项目而不是当前任务
+ // 此选项仅由IntelliJ IDEA使用
buildAllProjects false
}
```
-:::tip
-You can see a list of all configured userdev properties within the [MinecraftForge buildscript][buildscript].
+:::提示
+你可以在[MinecraftForge构建脚本][buildscript]内看到所有配置的userdev属性的列表。
:::
-Mod Configurations
+模组配置
------------------
-A mod in the current environment can be added using the `mods` block within a Run configuration. Mod blocks are also `NamedDomainObjectContainer`s.
+可以使用Run配置中的`mods`块添加当前环境中的模组。模组块也是`NamedDomainObjectContainer`。
```gradle
-// Inside the runs block
+// 在runs块内部
client {
// ...
mods {
- // Configures the 'example' mod
+ // 配置'example'模块
example {
- // Add a source set to a mod's sources
- // This is recommended over manually adding classes and resources
+ // 将源集添加到模组的源中
+ // 这比手动添加类和资源更为推荐
source sourceSets.main
- // Sets the location of the mod's classes
+ // 设置模组类的位置
classes sourceSets.api.output
- // Sets the location of the mod's resources
+ // 设置模组资源的位置
resources files('./my_resources')
}
}
From 9c59015ee58f51a691268ff04a0e001eae289514 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 12:40:04 +0800
Subject: [PATCH 19/87] Update index.md
---
.../version-5.x/docs/dependencies/index.md | 57 +++++++++----------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/neogradle_versioned_docs/version-5.x/docs/dependencies/index.md b/neogradle_versioned_docs/version-5.x/docs/dependencies/index.md
index 1576ec66a..9cb878bec 100644
--- a/neogradle_versioned_docs/version-5.x/docs/dependencies/index.md
+++ b/neogradle_versioned_docs/version-5.x/docs/dependencies/index.md
@@ -1,48 +1,48 @@
-Dependencies
+依赖关系
============
-Dependencies are not only used to develop interoperability between mods or add additional libraries to the game, but it also determines what version of Minecraft to develop for. This will provide a quick overview on how to modify the `repositories` and `dependencies` block to add dependencies to your development environment.
+依赖关系不仅用于开发模组之间的互操作性或向游戏添加额外的库,而且还决定了要为哪个版本的Minecraft开发。这里会简要介绍如何修改`repositories`和`dependencies`块来向你的开发环境添加依赖。
-> This will not explain Gradle concepts in depth. It is highly recommended to read the [Gradle Dependency Management guide][guide] before continuing.
+> 这不会深入解释Gradle概念。在继续之前,强烈推荐阅读[Gradle依赖管理指南][guide]。
`minecraft`
-----------
-The `minecraft` dependency specifies the version of Minecraft to use and must be included in the `dependencies` block. Any artifact, except artifacts which have the group `net.minecraft`, will apply any patches provided with the dependency. This typically only specifies the `net.minecraftforge:forge` artifact.
+`minecraft`依赖项指定要使用的Minecraft版本,必须包含在`dependencies`块中。任何非`net.minecraft`组的工件都将应用随依赖项提供的任何补丁。这通常仅指定`net.minecraftforge:forge`工件。
```gradle
dependencies {
- // Version of Forge artifact is in the form '-'
- // 'mc_version' is the version of Minecraft to load (e.g., 1.19.4)
- // 'forge_version' is the version of Forge wanted for that Minecraft version (e.g., 45.0.23)
- // Vanilla can be compiled against using 'net.minecraft:joined:' instead
+ // Forge工件的版本格式为'-'
+ // 'mc_version' 是要加载的Minecraft版本(例如,1.19.4)
+ // 'forge_version' 是该Minecraft版本所需的Forge版本(例如,45.0.23)
+ // 正版可以使用'net.minecraft:joined:'来编译
minecraft 'net.minecraftforge:forge:1.19.4-45.0.23'
}
```
-Mod Dependencies
+模组依赖项
----------------
-In a typical development environment, Minecraft is deobfuscated to intermediate mappings, used in production, and then transformed into whatever [human-readable mappings][mappings] the modder specified. Mod artifacts, when built, are obfuscated to production mappings (SRG), and as such, are unable to be used directly as a Gradle dependency.
+在典型的开发环境中,Minecraft的代码会去混淆到中间映射,这些映射用于生产,然后转换成模组开发者指定的任何[可读的映射][mappings]。构建的模组工件在生产中被混淆为SRG映射,因此不能直接用作Gradle依赖。
-As such, all mod dependencies need to be wrapped with `fg.deobf` before being added to the intended configuration.
+因此,所有模组依赖项在添加到预定配置之前都需要用`fg.deobf`进行包装。
```gradle
dependencies {
- // Assume we have already specified the 'minecraft' dependency
+ // 假设我们已经指定了`minecraft`依赖项
- // Assume we have some artifact 'examplemod' that can be obtained from a specified repository
+ // 假设我们有一些可以从指定仓库获得的`examplemod`工件
implementation fg.deobf('com.example:examplemod:1.0')
}
```
-### Local Mod Dependencies
+### 本地模组依赖项
-If the mod you are trying to depend on is not available on a maven repository (e.g., [Maven Central][central], [CurseMaven], [Modrinth]), you can add a mod dependency using a [flat directory] instead:
+如果你试图依赖的模组没有在maven仓库(例如,[Maven Central][central]、[CurseMaven]、[Modrinth])上可用,你可以使用[平面目录][flat]添加模组依赖项:
```gradle
repositories {
- // Adds the 'libs' folder in the project directory as a flat directory
+ // 将项目目录中的`libs`文件夹添加为平面目录
flatDir {
dir 'libs'
}
@@ -51,16 +51,16 @@ repositories {
dependencies {
// ...
- // Given some :::
- // with an extension
- // Artifacts in flat directories will be resolved in the following order:
+ // 假定有某个:::
+ // 且扩展名为
+ // 平面目录中的工件将按以下顺序解析:
// - -.
// - --.
// - .
// - -.
- // If a classifier is explicitly specified
- // artifacts with the classifier will take priority:
+ // 如果显式指定了分类器
+ // 带有分类器的工件将获得优先权:
// - examplemod-1.0-api.jar
// - examplemod-api.jar
// - examplemod-1.0.jar
@@ -69,33 +69,30 @@ dependencies {
}
```
-:::note
-The group name can be anything but must not be empty for flat directory entries as they are not checked when resolving the artifact file.
+:::注意
+组名可以是任何东西,但对于平面目录项来说不能是空的,因为在解析工件文件时不会检查它。
:::
-Non-Minecraft Dependencies
+非Minecraft依赖项
--------------------------
-Non-Minecraft dependencies are not loaded by Forge by default in the development environment. To get Forge to recognize the non-Minecraft dependency, they must be added to the `minecraftLibrary` configuration. `minecraftLibrary` works similarly to the `implementation` configuration within Gradle, being applied during compile time and runtime.
+Forge默认情况下不会在开发环境中加载非Minecraft依赖项。要让Forge识别非Minecraft依赖项,它们必须被添加到`minecraftLibrary`配置中。`minecraftLibrary`的工作方式类似于Gradle中的`implementation`配置,在编译时和运行时被应用。
```gradle
dependencies {
// ...
- // Assume there is some non-Minecraft library 'dummy-lib'
+ // 假设有一些非Minecraft库'dummy-lib'
minecraftLibrary 'com.dummy:dummy-lib:1.0'
}
```
-> Non-Minecraft dependencies added to the development environment will not be included in built artifact by default! You must use [Jar-In-Jar][jij] to include the dependencies within the artifact on build.
+> 默认情况下,添加到开发环境中的非Minecraft依赖项将不会包含在构建的工件中!你必须使用[Jar-In-Jar][jij]在构建时,在工件中包含这些依赖项。
[guide]: https://docs.gradle.org/7.6/userguide/dependency_management.html
[mappings]: ../configuration/index.md#human-readable-mappings
-
[central]: https://central.sonatype.com/
[CurseMaven]: https://cursemaven.com/
[Modrinth]: https://docs.modrinth.com/docs/tutorials/maven/
-
[flat]: https://docs.gradle.org/7.6/userguide/declaring_repositories.html#sub:flat_dir_resolver
-
[jij]: ./jarinjar.md
From d0bf0fc7699c4dc3e4bf76bf7369b7e4f3eb694a Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 12:46:10 +0800
Subject: [PATCH 20/87] Update jarinjar.md
---
.../version-5.x/docs/dependencies/jarinjar.md | 85 ++++++-------------
1 file changed, 27 insertions(+), 58 deletions(-)
diff --git a/neogradle_versioned_docs/version-5.x/docs/dependencies/jarinjar.md b/neogradle_versioned_docs/version-5.x/docs/dependencies/jarinjar.md
index 6222a5fe0..3436bf0f2 100644
--- a/neogradle_versioned_docs/version-5.x/docs/dependencies/jarinjar.md
+++ b/neogradle_versioned_docs/version-5.x/docs/dependencies/jarinjar.md
@@ -1,109 +1,78 @@
Jar-in-Jar
==========
-Jar-in-Jar is a way to load dependencies for mods from within the jars of the mods. To accomplish this, Jar-in-Jar generates a metadata json within `META-INF/jarjar/metadata.json` on build containing the artifacts to load from within the jar.
+Jar-in-Jar 是一种从模组的 jar 文件内加载依赖的方式。为了实现这一点,在构建时 Jar-in-Jar 在 `META-INF/jarjar/metadata.json` 中生成一个元数据 json 文件,其中包含要从 jar 内加载的工件。
-Jar-in-Jar is a completely optional system which can be enabled using `jarJar#enable` before the `minecraft` block. This will include all dependencies from the `jarJar` configuration into the `jarJar` task. You can configure the task similarly to other jar tasks:
+Jar-in-Jar 是一个完全可选的系统,可以使用 `jarJar#enable` 在 `minecraft` 代码块之前启用。这将包括所有来自 `jarJar` 配置的依赖到 `jarJar` 任务中。你可以像其它 jar 任务一样配置这个任务:
```gradle
-// In build.gradle
+// 在 build.gradle 中
-// Enable the Jar-in-Jar system for your mod
+// 为你的模组启用 Jar-in-Jar 系统
jarJar.enable()
-
-// Configure the 'jarJar' task
-// 'all' is the default classifier
+// 配置 'jarJar' 任务
+// 'all' 是默认的分类器
tasks.named('jarJar') {
// ...
}
```
-Adding Dependencies
+添加依赖
-------------------
-You can add dependencies to be included inside your jar using the `jarJar` configuration. As Jar-in-Jar is a negotiation system, all versions should supply a supported range.
+你可以使用 `jarJar` 配置在你的 jar 文件中包含要添加的依赖。由于 Jar-in-Jar 是一个协商系统,所有的版本都应提供一个支持的版本范围。
```gradle
-// In build.gradle
+// 在 build.gradle 中
dependencies {
- // Compiles against and includes the highest supported version of examplelib
- // between 2.0 (inclusive) and 3.0 (exclusive)
+ // 编译并包含 examplelib 的最高支持版本
+ // 从 2.0(包含)到 3.0(不包含)
jarJar(group: 'com.example', name: 'examplelib', version: '[2.0,3.0)')
}
```
-If you need to specify an exact version to include rather than the highest supported version in the range, you can use `jarJar#pin` within the dependency closure. In these instances, the artifact version will be used during compile time while the pinned version will be bundled inside the mod jar.
+如果你需要在编译时指定要包含的确切版本,而不是范围内的最高支持版本,你可以在依赖闭包内使用 `jarJar#pin`。在这些情况下,将在编译时使用工件版本,而固定的版本将被打包在模组 jar 内。
```gradle
-// In build.gradle
+// 在 build.gradle 中
dependencies {
- // Compiles against the highest supported version of examplelib
- // between 2.0 (inclusive) and 3.0 (exclusive)
+ // 编译时使用 examplelib 的最高支持版本
+ // 从 2.0(包含)到 3.0(不包含)
jarJar(group: 'com.example', name: 'examplelib', version: '[2.0,3.0)') {
- // Includes examplelib 2.8.0
+ // 包含 examplelib 2.8.0
jarJar.pin(it, '2.8.0')
}
}
```
-You can additionally pin a version range while compiling against a specific version instead:
+你也可以在编译对特定版本编译的同时,固定一个版本范围:
```gradle
-// In build.gradle
+// 在 build.gradle 中
dependencies {
- // Compiles against examplelib 2.8.0
+ // 针对 examplelib 2.8.0 编译
jarJar(group: 'com.example', name: 'examplelib', version: '2.8.0') {
- // Includes the highest supported version of examplelib
- // between 2.0 (inclusive) and 3.0 (exclusive)
+ // 包含 examplelib 的最高支持版本
+ // 从 2.0(包含)到 3.0(不包含)
jarJar.pin(it, '[2.0,3.0)')
}
}
```
-### Using Runtime Dependencies
+### 使用运行时依赖
-If you would like to include the runtime dependencies of your mod inside your jar, you can invoke `jarJar#fromRuntimeConfiguration` within your buildscript. If you decide to use this option, it is highly suggested to include dependency filters; otherwise, every single dependency -- including Minecraft and Forge -- will be bundled in the jar as well. To support more flexible statements, the `dependency` configuration has been added to the `jarJar` extension and task. Using this, you can specify patterns to include or exclude from the configuration:
+如果你希望在你的 jar 中包含你的模组的运行时依赖,你可以在构建脚本中调用 `jarJar#fromRuntimeConfiguration`。如果你决定使用这个选项,强烈建议包含依赖过滤器;否则,包括 Minecraft 和 Forge 在内的每一个依赖项都会被打包到jar文件中。为了支持更灵活的声明,`dependency` 配置已添加到 `jarJar` 扩展和任务中。使用它,你可以指定模式来包括或排除来自配置的内容:
```gradle
-// In build.gradle
+// 在 build.gradle 中
-// Add runtime dependencies to jar
+// 向 jar 添加运行时依赖
jarJar.fromRuntimeConfiguration()
// ...
jarJar {
- // Include or exclude dependencies here from runtime configuration
+ // 在这里包含或排除运行时配置中的依赖
dependencies {
- // Exclude any dependency which begins with 'com.google.gson.'
- exclude(dependency('com.google.gson.*'))
- }
-}
-```
-
-:::tip
-It is generally recommended to set at least one `include` filter when using `#fromRuntimeConfiguration`.
-:::
-
-Publishing a Jar-in-Jar to Maven
---------------------------------
-
-For archival reasons, ForgeGradle supports publishing Jar-in-Jar artifacts to a maven of choice, similar to how the [Shadow plugin][shadow] handles it. In practices, this is not useful or recommended.
-
-```gradle
-// In build.gradle (has 'maven-publish' plugin)
-
-publications {
- mavenJava(MavenPublication) {
- // Add standard java components and Jar-in-Jar artifact
- from components.java
- jarJar.component(it)
-
- // ...
- }
-}
-```
-
-
-[shadow]: https://imperceptiblethoughts.com/shadow/getting-started/
+ // 排除任何以 'com.google.gson.' 开头的
From 576b02f4df695822881bf4c26d2eaec03b94d8ca Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 12:49:31 +0800
Subject: [PATCH 21/87] Update index.md
---
.../version-5.x/docs/gettingstarted/index.md | 54 +++++++++----------
1 file changed, 26 insertions(+), 28 deletions(-)
diff --git a/neogradle_versioned_docs/version-5.x/docs/gettingstarted/index.md b/neogradle_versioned_docs/version-5.x/docs/gettingstarted/index.md
index 248d1175b..beb5ba9eb 100644
--- a/neogradle_versioned_docs/version-5.x/docs/gettingstarted/index.md
+++ b/neogradle_versioned_docs/version-5.x/docs/gettingstarted/index.md
@@ -1,42 +1,41 @@
-Getting Started with ForgeGradle
+ForgeGradle入门
================================
-If you have never used ForgeGradle before, here is the minimum amount of information needed to get a development environment setup.
+如果你以前从未使用过ForgeGradle,这里有一些设置开发环境所需的最少内容。
-#### Prerequisites
+#### 先决条件
-* An installation of the Java Development Kit (JDK)
+* Java开发工具包(JDK)的安装
-Minecraft Versions | Java Development Kit Version
-:---: | :---:
-1.12 - 1.16 | [JDK 8][jdk8]
-1.17 | [JDK 16][jdk16]
-1.18 - 1.19 | [JDK 17][jdk17]
+Minecraft版本 | Java开发工具包版本
+:---: | :---:
+1.12 - 1.16 | [JDK 8][jdk8]
+1.17 | [JDK 16][jdk16]
+1.18 - 1.19 | [JDK 17][jdk17]
-* Familiarity with an Integrated Development Environment (IDE)
- * It is preferable to use one with some form of Gradle integration
+* 熟悉一个集成开发环境(IDE)
+ * 最好使用带有某种形式的Gradle集成的IDE
-## Setting Up ForgeGradle
+## 设置ForgeGradle
-1. First download a copy of the [Modder Development Kit (MDK)][mdk] from MinecraftForge and extract the zip to an empty directory.
-1. Open the directory you extracted the MDK to within your IDE of choice. If your IDE integrates with Gradle, import it as a Gradle project.
-1. Customize your Gradle buildscript for your mod:
- 1. Set `archivesBaseName` to the desired mod id. Additionally, replace all occurrences of `examplemod` with the mod id as well.
- 1. Change the `group` to your desired package name. Make sure to follow existing [naming conventions][group].
- 1. Change the `version` number to reflect the current version of your mod. It is highly recommended to use [Forge's extension on semantic versioning][semver].
+1. 首先从MinecraftForge下载[模组开发套件(MDK)][mdk]的副本,并将zip解压到一个空目录中。
+1. 在你选择的IDE中打开你解压MDK的目录。如果你的IDE与Gradle集成,将其作为一个Gradle项目导入。
+1. 自定义你的Gradle构建脚本以适合你的模组:
+ 1. 将`archivesBaseName`设置为所需的模组ID。此外,将所有出现的`examplemod`替换为模组ID。
+ 1. 更改`group`为你想要的包名。确保遵循现有的[命名惯例][group]。
+ 1. 将`version`号更改为反映你的模组的当前版本。强烈建议使用[Forge对语义版本控制的扩展][semver]。
-
-:::caution
-Make sure that any changes to the mod id are reflected in the mods.toml and main mod class. See [Structuring Your Mod][structuring] on the Forge docs for more information.
+:::警告
+确保对模组ID的任何更改都反映在mods.toml和主模组类中。有关更多信息,请参阅Forge文档上的[结构化你的模组][structuring]。
:::
-4. Reload or refresh your Gradle project using your IDE. If your IDE does not have Gradle integration, run the following from a shell in your project's directory:
+4. 使用你的IDE重新加载或刷新你的Gradle项目。如果你的IDE没有Gradle集成,以上一个shell在你项目的目录下运行以下命令:
```sh
./gradlew build --refresh-dependencies
```
-5. If your IDE is either Eclipse, IntelliJ IDEA, or Visual Studio Code, you can generate run configurations using one of the following commands, respectively:
+5. 如果你的IDE是Eclipse、IntelliJ IDEA或Visual Studio Code,你可以使用下列命令之一生成运行配置:
#### Eclipse
@@ -56,14 +55,13 @@ Make sure that any changes to the mod id are reflected in the mods.toml and main
./gradlew genVSCodeRuns
```
-You can the run the client, server, etc. using one of the generated run configurations.
+你可以使用生成的运行配置来运行客户端、服务器等。
-:::tip
-If your IDE is not listed, you can still run the configurations using `./gradlew run*` (e.g., `runClient`, `runServer`, `runData`). You can use these commands with the supported IDEs as well.
+:::提示
+如果你的IDE未被列出,你仍然可以使用`./gradlew run*`(例如,`runClient`, `runServer`, `runData`)运行配置。你也可以在支持的IDE中使用这些命令。
:::
-Congratulations, now you have a development environment set up!
-
+恭喜你,现在你已经设置了一个开发环境!
[jdk8]: https://adoptium.net/temurin/releases/?version=8
[jdk16]: https://adoptium.net/temurin/releases/?version=16
From 8f1207ae91bda419c7c77a0a9f1b0d5e41ffb659 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 13:11:31 +0800
Subject: [PATCH 22/87] Update index.md
---
docs/blocks/index.md | 216 +++++++++++++++++++++----------------------
1 file changed, 105 insertions(+), 111 deletions(-)
diff --git a/docs/blocks/index.md b/docs/blocks/index.md
index 95ed54dd3..95f1376da 100644
--- a/docs/blocks/index.md
+++ b/docs/blocks/index.md
@@ -1,71 +1,67 @@
-# Blocks
+## 统一方块的规则
-Blocks are essential to the Minecraft world. They make up all the terrain, structures, and machines. Chances are if you are interested in making a mod, then you will want to add some blocks. This page will guide you through the creation of blocks, and some of the things you can do with them.
+在开始之前,你需要明白在游戏中每个方块都只有一个。一个世界由成千上万个在不同位置引用该方块的实例组成。换句话说,同一个方块多次被显示。
-## One Block to Rule Them All
+因此,一个方块只应该在[注册]期间实例化一次。一旦注册了方块,你可以根据需要使用已注册的引用。
-Before we get started, it is important to understand that there is only ever one of each block in the game. A world consists of thousands of references to that one block in different locations. In other words, the same block is just displayed a lot of times.
+与大多数其他注册表不同,方块可以使用`DeferredRegister`的特殊版本,称为`DeferredRegister.Blocks`。 `DeferredRegister.Blocks`基本上就像`DeferredRegister`,但有一些细微的差别:
-Due to this, a block should only ever be instantiated once, and that is during [registration]. Once the block is registered, you can then use the registered reference as needed.
+- 它们是通过`DeferredRegister.createBlocks("yourmodid")`创建的,而不是通常的`DeferredRegister.create(...)`方法。
+- `#register`返回一个`DeferredBlock`,它扩展了`DeferredHolder`。 `T`是我们正在注册的方块类的类型。
+- 有一些帮助注册方块的方法。 更多详情请参见[下方]。
-Unlike most other registries, blocks can use a specialized version of `DeferredRegister`, called `DeferredRegister.Blocks`. `DeferredRegister.Blocks` acts basically like a `DeferredRegister`, but with some minor differences:
-
-- They are created via `DeferredRegister.createBlocks("yourmodid")` instead of the regular `DeferredRegister.create(...)` method.
-- `#register` returns a `DeferredBlock`, which extends `DeferredHolder`. `T` is the type of the class of the block we are registering.
-- There are a few helper methods for registering block. See [below] for more details.
-
-So now, let's register our blocks:
+现在,让我们注册我们的方块:
```java
//BLOCKS is a DeferredRegister.Blocks
public static final DeferredBlock MY_BLOCK = BLOCKS.register("my_block", () -> new Block(...));
```
-After registering the block, all references to the new `my_block` should use this constant. For example, if you want to check if the block at a given position is `my_block`, the code for that would look something like this:
+注册了方块后,所有对新的`my_block`的引用应使用此常量。例如,如果你想检查给定位置的方块是否是`my_block`,那么相应的代码看起来像这样:
```java
-level.getBlockState(position) // returns the blockstate placed in the given level (world) at the given position
+level.getBlockState(position) //返回在给定位置放置的方块状态
//highlight-next-line
.is(MyBlockRegistrationClass.MY_BLOCK.get());
```
-This approach also has the convenient effect that `block1 == block2` works and can be used instead of Java's `equals` method (using `equals` still works, of course, but is pointless since it compares by reference anyway).
+这种方法也有一个方便的效果,即`block1 == block2`有效,并且可以代替Java的`equals`方法使用(当然,使用`equals`仍然有效,但是因为它还是通过引用进行比较,所以没有意义)。
:::danger
-Do not call `new Block()` outside registration! As soon as you do that, things can and will break:
+不要在注册外部调用`new Block()`!一旦你那样做了,会出现问题:
-- Blocks must be created while registries are unfrozen. NeoForge unfreezes registries for you and freezes them later, so registration is your time window to create blocks.
-- If you try to create and/or register a block when registries are frozen again, the game will crash and report a `null` block, which can be very confusing.
-- If you still manage to have a dangling block instance, the game will not recognize it while syncing and saving, and replace it with air.
+- 方块必须在注册表解锁时创建。NeoForge为您解锁注册表,并稍后再冻结它们,所以注册是您创建方块的时机窗口。
+- 如果你在注册表再次冻结时尝试创建和/或注册方块,游戏将崩溃并报告一个“null”方块,这可能会非常混乱。
+- 如果你仍然设法拥有一个悬空的方块实例,游戏在同步和保存时将不能识别它,并将其替换为空气。
:::
-## Creating Blocks
+## 创建方块
-As discussed before, we start by creating our `DeferredRegister.Blocks`:
+如上所述,我们首先创建我们的`DeferredRegister.Blocks`:
```java
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks("yourmodid");
```
-### Basic Blocks
+### 基础方块
-For simple blocks which need no special functionality (think cobblestone, wooden planks, etc.), the `Block` class can be used directly. To do so, during registration, instantiate `Block` with a `BlockBehaviour.Properties` parameter. This `BlockBehaviour.Properties` parameter can be created using `BlockBehaviour.Properties#of`, and it can be customized by calling its methods. The most important methods for this are:
+对于不需要特殊功能的简单方块(如圆石,木板等),可以直接使用`Block`类。要做到这一点,在注册期间,用`BlockBehaviour.Properties`参数实例化`Block`。可以使用`BlockBehaviour.Properties#of`创建此`BlockBehaviour.Properties`参数,并可以通过调用其方法进行定制。这其中最重要的方法是:
-- `destroyTime` - Determines the time the block needs to be destroyed.
- - Stone has a destroy time of 1.5, dirt has 0.5, obsidian has 50, and bedrock has -1 (unbreakable).
-- `explosionResistance` - Determines the explosion resistance of the block.
- - Stone has an explosion resistance of 6.0, dirt has 0.5, obsidian has 1,200, and bedrock has 3,600,000.
-- `sound` - Sets the sound the block makes when it is punched, broken, or placed.
- - The default value is `SoundType.STONE`. See the [Sounds page][sounds] for more details.
-- `lightLevel` - Sets the light emission of the block. Accepts a function with a `BlockState` parameter that returns a value between 0 and 15.
- - For example, glowstone uses `state -> 15`, and torches use `state -> 14`.
-- `friction` - Sets the friction (slipperiness) of the block.
- - Default value is 0.6. Ice uses 0.98.
+- `destroyTime`-决定破坏方块所需的时间。
+ - 石头的破坏时间为1.5,泥土为0.5,黑曜石为50,基岩为-1(不可破坏)。
+- `explosionResistance`-决定方块的抗爆性。
+ - 石头的抗爆性为6.0,泥土为0.5,黑曜石为1,200,基岩为3,600,000。
+- `sound`-设置方块在被击中,打破或放置时的声音。
+ - 默认值是`SoundType.STONE`。更多详细信息请参见[声音页面][sounds]。
+- `lightLevel`-设置方块的光线发射。接收一个带有`BlockState`参数的函数,返回0到15之间的值。
+ 例如,萤石使用`state -> 15`,火炬使用`state -> 14`。
+- `摩擦` - 设置方块的摩擦(滑滑的程度)。
+ - 默认值是0.6。冰使用0.98。
-So for example, a simple implementation would look something like this:
+例如,一个简单的实现可能看起来像这样:
```java
-//BLOCKS is a DeferredRegister.Blocks
+// BLOCKS is a DeferredRegister.Blocks
public static final DeferredBlock MY_BETTER_BLOCK = BLOCKS.register(
"my_better_block",
() -> new Block(BlockBehaviour.Properties.of()
@@ -78,78 +74,76 @@ public static final DeferredBlock MY_BETTER_BLOCK = BLOCKS.register(
));
```
-For further documentation, see the source code of `BlockBehaviour.Properties`. For more examples, or to look at the values used by Minecraft, have a look at the `Blocks` class.
+有关更多文档,请参阅`BlockBehaviour.Properties`的源代码。有关更多示例,或查看Minecraft使用的值,请查看`Blocks`类。
:::note
-It is important to understand that a block in the world is not the same thing as in an inventory. What looks like a block in an inventory is actually a `BlockItem`, a special type of [item] that places a block when used. This also means that things like the creative tab or the max stack size are handled by the corresponding `BlockItem`.
-
-A `BlockItem` must be registered separately from the block. This is because a block does not necessarily need an item, for example if it is not meant to be collected (as is the case with fire, for example).
-:::
+重要的是要理解,世界中的一个方块并不同于库存中的东西。库存中看起来像方块的其实是`BlockItem`,它是一种特殊类型的[物品],在使用时会放置一个方块。这也就意味着,创造标签页或最大堆叠大小等内容都由相应的`BlockItem`处理。
-### More Functionality
+`BlockItem`必须与方块单独注册。这是因为方块不一定需要一个物品,例如,如果它不能被收集 (例如火)。
+### 更多功能
-Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; see the classes `Block`, `BlockBehaviour` and `IBlockExtension` for more information. See also the [Using blocks][usingblocks] section below for some of the most common use cases for blocks.
+直接使用`Block`只能创造非常基本的方块。如果你想添加功能,像是玩家交互或不同的碰撞箱,就需要一个扩展了`Block`的自定义类。`Block`类有许多可以被重写以实现不同功能的方法;更多信息请参见`Block`、`BlockBehaviour`和`IBlockExtension`类。另外,请查看下方的[使用方块][usingblocks]部分,了解一些方块最常见的用例。
-If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite and reasonably small amount of states (= a few hundred states at most), use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity.
+如果你想制作一个有不同变体的方块(想想一个有底部、顶部和双层变体的台阶),你应该使用[blockstates]。最后,如果你想要一个可以存储额外数据的方块(比如一个可以存储其库存的箱子),那么应该使用[block entity][blockentities]。这里的经验法则是,如果你有有限而且相当小的状态量(=最多几百个状态),使用blockstates;如果你有无限或近乎无限的状态量,使用方块实体。
-### `DeferredRegister.Blocks` helpers
+### `DeferredRegister.Blocks` 辅助器
-We already discussed how to create a `DeferredRegister.Blocks` [above], as well as that it returns `DeferredBlock`s. Now, let's have a look at what other utilities the specialized `DeferredRegister` has to offer. Let's start with `#registerBlock`:
+我们已经讨论了如何创建`DeferredRegister.Blocks`[上面],以及它返回`DeferredBlock`的内容。现在,让我们看看这个专门的`DeferredRegister`还有哪些辅助工具。我们先从`#registerBlock`开始:
```java
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks("yourmodid");
public static final DeferredBlock EXAMPLE_BLOCK = BLOCKS.registerBlock(
"example_block",
- Block::new, // The factory that the properties will be passed into.
- BlockBehaviour.Properties.of() // The properties to use.
+ Block::new, // 将使用的属性传递到哪个工厂。
+ BlockBehaviour.Properties.of() // 要使用的属性。
);
```
-Internally, this will simply call `BLOCKS.register("example_block", () -> new Block(BlockBehaviour.Properties.of()))` by applying the properties parameter to the provided block factory (which is commonly the constructor).
+在内部,这将简单地通过应用属性参数到所提供的方块工厂(通常是构造函数)来调用`BLOCKS.register("example_block", () -> new Block(BlockBehaviour.Properties.of()))`。
-If you want to use `Block::new`, you can leave out the factory entirely:
+如果你想使用`Block::new`,可以完全不使用工厂:
```java
public static final DeferredBlock EXAMPLE_BLOCK = BLOCKS.registerSimpleBlock(
"example_block",
- BlockBehaviour.Properties.of() // The properties to use.
+ BlockBehaviour.Properties.of() // 要使用的属性。
);
```
-This does the exact same as the previous example, but is slightly shorter. Of course, if you want to use a subclass of `Block` and not `Block` itself, you will have to use the previous method instead.
+这和之前的例子做的完全一样,只是稍微简洁了一些。当然,如果你想使用`Block`的子类而不是`Block`本身,你将不得不使用前面的方法。
-### Resources
+### 资源
-If you register your block and place it in the world, you will find it to be missing things like a texture. This is because [textures], among others, are handled by Minecraft's resource system. To apply the texture to the block, you must provide a [model] and a [blockstate file][bsfile] that associates the block with the texture and a shape. Give the linked articles a read for more information.
+当你注册你的方块并将其放置在世界中时,你会发现它缺少如纹理等内容。这是因为[纹理]等内容是由Minecraft的资源系统处理的。要将纹理应用到方块上,你必须提供一个[模型]和一个与纹理和形状关联的[方块状态文件][bsfile]。阅读链接文章以获取更多信息。
-## Using Blocks
+## 使用方块
-Blocks are very rarely directly used to do things. In fact, probably two of the most common operations in all of Minecraft - getting the block at a position, and setting a block at a position - use blockstates, not blocks. The general design approach is to have the block define behavior, but have the behavior actually run through blockstates. Due to this, `BlockState`s are often passed to methods of `Block` as a parameter. For more information on how blockstates are used, and on how to get one from a block, see [Using Blockstates][usingblockstates].
+方块很少直接用来做事。实际上,可能在整个Minecraft中最常见的两个操作 - 获取位置上的方块,和设置位置上的方块 - 使用的是方块状态,而不是方块。一般的设计方法是让方块定义行为,但实际上通过方块状态来运行行为。因此,`BlockState`经常作为参数传递给`Block`的方法。有关如何使用方块状态的更多信息,以及如何从方块获取方块状态,请参见[使用方块状态][usingblockstates]。
-In several situations, multiple methods of `Block` are used at different times. The following subsections list the most common block-related pipelines. Unless specified otherwise, all methods are called on both logical sides and should return the same result on both sides.
+在几种情况下,`Block`的多个方法在不同的时间被使用。以下小节列出了最常见的与方块相关的流程。除非另有说明,否则所有方法都在逻辑两侧调用,并应在两侧返回相同的结果。
-### Placing a Block
+### 放置方块
-Block placement logic is called from `BlockItem#useOn` (or some subclass's implementation thereof, such as in `PlaceOnWaterBlockItem`, which is used for lily pads). For more information on how the game gets there, see the [Interaction Pipeline][interactionpipeline]. In practice, this means that as soon as a `BlockItem` is right-clicked (for example a cobblestone item), this behavior is called.
+方块放置逻辑是从`BlockItem#useOn`(或其某些子类的实现,例如用于睡莲的`PlaceOnWaterBlockItem`)调用的。有关游戏如何到达这一点的更多信息,请参见[交互流程][interactionpipeline]。实际上,这意味着一旦`BlockItem`被右键点击(例如圆石物品),这个行为就被调用。
-- Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the block are enabled or that the target position is not outside the world border. If at least one of these checks fails, the pipeline ends.
-- `Block#canBeReplaced` is called for the block currently at the position where the block is attempted to be placed. If it returns `false`, the pipeline ends. Prominent cases that return `true` here are tall grass or snow layers.
-- `Block#getStateForPlacement` is called. This is where, depending on the context (which includes information like the position, the rotation and the side the block is placed on), different block states can be returned. This is useful for example for blocks that can be placed in different directions.
-- `Block#canSurvive` is called with the blockstate obtained in the previous step. If it returns `false`, the pipeline ends.
-- The blockstate is set into the level via a `Level#setBlock` call.
- - In that `Level#setBlock` call, `Block#onPlace` is called.
-- `Block#setPlacedBy` is called.
+- 检查几个先决条件,例如你不是在旁观者模式下,所有要求的方块功能标志都已启用,或目标位置不在世界边界之外。如果至少有一个检查失败,流程结束。
+- 对当前位于被尝试放置方块的位置的方块调用`Block#canBeReplaced`。如果它返回`false`,流程结束。在这里返回`true`的显著案例是高草或雪层。
+- 调用`Block#getStateForPlacement`。这是根据上下文(包括位置,旋转和放置方块的侧面等信息)返回不同方块状态的地方。这对于例如可以以不同方向放置的方块很有用。
+- 用前一步获得的方块状态调用`Block#canSurvive`。如果返回`false`,流程结束。
+- 通过`Level#setBlock`调用将方块状态设置到游戏世界中。
+ - 在那个`Level#setBlock`调用中,调用`Block#onPlace`。
+- 调用`Block#setPlacedBy`。
-### Breaking a Block
+### 破坏方块
-Breaking a block is a bit more complex, as it requires time. The process can be roughly divided into three stages: "initiating", "mining" and "actually breaking".
+破坏方块稍微复杂一些,因为它需要时间。这个过程可以大致分为三个阶段:“启动”,“挖掘”和“实际破坏”。
-- When the left mouse button is clicked, the "initiating" stage is entered.
-- Now, the left mouse button needs to be held down, entering the "mining" stage. **This stage's methods are called every tick.**
-- If the "continuing" stage is not interrupted (by releasing the left mouse button) and the block is broken, the "actually breaking" stage is entered.
+- 当左键被点击时,进入“启动”阶段。
+- 现在,需要持续按住左键,进入“挖掘”阶段。**这个阶段的方法每个刻都会被调用。**
+- 如果“继续”阶段没有被中断(通过释放左键)并且方块被打破,那么进入“实际破坏”阶段。
-Or for those who prefer pseudocode:
+或者对于那些更喜欢伪代码的人:
```java
leftClick();
@@ -163,65 +157,65 @@ while (leftClickIsBeingHeld()) {
}
```
-The following subsections further break down these stages into actual method calls.
+以下小节进一步将这些阶段分解为实际的方法调用。
-#### The "Initiating" Stage
+#### “启动”阶段
-- Client-only: `InputEvent.InteractionKeyMappingTriggered` is fired with the left mouse button and the main hand. If the event is canceled, the pipeline ends.
-- Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the `ItemStack` in your main hand are enabled or that the block in question is not outside the world border. If at least one of these checks fails, the pipeline ends.
-- `PlayerInteractEvent.LeftClickBlock` is fired. If the event is canceled, the pipeline ends.
- - Note that when the event is canceled on the client, no packets are sent to the server and thus no logic runs on the server.
- - However, canceling this event on the server will still cause client code to run, which can lead to desyncs!
-- `Block#attack` is called.
+- 仅客户端:当左键和主手被触发时,会触发`InputEvent.InteractionKeyMappingTriggered`事件。如果事件被取消,流程结束。
+- 检查几个先决条件,例如你不是在旁观者模式下,主手中的`ItemStack`的所有必需功能标志都已启用,或被询问的方块不在世界边界之外。如果至少有一个检查失败,流程结束。
+- 触发`PlayerInteractEvent.LeftClickBlock`事件。如果事件被取消,流程结束。
+ - 注意当事件在客户端被取消时,不会向服务器发送数据包,因此服务器上不会运行任何逻辑。
+ - 然而,在服务器上取消此事件仍然会导致客户端代码运行,这可能会导致不同步!
+- 调用`Block#attack`。
-#### The "Mining" Stage
+#### “挖掘”阶段
-- `PlayerInteractEvent.LeftClickBlock` is fired. If the event is canceled, the pipeline moves to the "finishing" stage.
- - Note that when the event is canceled on the client, no packets are sent to the server and thus no logic runs on the server.
- - However, canceling this event on the server will still cause client code to run, which can lead to desyncs!
-- `Block#getDestroyProgress` is called and added to the internal destroy progress counter.
- - `Block#getDestroyProgress` returns a float value between 0 and 1, representing how much the destroy progress counter should be increased every tick.
-- The progress overlay (cracking texture) is updated accordingly.
-- If the destroy progress is greater than 1.0 (i.e. completed, i.e. the block should be broken), the "mining" stage is exited and the "actually breaking" stage is entered.
+- 触发`PlayerInteractEvent.LeftClickBlock`事件。如果事件被取消,流程移动到“结束”阶段。
+ - 注意当事件在客户端被取消时,不会向服务器发送数据包,因此服务器上不会运行任何逻辑。
+ - 然而,在服务器上取消此事件仍然会导致客户端代码运行,这可能会导致不同步!
+- 调用`Block#getDestroyProgress`并将其加到内部的破坏进度计数器上。
+ - `Block#getDestroyProgress`返回一个介于0和1之间的浮点值,表示破坏进度计数器每个刻应该增加多少。
+- 相应地更新进度覆盖(破裂纹理)。
+- 如果破坏进度大于1.0(即完成,即方块应该被破坏),则退出“挖掘”阶段并进入“实际破坏”阶段。
-#### The "Actually Breaking" Stage
+#### “实际破坏”阶段
-- `Item#onBlockStartBreak` is called. If it returns `true` (determining that the block should not be broken), the pipeline moves to the "finishing" stage.
-- Server-only: `IBlockExtension#canHarvestBlock` is called. This determines whether the block can be harvested, i.e. broken with drops.
-- `Block#onDestroyedByPlayer` is called. If it returns `false`, the pipeline moves to the "finishing" stage. In that `Block#onDestroyedByPlayer` call:
- - `Block#playerWillDestroy` is called.
- - The blockstate is removed from the level via a `Level#setBlock` call with `Blocks.AIR.defaultBlockState()` as the blockstate parameter.
- - In that `Level#setBlock` call, `Block#onRemove` is called.
-- `Block#destroy` is called.
-- Server-only: If the previous call to `IBlockExtension#canHarvestBlock` returned `true`, `Block#playerDestroy` is called.
-- Server-only: `IBlockExtension#getExpDrop` is called.
-- Server-only: `Block#popExperience` is called with the result of the previous `IBlockExtension#getExpDrop` call, if that call returned a value greater than 0.
+- 调用`Item#onBlockStartBreak`。如果它返回`true`(决定方块不应被破坏),流程移动到“结束”阶段。
+- 仅服务器:调用`IBlockExtension#canHarvestBlock`。这决定了方块是否可以被收获,即是否可以带着掉落物被破坏。
+- 调用`Block#onDestroyedByPlayer`。如果它返回`false`,流程移动到“结束”阶段。在`Block#onDestroyedByPlayer`调用中:
+ - 调用`Block#playerWillDestroy`。
+ - 通过用`Blocks.AIR.defaultBlockState()`作为方块状态参数的`Level#setBlock`调用,从游戏世界中移除方块状态。
+ - 在那个`Level#setBlock`调用中,调用`Block#onRemove`。
+- 调用`Block#destroy`。
+- 仅服务器:如果之前对`IBlockExtension#canHarvestBlock`的调用返回了`true`,则调用`Block#playerDestroy`。
+- 仅服务器:调用`IBlockExtension#getExpDrop`。
+- 仅服务器:如果之前`IBlockExtension#getExpDrop`调用的结果大于0,就调用`Block#popExperience`。
-### Ticking
+### 游戏刻
-Ticking is a mechanism that updates (ticks) parts of the game every 1 / 20 seconds, or 50 milliseconds ("one tick"). Blocks provide different ticking methods that are called in different ways.
+游戏刻是一种机制,它在每1/20秒或50毫秒(“一个游戏刻”)更新(游戏刻)游戏的某些部分。方块提供了不同的游戏刻方法,这些方法以不同的方式被调用。
-#### Server Ticking and Tick Scheduling
+#### 服务器游戏刻和游戏刻调度
-`Block#tick` is called in two occasions: either through default [random ticking][randomtick] (see below), or through scheduled ticks. Scheduled ticks can be created through `Level#scheduleTick(BlockPos, Block, int)`, where the `int` denotes a delay. This is used in various places by vanilla, for example, the tilting mechanism of big dripleaves heavily relies on this system. Other prominent users are various redstone components.
+`Block#tick`在两种情况下被调用:通过默认的[随机刻][randomtick](见下文),或通过调度的游戏刻。可以通过`Level#scheduleTick(BlockPos, Block, int)`创建调度的游戏刻,其中`int`表示延迟。这在vanilla的多个地方被使用,例如,大型滴叶的倾斜机制就严重依赖于这个系统。其他显著的使用者包括各种红石组件。
-#### Client Ticking
+#### 客户端游戏刻
-`Block#animateTick` is called exclusively on the client, every frame. This is where client-only behavior, for example the torch particle spawning, happens.
+`Block#animateTick`仅在客户端,每帧被调用。这是发生客户端仅行为的地方,例如火炬粒子的生成。
-#### Weather Ticking
+#### 天气游戏刻
-Weather ticking is handled by `Block#handlePrecipitation` and runs independent of regular ticking. It is called only on the server, only when it is raining in some form, with a 1 in 16 chance. This is used for example by cauldrons that fill during rain or snowfall.
+天气游戏刻由`Block#handlePrecipitation`处理,并独立于常规游戏刻运行。它仅在服务器上被调用,仅当以某种形式下雨时,有1/16的机会被调用。这被用于例如收集雨水或雪水的炼药锅。
-#### Random Ticking
+#### 随机刻
-The random tick system runs independent of regular ticking. Random ticks must be enabled through the `BlockBehaviour.Properties` of the block by calling the `BlockBehaviour.Properties#randomTicks()` method. This enables the block to be part of the random ticking mechanic.
+随机刻系统独立于常规游戏刻运行。随机刻必须通过调用`BlockBehaviour.Properties`的`BlockBehaviour.Properties#randomTicks()`方法来启用。这使得方块可以是随机刻机制的一部分。
-Random ticks occur every tick for a set amount of blocks in a chunk. That set amount is defined through the `randomTickSpeed` gamerule. With its default value of 3, every tick, 3 random blocks from the chunk are chosen. If these blocks have random ticking enabled, then their respective `Block#randomTick` methods are called.
+每个刻为一个区块中设定数量的方块执行随机刻。这个设定数量是通过`randomTickSpeed`游戏规则定义的。其默认值为3,每个刻,从区块中随机选择3个方块。如果这些方块启用了随机刻,则分别调用它们的`Block#randomTick`方法。
-`Block#randomTick` by default calls `Block#tick`, which is what should normally be overridden. `Block#randomTick` should only be overridden if you specifically want different behavior for random ticking and regular (scheduled) ticking.
+`Block#randomTick`默认调用`Block#tick`,这是通常应该被覆盖的。仅当你特别希望随机刻和常规(调度)游戏刻有不同行为时,才应覆盖`Block#randomTick`。
-Random ticking is used by a wide range of mechanics in Minecraft, such as plant growth, ice and snow melting, or copper oxidizing.
+随机刻被Minecraft中的许多机制使用,例如植物生长、冰雪融化或铜氧化。
[above]: #one-block-to-rule-them-all
[below]: #deferredregisterblocks-helpers
From 533ccc4b9c358663c3e3bb3512e7bd695ad05483 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 14:26:54 +0800
Subject: [PATCH 23/87] Update index.mdx
---
src/pages/index.mdx | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/pages/index.mdx b/src/pages/index.mdx
index a2740f0f3..dc7821bd2 100644
--- a/src/pages/index.mdx
+++ b/src/pages/index.mdx
@@ -1,37 +1,37 @@
import Card from "../theme/Card.tsx";
-# NeoForged Documentation
+# NeoForged 文档
:::caution
-Please note that this documentation may not be up to date considering the recent creation of NeoForged.
+请注意,鉴于NeoForged最近的创建,本文档可能未能完全跟上最新的情况。
:::
-This is the official documentation for [NeoForged], the Minecraft modding API.
+这是[Minecraft modding API NeoForged]的官方文档。
-This documentation is _only_ for NeoForged, **this is not a Java tutorial**.
+此文档_仅限于_ NeoForged,**这不是Java教程**。
-If you would like to contribute to the docs, read [Contributing to the Docs][contributing].
+如果您想向文档贡献内容,请阅读[如何为文档贡献][贡献]。
[NeoForged]: https://neoforged.net
-[contributing]: ./contributing
+[贡献]: ./contributing
From b9fea6653c792c77ff51be9baa7bf0fff0de9ebb Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 14:27:21 +0800
Subject: [PATCH 24/87] Update index.mdx
---
src/pages/index.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/index.mdx b/src/pages/index.mdx
index dc7821bd2..23d6994bf 100644
--- a/src/pages/index.mdx
+++ b/src/pages/index.mdx
@@ -8,7 +8,7 @@ import Card from "../theme/Card.tsx";
这是[Minecraft modding API NeoForged]的官方文档。
-此文档_仅限于_ NeoForged,**这不是Java教程**。
+此文档 _仅限于_ NeoForged,**这不是Java教程**。
如果您想向文档贡献内容,请阅读[如何为文档贡献][贡献]。
From e50e9f372926a4fd5187e193574c9e5b16052df6 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 14:38:27 +0800
Subject: [PATCH 25/87] Update contributing.mdx
---
src/pages/contributing.mdx | 157 +++++++++++++++++++------------------
1 file changed, 79 insertions(+), 78 deletions(-)
diff --git a/src/pages/contributing.mdx b/src/pages/contributing.mdx
index 6cee77db6..0cc345717 100644
--- a/src/pages/contributing.mdx
+++ b/src/pages/contributing.mdx
@@ -1,78 +1,78 @@
-# Contributing to the Documentation
+# 为文档做贡献
-This is a non-exhaustive guideline for making contributions to the [NeoForged Documentation][docs] repository. Contributions can be made by forking and cloning the repository and then added via a pull request, or PR, on the [GitHub][docs].
+这是一个对[NeoForged文档][docs]仓库做出贡献的非详尽指南。贡献可以通过Fork和Clone仓库然后通过在[GitHub][docs]上添加一个拉取请求(PR)来实现。
-You can run the website locally using [npm]. It is recommended to use a Node Version Manager like [nvm] (Mac, Linux) or [nvs] (Windows) to setup and install npm and Node. From there, you can run the following commands:
+你可以使用[npm]在本地运行网站。建议使用Node版本管理器,如[nvm](Mac,Linux)或[nvs](Windows),来设置并安装npm和Node。从那里,你可以运行以下命令:
```bash
-nvm use # or nvs use on Windows
+nvm use # 或在Windows上使用 nvs use
npm install
npm run start
```
-## Principles
+## 原则
-This documentation is a guide to help a modder understand and implement a given concept from Minecraft or NeoForged.
+这份文档旨在帮助模组开发者理解并实现来自Minecraft或NeoForged的概念。
-This documentation is **not** meant as a tutorial, allowing a modder to copy-paste the examples. If you are looking for a tutorial, there are plenty of videos and pages, which are not linked here, that you can use and follow along with.
+这份文档**不**是一个教程,不允许模组开发者复制粘贴示例。如果你正在寻找一个教程,有许多视频和页面可以使用和跟随,这里没有链接。
-This documentation is also **not** meant as documentation for a class. Providing a description of an element is unavoidable when writing a guide; however, if you would like to document a class, you should contribute to [Parchment for Minecraft][parchment] or [NeoForge for NeoForged][neo].
+这份文档也**不**旨在作为一个类的文档。编写指南时提供元素的描述是不可避免的;但是,如果你想要记录一个类,你应该为[Parchment for Minecraft][parchment]或[NeoForge for NeoForged][neo]做贡献。
-Finally, this documentation is **not** meant to explain Java concepts. This documentation is intended for people who already have a solid basis in Java. If a Java concept needs to be explained to better understand the concept (such as JVM Descriptors for Access Transformers), a link should be provided to the original resource. Otherwise, if you are unfamiliar with Java, there are plenty of online resources to learn from:
+最后,这份文档**不**旨在解释Java概念。这份文档是为那些已经具有扎实Java基础的人准备的。如果需要解释Java概念以更好地理解概念(如为访问转换器的JVM描述符),应提供指向原始资源的链接。否则,如果你不熟悉Java,有许多在线资源可以学习:
* [JetBrains Academy][jetbrains]
* [Codeacademy][codeacademy]
-* [University of Helsinki][helsinki]
+* [赫尔辛基大学][helsinki]
* [Oracle][oracle]
-* [Introduction to Programming using Java by David J. Eck][eck]
+* [David J. Eck的《使用Java进行编程入门》][eck]
-## Concepts
+## 概念
-Each page should guide a modder on a particular concept. If the concept is too large in scope, the concept should be split into separate sub-concepts, each within its own page. For example, if you are writing a cookbook, there can be a page for each recipe, rather than a single page containing all the recipes.
+每页应指导模组开发者了解特定概念。如果概念范围太大,应将概念分割成单独的子概念,每个子概念都有自己的页面。例如,如果你在写一个食谱,可以为每个食谱设置一个页面,而不是一个页面包含所有食谱。
-When describing a concept, you should first introduce what the concept is, where it is used in Minecraft, why it should be used, and how to use it. Each section within a concept should have a header. A section can also be broken into sub-sections if necessary. For example, each recipe within a cookbook can have a sub-section for ingredients and the recipe itself.
+描述概念时,你应该首先介绍概念是什么,它在Minecraft中的用途,为什么应该使用它,以及如何使用它。概念中的每个部分都应该有一个标题。如果需要,一个部分也可以被分解成子部分。例如,每个食谱中的食谱可以有配料和食谱本身的子节。
-If you need to refer to other concepts, the relevant page should be linked along with a summary and/or some example to understand the application.
+如果需要引用其他概念,应链接相关页面,并附上摘要和/或一些例子来理解应用。
-## Examples
+## 示例
-Code examples should generally be pseudocode-like objects meant to enhance the understanding of a modder. For this documentation, pseudocode-like refers to code blocks written in the structure and syntax of the desired language with comments used as placeholders for specific logic that the modder may choose to implement themselves. The code blocks do not necessarily need to be compilable, but each line should have valid syntax and structure of the desired language.
+代码示例通常应该是伪代码对象,旨在增强模组开发者的理解。对于这份文档来说,伪代码是指以所需语言的结构和语法编写的代码块,使用注释作为模组开发者可能选择自己实现的特定逻辑的占位符。代码块不一定需要编译,但每行都应该有所需语言的有效语法和结构。
-When implementing a method, it is usually specific to the desired goal a modder is trying to achieve. As a guide, this documentation aims to be somewhat agnostic to a modder's specific goal, instead covering the general use case.
+实现一个方法通常特定于模组开发者试图实现的目标。作为一个指南,这份文档旨在在某种程度上对模组开发者的特定目标保持中立,而是覆盖普遍的用例。
-Let's say we are using a method called `#applyDiscount` to take some value off the current price. Not everyone will implement the same logic within the method. So, the pseudocode can leave a comment mentioning what to do instead:
+例如,假设我们使用一个叫做`#applyDiscount`的方法从当前价格中减去一些值。不是每个人都会在方法内实现相同的逻辑。因此,伪代码可以留下一个评论说明代替做什么:
```java
-// In some class
+// 在某个类中
public float applyDiscount(float price) {
float newPrice = price;
- // Apply discount to newPrice
+ // 对newPrice应用折扣
// ...
return newPrice;
}
```
:::tip
-If the pseudocode is not explanatory enough to understand the concept, then a full code example can be used instead. A full code example should supply dummy values and explain what they represent.
+如果伪代码不足以解释概念,那么可以使用完整的代码示例代替。完整的代码示例应提供虚拟值,并解释它们代表什么。
:::
-## Minor and Patch Changes
+## 小变更和补丁变更
-If a change occurs between a minor or patch versions of NeoForge, then relevant changes in the documentation should be split into separate sections or put into tabs. This maintains the accuracy of the information depending on the version the modder is currently developing for.
+如果 NeoForge 在小版本或补丁版本之间发生变更,则文档中的相关变更应分割成单独的部分或放入标签中。这样可以根据模组开发者当前开发的版本保持信息的准确性。
-Tabs must be in an `.mdx` file, not an `.md` file, for proper IDE support.
+标签必须在`.mdx`文件中,而不是`.md`文件中,以获得适当的 IDE 支持。
````md
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-
-
-
+
+
+
-
+
```java
public void latestMethod() {
// ...
@@ -80,10 +80,10 @@ public void latestMethod() {
```
-
+
-
+
```java
public void previousMethod() {
// ...
@@ -142,135 +142,135 @@ public void firstMethod() {
-## Style Guide
+## 编撰文档的风格指南
-This documentation uses [Docusaurus][docusaurus], which internally uses [MDX][mdx], to generate the pages. You can find more detailed information about available features on their pages. This style guide will be more focused towards common features and formatting we use in the Markdown files.
+此文档采用 [Docusaurus][docusaurus] 为基础,此框架内部使用 [MDX][mdx] 生成页面。您可以在他们的页面上找到更多可用功能的详细信息。此风格指南将更专注于我们在 Markdown 文件中使用的常见功能和格式。
-### Front Matter
+### 前言
-Front matter defines metadata fields which can affect how the page is rendered. This is denoted using `---`, similar to a code block. The only front matter that should usually be defined is `sidebar_position`, which determines where the page should be rendered on the sidebar.
+前言定义了可以影响页面渲染方式的元数据字段。这使用 `---` 表示,类似于代码块。通常应该定义的唯一前言是 `sidebar_position`,它决定页面在侧边栏中的渲染位置。
-There are other metadata fields like `title` and `description`, but those are typically parsed from the page itself.
+还有其他元数据字段如 `title` 和 `description`,但这些通常从页面本身解析。
```md
-
+
---
sidebar_position: 2
---
```
-#### Categories
+#### 类别
-Categories are folders within the documentation. They inherit titles and positional data from `index.md`. If an `index.md` is not within a subfolder, a `_category_.json` file should be created, specifying the `label` representing the name of the section, and `position` representing where on the sidebar it should go.
+类别是文档内的文件夹。他们从 `index.md` 继承标题和位置数据。如果子文件夹内没有 `index.md`,应该创建一个 `_category_.json` 文件,指定代表部分名称的 `label` 和代表它应该在侧边栏上去哪里的 `position`。
```json5
{
- // Name of the category to display
- "label": "Example Title",
+ // 要显示的类别名称
+ "label": "示例标题",
- // This will be rendered as the third element on the sidebar at the current level.
+ // 这将在当前级别的侧边栏中作为第三个元素渲染。
"position": 3
}
```
-### Titles
+### 标题
-Titles are defined using up to six hashtags (`#`) to define each section. Titles should capitalize everything but unimportant words.
+使用多达六个井号(`#`)定义每个部分的标题。标题应该将所有东西都首字母大写,但不重要的单词除外。
```md
-
-# Guide For Contributing to This Documentation
+
+# 编撰此文档的指南
-### Building and Testing Your Mod
+### 构建和测试你的Mod
```
-### Diction
+### 措辞
-Spelling, grammar, and syntax should follow those in American English. Avoid using contractions in sentences; use two separate words ('is not' instead of 'isn't'). Additionally, avoid using pronouns (e.g. I, me, you) when possible, unless you need to directly refer to the reader. Demonstratives (e.g. this, that, its) should be used sparingly to avoid confusing the reader. Prefer using the actual object or noun being referred to.
+拼写、语法和句法应遵循美式英语。避免使用缩写词;使用两个单词('is not' 而不是 'isn't')。另外,尽可能避免使用代词(例如 I, me, you),除非您需要直接提及读者。指示代词(例如 this, that, its)应谨慎使用,以避免使读者感到困惑。更喜欢使用所指的实际对象或名词。
-### Paragraphs
+### 段落
-Paragraphs should be a continuous block, separated by a newline. Paragraphs should **not** have each sentence be on a new line.
+段落应该是一个连续的块,由一个换行符分隔。段落**不**应该每个句子都在新行上。
```md
-This is my first paragraph. See how the next sentence is on the same line? You can use word wrapping in your editor to stop the line from going off the screen.
+这是我的第一段。看到下一句是如何在同一行上的吗?您可以在编辑器中使用单词换行来阻止行条从屏幕上滚动。
-This is my next paragraph. It is separated by a new line.
+这是我的下一段。它通过一个新行分隔。
```
-### Indentation
+### 缩进
-When indenting lines, use four spaces instead of tabs. Most markdown features require four spaces to recognize indentation, so it allows consistency across the document.
+缩进行时,使用四个空格而不是制表符。大多数 markdown 功能要求四个空格来识别缩进,因此它允许整个文档保持一致性。
```md
-* Hello World
- * Four Spaces In
+* 你好,世界
+ * 四个空格缩进
```
-### Importance
+### 重要性
-Emphasizing words should be done using **bold** or _italics_. Please use two asterisks (`**`) for bold and an underscore (`_`) for italics to make the separation in Markdown more distinct.
+强调单词应使用 **粗体** 或 _斜体_。请使用两个星号(`**`)进行粗体和下划线(`_`)进行斜体,以使 Markdown 中的区分更加明显。
```md
-This is a **bolded** word.
+这是一个**加粗**的单词。
-This is an _italicized_ word.
+这是一个_倾斜_的单词。
```
-### Code References
+### 代码引用
-When referencing elements outside of code blocks, they should be surrounded with backticks (`` ` ``). Classes should use their simple name. Methods and fields should specify the class name followed by a `#`. If the class name is implied, the method or field can simply be prefixed with `#`. Inner classes should specify the name of the outer class followed by a `.`.
+当引用代码块外的元素时,它们应该用反引号(`` ` ``)包围。类应使用它们的简单名称。方法和字段应在 `#` 之前指定类名。如果类名是隐含的,则方法或字段可以简单地以 `#` 作为前缀。内部类应在 `.` 之后指定外部类的名称。
```md
-
+
`MyClass`
`MyClass.InnerClass`
-
+
`MyClass#foo`
`MyClass.InnerClass#bar`
`#SOME_CONSTANT`
```
-Code blocks should specify the language after the triple backtick (`` ``` ``). When writing a JSON block, the JSON5 (`json5`) syntax highlighter should be used to allow comments.
+代码块应在三连反引号(`` ``` ``)之后指定语言。编写 JSON 块时,应使用 JSON5(`json5`)语法高亮显示器,以允许注释。
````md
-
+
```java
public void run() {
//...
}
```
-
+
```json5
{
- // Comments are allowed here
- "text": "Hiya"
+ // 这里允许注释
+ "text": "嗨"
}
```
````
-### Links
+### 链接
-All links should use brackets (`[]`) to refer to a link specified on the bottom of the markdown page. The second pair of brackets can be omitted if the name between the first pair of brackets is used.
+所有链接应使用括号 (`[]`) 引用页面底部指定的链接。如果第一对括号中的名称被使用,则可以省略第二对括号。
```md
-
-There are [two] different types of [link references][linkref].
+
+这里有两种不同类型的[链接引用][linkref]。
-
+
[two]: https://linkrefwithoutref.donotclick
[linkref]: https://linkref.donotclick
```
-### Admonitions
+### 警示
-Admonitions can be specified on the page using three colons (`:::`) and by specifying its type. Admonition formatting can be found on the [Docusaurus wiki][admonition].
+可以使用三个冒号(`:::`)和指定其类型在页面上指定警示。警示的格式可以在 [Docusaurus wiki][admonition] 上找到。
```md
:::note
-I'm within an admonition!
+我在一个警示框内部!
:::
```
@@ -292,4 +292,5 @@ I'm within an admonition!
[docusaurus]: https://docusaurus.io/docs/markdown-features
[mdx]: https://mdxjs.com/guides/
+
[admonition]: https://docusaurus.io/docs/markdown-features/admonitions
From 93c51258768d7d29a71efac33cdd54c71bfe0023 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 14:53:17 +0800
Subject: [PATCH 26/87] Update states.md
---
docs/blocks/states.md | 124 +++++++++++++++++++++---------------------
1 file changed, 61 insertions(+), 63 deletions(-)
diff --git a/docs/blocks/states.md b/docs/blocks/states.md
index c0829286e..9551668f3 100644
--- a/docs/blocks/states.md
+++ b/docs/blocks/states.md
@@ -1,14 +1,14 @@
Blockstates
===========
-Often, you will find yourself in a situation where you want different states of a block. For example, a wheat crop has eight growth stages, and making a separate block for each stage feels wrong. Or you have a slab or slab-like block - one bottom state, one top state, and one state that has both.
+经常会遇到想要拥有不同状态的方块的情况。例如,小麦作物有八个生长阶段,为每个阶段制作一个单独的方块感觉并不合适。或者你有一个台阶或类台阶方块 - 一个底部状态、一个顶部状态,以及一个状态同时具有两者。
-This is where blockstates come into play. Blockstates are an easy way to represent the different states a block can have, like a growth stage or a slab placement type.
+这就是Blockstates发挥作用的地方。Blockstates是一种表示方块可以具有的不同状态的简便方法,如生长阶段或台阶放置类型。
-Blockstate Properties
+Blockstate 属性
---------------------
-Blockstates use a system of properties. A block can have multiple properties of multiple types. For example, an end portal frame has two properties: whether it has an eye (`eye`, 2 options) and which direction it is placed in (`facing`, 4 options). So in total, the end portal frame has 8 (2 * 4) different blockstates:
+Blockstates使用一套属性系统。一个方块可以具有多种类型的多个属性。例如,一个末地传送门框架有两个属性:它是否有一个眼睛(`eye`,2个选项)和放置的方向(`facing`,4个选项)。所以总的来说,末地传送门框架有8(2 * 4)个不同的Blockstates:
```
minecraft:end_portal_frame[facing=north,eye=false]
@@ -21,68 +21,69 @@ minecraft:end_portal_frame[facing=south,eye=true]
minecraft:end_portal_frame[facing=west,eye=true]
```
-The notation `blockid[property1=value1,property2=value,...]` is the standardized way of representing a blockstate in text form, and is used in some locations in vanilla, for example in commands.
+表示法 `blockid[property1=value1,property2=value,...]` 是表示文本形式Blockstate的标准方式,并且在游戏的某些地方使用,例如在命令中。
-If your block does not have any blockstate properties defined, it still has exactly one blockstate - that is the one without any properties, since there are no properties to specify. This can be denoted as `minecraft:oak_planks[]` or simply `minecraft:oak_planks`.
+如果您的方块没有定义任何Blockstate属性,它仍然有一个Blockstate - 那就是没有任何属性的那个,因为没有属性需要指定。这可以表示为 `minecraft:oak_planks[]` 或者简单的 `minecraft:oak_planks`。
-As with blocks, every `BlockState` exists exactly once in memory. This means that `==` can and should be used to compare `BlockState`s. `BlockState` is also a final class, meaning it cannot be extended. **Any functionality goes in the corresponding [Block][block] class!**
+与方块一样,每个 `BlockState` 在内存中仅存在一个。这意味着可以并且应该使用 `==` 来比较 `BlockState`。`BlockState` 也是一个终极类,意味着它不能被扩展。**任何功能都在相应的[Block][block]类中!**
-When to Use Blockstates
+何时使用Blockstates
-----------------------
-### Blockstates vs. Separate Blocks
+### Blockstates vs. 独立方块
-A good rule of thumb is: **if it has a different name, it should be a separate block**. An example is making chair blocks: the direction of the chair should be a property, while the different types of wood should be separated into different blocks. So you'd have one chair block for each wood type, and each chair block has four blockstates (one for each direction).
+一个好的经验法则是:**如果它有一个不同的名称,它应该是一个独立的方块**。一个例子是制作椅子方块:椅子的方向应该是一个属性,而不同类型的木头应该分成不同的方块。所以你会有一个椅子方块适用于每种木头类型,每个椅子方块有四个Blockstates(每个方向一个)。
-### Blockstates vs. [Block Entities][blockentity]
+### Blockstates vs. [方块实体][blockentity]
-Here, the rule of thumb is: **if you have a finite amount of states, use a blockstate, if you have an infinite or near-infinite amount of states, use a block entity.** Block entities can store arbitrary amounts of data, but are slower than blockstates.
+这里的经验法则是:**如果你有一个有限的状态量,使用blockstate,如果你有一个无限或几乎无限的状态量,使用方块实体。** 方块实体可以存储任意量的数据,但比blockstates慢。
-Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is waterlogged or not, or becoming a double chest, while storing the inventory, whether it is currently open or not, or interacting with hoppers is handled by a block entity.
+Blockstates和方块实体可以联合使用。例如,箱子使用Blockstate属性来表示诸如方向、是否被水淹没或成为双箱子等事物,同时通过方块实体存储库存、是否当前打开或与漏斗的互动等。
-There is no definitive answer to the question "How many states are too much for a blockstate?", but we recommend that if you need more than 8-9 bits of data (i.e. more than a few hundred states), you should use a block entity instead.
+没有一个明确的答案来回答“对于Blockstate来说,多少状态太多了?”的问题,但我们建议,如果您需要超过8-9比特的数据(即超过几百种状态),您应该使用方块实体代替。
-Implementing Blockstates
+实现Blockstates
------------------------
-To implement a blockstate property, in your block class, create or reference a `public static final Property>` constant. While you are free to make your own `Property>` implementations, the vanilla code provides several convenience implementations that should cover most use cases:
+要实现Blockstate属性,在您的方块类中创建或引用一个 `public static final Property>` 常量。虽然您可以自由制作自己的 `Property>` 实现,但游戏代码提供了几种便利实现,应该涵盖大多数用例:
* `IntegerProperty`
- * Implements `Property`. Defines a property that holds an integer value. Note that negative values are not supported.
- * Created by calling `IntegerProperty#create(String propertyName, int minimum, int maximum)`.
+ * 实现 `Property`。定义一个持有整数值的属性。注意不支持负值。
+ * 通过调用 `IntegerProperty#create(String propertyName, int minimum, int maximum)` 创建。
* `BooleanProperty`
- * Implements `Property`. Defines a property that holds a `true` or `false` value.
- * Created by calling `BooleanProperty#create(String propertyName)`.
+ * 实现 `Property`。定义一个持有 `true` 或 `false` 值的属性。
+ * 通过调用 `BooleanProperty#create(String propertyName)` 创建。
* `EnumProperty>`
- * Implements `Property`. Defines a property that can take on the values of an Enum class.
- * Created by calling `EnumProperty#create(String propertyName, Class enumClass)`.
- * It is also possible to use only a subset of the Enum values (e.g. 4 out of 16 `DyeColor`s), see the overloads of `EnumProperty#create`.
+ * 实现 `Property`。定义一个可以取枚举类值的属性。
+ * 通过调用 `EnumProperty#create(String propertyName, Class enumClass)` 创建。
+ * 还可以使用枚举值的子集(例如,16个`DyeColor`s中的4个),见 `EnumProperty#create` 的重载方法。
* `DirectionProperty`
- * Extends `EnumProperty`. Defines a property that can take on a `Direction`.
- * Created by calling `DirectionProperty#create(String propertyName)`.
- * Several convenience predicates are provided. For example, to get a property that represents the cardinal directions, call `DirectionProperty.create("", Direction.Plane.HORIZONTAL)`; to get the X directions, `DirectionProperty.create("", Direction.Axis.X)`.
+ * `DirectionProperty`
+ * 扩展自 `EnumProperty`。定义了一个可以承载 `Direction`(方向)的属性。
+ * 通过调用 `DirectionProperty#create(String propertyName)` 来创建。
+ * 提供了几个便利的谓词方法。例如,要获取代表基本方向的属性,调用 `DirectionProperty.create("", Direction.Plane.HORIZONTAL)`;要获取X轴方向,调用 `DirectionProperty.create("", Direction.Axis.X)`。
-The class `BlockStateProperties` contains shared vanilla properties which should be used or referenced whenever possible, in place of creating your own properties.
+类 `BlockStateProperties` 包含了共享的原版属性,这些属性应尽可能使用或引用,而不是创建自己的属性。
-Once you have your property constant, override `Block#createBlockStateDefinition(StateDefinition$Builder)` in your block class. In that method, call `StateDefinition.Builder#add(YOUR_PROPERTY);`. `StateDefinition.Builder#add` has a vararg parameter, so if you have multiple properties, you can add them all in one go.
+一旦你有了你的属性常量,在你的方块类中重写 `Block#createBlockStateDefinition(StateDefinition$Builder)`。在该方法中,调用 `StateDefinition.Builder#add(YOUR_PROPERTY);`。`StateDefinition.Builder#add` 有一个变长参数,所以如果你有多个属性,你可以一次性添加它们所有。
-Every block will also have a default state. If nothing else is specified, the default state uses the default value of every property. You can change the default state by calling the `Block#registerDefaultState(BlockState)` method from your constructor.
+每个方块还有一个默认状态。如果没有指定其他内容,缺省状态使用每个属性的默认值。你可以通过从构造函数中调用 `Block#registerDefaultState(BlockState)` 方法来更改默认状态。
-If you wish to change which `BlockState` is used when placing your block, override `Block#getStateForPlacement(BlockPlaceContext)`. This can be used to, for example, set the direction of your block depending on where the player is standing or looking when they place it.
+如果你希望改变放置方块时使用的 `BlockState`,请重写 `Block#getStateForPlacement(BlockPlaceContext)`。这可以用来设置方块的方向,比如基于玩家放置时的站立位置或方向。
-To further illustrate this, this is what the relevant bits of the `EndPortalFrameBlock` class look like:
+为进一步说明,这是 `EndPortalFrameBlock` 类相关部分的样子:
```java
public class EndPortalFrameBlock extends Block {
- // Note: It is possible to directly use the values in BlockStateProperties instead of referencing them here again.
- // However, for the sake of simplicity and readability, it is recommended to add constants like this.
+ // 注意:直接使用 BlockStateProperties 中的值而不是在这里再次引用它们是可能的。
+ // 然而,为了简单和可读性考虑,推荐像这样添加常量。
public static final DirectionProperty FACING = BlockStateProperties.FACING;
public static final BooleanProperty EYE = BlockStateProperties.EYE;
public EndPortalFrameBlock(BlockBehaviour.Properties pProperties) {
super(pProperties);
- // stateDefinition.any() returns a random BlockState from an internal set,
- // we don't care because we're setting all values ourselves anyway
+ // stateDefinition.any() 返回一个内部集合中的随机 BlockState,
+ // 我们不在意,因为我们 anyway 要自己设置所有值
registerDefaultState(stateDefinition.any()
.setValue(FACING, Direction.NORTH)
.setValue(EYE, false)
@@ -91,63 +92,60 @@ public class EndPortalFrameBlock extends Block {
@Override
protected void createBlockStateDefinition(StateDefinition.Builder pBuilder) {
- // this is where the properties are actually added to the state
+ // 这里是属性实际被添加到状态的地方
pBuilder.add(FACING, EYE);
}
@Override
@Nullable
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
- // code that determines which state will be used when
- // placing down this block, depending on the BlockPlaceContext
+ // 根据 BlockPlaceContext 确定放置此方块时将使用的状态的
+ // 代码
}
}
```
-Using Blockstates
------------------
+使用 Blockstates
+----------------
-To go from `Block` to `BlockState`, call `Block#defaultBlockState()`. The default blockstate can be changed through `Block#registerDefaultState`, as described above.
+要从 `Block` 转换到 `BlockState`,调用 `Block#defaultBlockState()`。可以通过 `Block#registerDefaultState` 更改默认 blockstate,如上所述。
-You can get the value of a property by calling `BlockState#getValue(Property>)`, passing it the property you want to get the value of. Reusing our end portal frame example, this would look something like this:
+你可以通过调用 `BlockState#getValue(Property>)` 来获取一个属性的值,传递你想获取值的属性。复用我们末地传送门框架的例子,这看起来像这样:
```java
-// EndPortalFrameBlock.FACING is a DirectionProperty and thus can be used to obtain a Direction from the BlockState
+// EndPortalFrameBlock.FACING 是一个 DirectionProperty,因此可以用来从 BlockState 中获取一个 Direction
Direction direction = endPortalFrameBlockState.getValue(EndPortalFrameBlock.FACING);
```
-If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` on an existing block state with the property and its value. With our lever, this goes something like this:
+如果你想获得一个具有不同值集的 `BlockState`,只需在现有的 block state 上调用 `BlockState#setValue(Property, T)` 并传入属性及其值。对于我们的杠杆来说,像这样:
```java
endPortalFrameBlockState = endPortalFrameBlockState.setValue(EndPortalFrameBlock.FACING, Direction.SOUTH);
```
:::note
-`BlockState`s are immutable. This means that when you call `#setValue(Property, T)`, you are not actually modifying the blockstate. Instead, a lookup is performed internally, and you are given the blockstate object you requested, which is the one and only object that exists with these exact property values. This also means that just calling `state#setValue` without saving it into a variable (for example back into `state`) does nothing.
+`BlockState` 是不可变的。这意味着当你调用 `#setValue(Property, T)` 时,你实际上不是在修改 blockstate。相反,内部进行了查找,你得到了你请求的 blockstate 对象,那是唯一存在的、具有这些确切属性值的对象。这也意味着,仅仅调用 `state#setValue` 而没有将其保存到一个变量中(例如回到 `state` 中)是无效的。
:::
-To get a `BlockState` from the level, use `Level#getBlockState(BlockPos)`.
+要从场景中获取一个 `BlockState`,使用 `Level#getBlockState(BlockPos)`。
### `Level#setBlock`
-To set a `BlockState` in the level, use `Level#setBlock(BlockPos, BlockState, int)`.
+要在场景中设置一个 `BlockState`,使用 `Level#setBlock(BlockPos, BlockState, int)`。
-The `int` parameter deserves some extra explanation, as its meaning is not immediately obvious. It denotes what is known as update flags.
+`int` 参数需要额外的解释,因为它的含义不立即明显。它表示更新标志。
-To help setting the update flags correctly, there are a number of `int` constants in `Block`, prefixed with `UPDATE_`. These constants can be bitwise-ORed together (for example `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`) if you wish to combine them.
+为了正确设置更新标志,`Block` 中有一些以 `UPDATE_` 开头的 `int` 常量。这些常量可以被按位或在一起(例如 `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`)如果你希望组合它们。
-- `Block.UPDATE_NEIGHBORS` sends an update to the neighboring blocks. More specifically, it calls `Block#neighborChanged`, which calls a number of methods, most of which are redstone-related in some way.
-- `Block.UPDATE_CLIENTS` syncs the block update to the client.
-- `Block.UPDATE_INVISIBLE` explicitly does not update on the client. This also overrules `Block.UPDATE_CLIENTS`, causing the update to not be synced. The block is always updated on the server.
-- `Block.UPDATE_IMMEDIATE` forces a re-render on the client's main thread.
-- `Block.UPDATE_KNOWN_SHAPE` stops neighbor update recursion.
-- `Block.UPDATE_SUPPRESS_DROPS` disables block drops for the old block at that position.
-- `Block.UPDATE_MOVE_BY_PISTON` is only used by piston code to signal that the block was moved by a piston. This is mainly responsible for delaying light engine updates.
-- `Block.UPDATE_ALL` is an alias for `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`.
-- `Block.UPDATE_ALL_IMMEDIATE` is an alias for `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE`.
-- `Block.NONE` is an alias for `Block.UPDATE_INVISIBLE`.
+- `Block.UPDATE_NEIGHBORS` 向相邻方块发送更新。更具体地说,它调用了 `Block#neighborChanged`,它调用了许多方法,其中大部分以某种方式与红石相关。
+- `Block.UPDATE_CLIENTS` 将方块更新同步到客户端。
+- `Block.UPDATE_INVISIBLE` 显式不在客户端更新。这也覆盖了 `Block.UPDATE_CLIENTS`,导致更新不被同步。方块始终在服务器上更新。
+- `Block.UPDATE_IMMEDIATE` 强制在客户端的主线程上重新渲染。
+- `Block.UPDATE_KNOWN_SHAPE` 停止邻居更新递归。
+- `Block.UPDATE_SUPPRESS_DROPS` 禁止旧方块在该位置的掉落物。
+- `Block.UPDATE_MOVE_BY_PISTON` 仅被活塞代码用于表示方块被活塞移动。这主要是为了延迟光照引擎的更新。
+- `Block.UPDATE_ALL` 是 `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS` 的别名。
+- `Block.UPDATE_ALL_IMMEDIATE` 是 `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE` 的别名。
+- `Block.NONE` 是 `Block.UPDATE_INVISIBLE` 的别名。
-There is also a convenience method `Level#setBlockAndUpdate(BlockPos pos, BlockState state)` that calls `setBlock(pos, state, Block.UPDATE_ALL)` internally.
-
-[block]: index.md
-[blockentity]: ../blockentities/index.md
+还有一个便利方法 `Level#setBlockAndUpdate(BlockPos pos, BlockState state)`,它在内部调用 `setBlock(pos, state, Block.UPDATE_ALL)`。
From 6807046349432e588b430dbb2a427a61b827825b Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 15:15:12 +0800
Subject: [PATCH 27/87] Update events.md
---
docs/concepts/events.md | 106 ++++++++++++----------------------------
1 file changed, 30 insertions(+), 76 deletions(-)
diff --git a/docs/concepts/events.md b/docs/concepts/events.md
index 64b0b6f21..83debfc15 100644
--- a/docs/concepts/events.md
+++ b/docs/concepts/events.md
@@ -1,16 +1,16 @@
-# Events
+# 事件系统
-One of NeoForge's main features is the event system. Events are fired for various things that happen in the game. For example, there are events for when the player right clicks, when a player or another entity jumps, when blocks are rendered, when the game is loaded, etc. A modder can subscribe event handlers to each of these events, and then perform their desired behavior inside these event handlers.
+NeoForge 的核心特性之一是其事件系统。在游戏中,各种事件根据游戏内的不同动作而触发。比如玩家右键点击、玩家或其他实体跳跃、方块渲染、游戏加载时等,都会触发相应的事件。模组开发者可以为这些事件编写处理函数,并在函数中实现他们期望的行为。
-Events are fired on their respective event bus. The most important bus is `NeoForge.EVENT_BUS`. Besides that, during startup, a mod bus is spawned for each loaded mod and passed into the mod's constructor. Many mod bus events are fired in parallel (as opposed to main bus events that always run on the same thread), dramatically increasing startup speed. See [below][modbus] for more information.
+这些事件会在相应的事件总线上触发。其中最重要的是 `NeoForge.EVENT_BUS`。此外,在游戏启动期间,系统会为每个加载的模组生成一个独立的模组总线,并传递给模组的构造函数。许多模组总线事件是并行触发的,这与总在同一个线程上运行的主总线事件不同,这种设计显著提高了启动速度。更多细节,请参考[下文][modbus]。
-## Registering an Event Handler
+## 注册事件处理函数
-There are multiple ways to register event handlers. Common for all of those ways is that every event handler is a method with a single event parameter and no result (i.e. return type `void`).
+注册事件处理函数有多种方式。所有这些方式的共同点是,每个事件处理函数都是一个只接收单一事件参数并且不返回结果(即返回类型为 `void`)的方法。
### `IEventBus#addListener`
-The simplest way to register method handlers is by registering their method reference, like so:
+最简单的注册方法是直接引用方法,如下所示:
```java
@Mod("yourmodid")
@@ -19,10 +19,10 @@ public class YourMod {
NeoForge.EVENT_BUS.addListener(YourMod::onLivingJump);
}
- // Heals an entity by half a heart every time they jump.
+ // 每次实体跳跃时为其恢复半颗心的生命值。
private static void onLivingJump(LivingJumpEvent event) {
Entity entity = event.getEntity();
- // Only heal on the server side
+ // 仅在服务器端进行治疗
if (!entity.level().isClientSide()) {
entity.heal(1);
}
@@ -32,7 +32,7 @@ public class YourMod {
### `@SubscribeEvent`
-Alternatively, event handlers can be annotation-driven by creating an event handler method and annotating it with `@SubscribeEvent`. Then, you can pass an instance of the encompassing class to the event bus, registering all `@SubscribeEvent`-annotated event handlers of that instance:
+另一种方式是使用注解来驱动事件处理,为处理函数添加 `@SubscribeEvent` 注解。然后将包含该处理函数的类的实例传递给事件总线,从而注册该实例中所有带有 `@SubscribeEvent` 注解的事件处理函数:
```java
public class EventHandler {
@@ -53,7 +53,7 @@ public class YourMod {
}
```
-You can also do it statically. Simply make all event handlers static, and instead of a class instance, pass in the class itself:
+你还可以通过将所有事件处理函数设置为静态,并直接传递类本身,而不是类的实例来实现:
```java
public class EventHandler {
@@ -76,9 +76,9 @@ public class YourMod {
### `@Mod.EventBusSubscriber`
-We can go one step further and also annotate the event handler class with `@Mod.EventBusSubscriber`. This annotation is discovered automatically by NeoForge, allowing you to remove all event-related code from the mod constructor. In essence, it is equivalent to calling `NeoForge.EVENT_BUS.register(EventHandler.class)` at the end of the mod constructor. This means that all handlers must be static, too.
+我们可以进一步优化,将事件处理类标注为 `@Mod.EventBusSubscriber`。这个注解会被 NeoForge 自动识别,允许你从模组构造函数中移除所有与事件相关的代码。实际上,这等同于在模组构造结束时调用 `NeoForge.EVENT_BUS.register(EventHandler.class)`。这也意味着所有的处理函数必须设置为静态。
-While not required, it is highly recommended to specify the `modid` parameter in the annotation, in order to make debugging easier (especially when it comes to mod conflicts).
+虽然不是必须的,但强烈建议在注解中指定 `modid` 参数,以便在处理模组冲突时能够更容易进行调试。
```java
@Mod.EventBusSubscriber(modid = "yourmodid")
@@ -93,87 +93,41 @@ public class EventHandler {
}
```
-## Event Options
+### 生命周期事件
-### Fields and Methods
+大多数模组总
-Fields and methods are probably the most obvious part of an event. Most events contain context for the event handler to use, such as an entity causing the event or a level the event occurs in.
+线事件被称为生命周期事件。生命周期事件在每个模组的生命周期中仅在启动时运行一次。很多这类事件是并行触发的,如果你想要在主线程上运行这些事件的代码,可以使用 `#enqueueWork(Runnable runnable)` 方法将它们加入队列。
-### Hierarchy
+生命周期事件通常按以下顺序进行:
-In order to use the advantages of inheritance, some events do not directly extend `Event`, but one of its subclasses, for example `BlockEvent` (which contains block context for block-related events) or `EntityEvent` (which similarly contains entity context) and its subclasses `LivingEvent` (for `LivingEntity`-specific context) and `PlayerEvent` (for `Player`-specific context). These context-providing super events are `abstract` and cannot be listened to.
-
-:::danger
-If you listen to an `abstract` event, your game will crash, as this is never what you want. You always want to listen to one of the subevents instead.
-:::
-
-### Cancellable Events
-
-Some events implement the `ICancellableEvent` interface. These events can be cancelled using `#setCanceled(boolean canceled)`, and the cancellation status can be checked using `#isCanceled()`. If an event is cancelled, other event handlers for this event will not run, and some kind of behavior that is associated with "cancelling" is enabled. For example, cancelling `LivingJumpEvent` will prevent the jump.
-
-Event handlers can opt to explicitly receive cancelled events. This is done by setting the `receiveCanceled` parameter in `IEventBus#addListener` (or `@SubscribeEvent`, depending on your way of attaching the event handlers) to true.
-
-### Results
-
-Some events have a `Result`. A `Result` can be one of three things: `DENY` which stops the event, `ALLOW` which force-runs the event, and `DEFAULT` which uses the Vanilla behavior. The result of an event can be set by calling `Event#setResult`. Not all events have results; an event with a result will be annotated with `@HasResult`.
-
-:::caution
-Results are deprecated and will be replaced by more specific per-event results soon.
-:::
-
-### Priority
-
-Event handlers can optionally get assigned a priority. The `EventPriority` enum contains five values: `HIGHEST`, `HIGH`, `NORMAL` (default), `LOW` and `LOWEST`. Event handlers are executed from highest to lowest priority. If they have the same priority, they fire in registration order on the main bus, which is roughly related to mod load order, and in exact mod load order on the mod bus (see below).
-
-Priorities can be defined by setting the `priority` parameter in `IEventBus#addListener` or `@SubscribeEvent`, depending on how you attach event handlers. Note that priorities are ignored for events that are fired in parallel.
-
-### Sided Events
-
-Some events are only fired on one [side][side]. Common examples include the various render events, which are only fired on the client. Since client-only events generally need to access other client-only parts of the Minecraft codebase, they need to be registered accordingly.
-
-Event handlers that use `IEventBus#addListener()` should use a `FMLEnvironment.dist` check and a separate client-only class, as outlined in the article on sides.
-
-Event handlers that use `@Mod.EventBusSubscriber` can specify the side as the `value` parameter of the annotation, for example `@Mod.EventBusSubscriber(value = Dist.CLIENT, modid = "yourmodid")`.
-
-## Event Buses
-
-While most events are posted on the `NeoForge.EVENT_BUS`, some events are posted on the mod event bus instead. These are generally called mod bus events. Mod bus events can be distinguished from regular events by their superinterface `IModBusEvent`.
-
-The mod event bus is passed to you as a parameter in the mod constructor, and you can then subscribe mod bus events to it. If you use `@Mod.EventBusSubscriber`, you can also set the bus as an annotation parameter, like so: `@Mod.EventBusSubscriber(bus = Bus.MOD, modid = "yourmodid")`. The default bus is `Bus.FORGE`.
-
-### The Mod Lifecycle
-
-Most mod bus events are what is known as lifecycle events. Lifecycle events run once in every mod's lifecycle during startup. Many of them are fired in parallel; if you want to run code from one of these events on the main thread, enqueue them using `#enqueueWork(Runnable runnable)`.
-
-The lifecycle generally follows the following order:
-
-- The mod constructor is called. Register your event handlers here, or in the next step.
-- All `@Mod.EventBusSubscriber`s are called.
-- `FMLConstructModEvent` is fired.
-- The registry events are fired, these include [`NewRegistryEvent`][newregistry], [`DataPackRegistryEvent.NewRegistry`][newdatapackregistry] and, for each registry, [`RegisterEvent`][registerevent].
-- `FMLCommonSetupEvent` is fired. This is where various miscellaneous setup happens.
-- The [sided][side] setup is fired: `FMLClientSetupEvent` if on a physical client, and `FMLDedicatedServerSetupEvent` if on a physical server.
-- `InterModComms` are handled (see below).
-- `FMLLoadCompleteEvent` is fired.
+- 调用模组构造函数。在这里或下一步注册你的事件处理函数。
+- 所有的 `@Mod.EventBusSubscriber` 被调用。
+- 触发 `FMLConstructModEvent` 事件。
+- 触发注册事件,包括 [`NewRegistryEvent`][newregistry]、[`DataPackRegistryEvent.NewRegistry`][newdatapackregistry] 以及每个注册表的 [`RegisterEvent`][registerevent]。
+- 触发 `FMLCommonSetupEvent` 事件。这是进行各种杂项设置的阶段。
+- 根据服务器类型触发侧边设置事件:如果在客户端,则为 `FMLClientSetupEvent`;如果在服务器,则为 `FMLDedicatedServerSetupEvent`。
+- 处理 `InterModComms`(详情见下文)。
+- 触发 `FMLLoadCompleteEvent` 事件。
#### `InterModComms`
-`InterModComms` is a system that allows modders to send messages to other mods for compatibility features. The class holds the messages for mods, all methods are thread-safe to call. The system is mainly driven by two events: `InterModEnqueueEvent` and `InterModProcessEvent`.
+`InterModComms` 是一个系统,允许模组开发者向其他模组发送消息以实现功能兼容。这个系统保存了模组的消息,所有方法都是线程安全的。主要通过两个事件推动:`InterModEnqueueEvent` 和 `InterModProcessEvent`。
-During `InterModEnqueueEvent`, you can use `InterModComms#sendTo` to send messages to other mods. These methods accept the id of the mod to send the message to, the key associated with the message data (to distinguish between different messages), and a `Supplier` holding the message data. The sender can be optionally specified as well.
+在 `InterModEnqueueEvent` 期间,你可以使用 `InterModComms#sendTo` 向其他模组发送消息。这些方法接受要发送消息到的模组的 ID、与消息数据相关的键(以区分不同的消息),以及持有消息数据的 `Supplier`。发送者可以选择性指定。
-Then, during `InterModProcessEvent`, you can use `InterModComms#getMessages` to get a stream of all received messages as `IMCMessage` objects. These hold the sender of the data, the intended receiver of the data, the data key, and the supplier for the actual data.
+接着,在 `InterModProcessEvent` 期间,你可以使用 `InterModComms#getMessages` 获取作为 `IMCMessage` 对象的所有接收到的消息的流。这些消息包含了数据的发送者、预期的接收者、数据键和实际数据的供应商。
-### Other Mod Bus Events
+### 其他模组总线事件
-Next to the lifecycle events, there are a few miscellaneous events that are fired on the mod event bus, mostly for legacy reasons. These are generally events where you can register, set up, or initialize various things. Most of these events are not ran in parallel in contrast to the lifecycle events. A few examples:
+除了生命周期事件外,还有一些其他在模组总线上触发的杂项事件,主要是出于历史原因。这些事件通常不是并行运行的,与生命周期事件相反。例如:
- `RegisterColorHandlersEvent`
- `ModelEvent.BakingCompleted`
- `TextureStitchEvent`
:::warning
-Most of these events are planned to be moved to the main event bus in a future version.
+计划在未来版本中将大多数这些事件转移到主事件总线上。
:::
[modbus]: #event-buses
From e8f8f0f05a303a3177ba43f461438eb0f5fdc90c Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 15:25:33 +0800
Subject: [PATCH 28/87] Update registries.md
---
docs/concepts/registries.md | 180 ++++++++++++++++++------------------
1 file changed, 92 insertions(+), 88 deletions(-)
diff --git a/docs/concepts/registries.md b/docs/concepts/registries.md
index 5dea1fab0..c959c41e3 100644
--- a/docs/concepts/registries.md
+++ b/docs/concepts/registries.md
@@ -1,90 +1,92 @@
-# Registries
+# 注册
-Registration is the process of taking the objects of a mod (such as [items][item], [blocks][block], entities, etc.) and making them known to the game. Registering things is important, as without registration the game will simply not know about these objects, which will cause unexplainable behaviors and crashes.
+注册是将模组中的对象(如[物品][item]、[方块][block]、实体等)加入游戏并使其被游戏识别的过程。注册这些对象非常重要,因为如果不注册,游戏将无法识别这些对象,这将导致无法解释的行为和崩溃。
-A registry is, simply put, a wrapper around a map that maps registry names (read on) to registered objects, often called registry entries. Registry names must be unique within the same registry, but the same registry name may be present in multiple registries. The most common example for this are blocks (in the `BLOCKS` registry) that have an item form with the same registry name (in the `ITEMS` registry).
+简而言之,注册表是围绕映射注册名称(下面将说明)到注册对象的映射的封装,这些注册对象通常称为注册表项。注册名在同一注册表中必须唯一,但同一注册名可以出现在多个注册表中。最常见的例子是方块(在`BLOCKS`注册表中)具有与其同名的物品形式(在`ITEMS`注册表中)。
-Every registered object has a unique name, called its registry name. The name is represented as a [`ResourceLocation`][resloc]. For example, the registry name of the dirt block is `minecraft:dirt`, and the registry name of the zombie is `minecraft:zombie`. Modded objects will of course not use the `minecraft` namespace; their mod id will be used instead.
+每个注册对象都有一个唯一的名称,称为其注册名称。名称表示为[`ResourceLocation`][resloc]。例如,泥土方块的注册名称为`minecraft:dirt`,僵尸的注册名称为`minecraft:zombie`。当然,模组化对象不会使用`minecraft`命名空间;而是使用它们的模组ID。
-## Vanilla vs. Modded
+## 原版与模组化
-To understand some of the design decisions that were made in NeoForge's registry system, we will first look at how Minecraft does this. We will use the block registry as an example, as most other registries work the same way.
+为了理解NeoForge的注册系统中所做的一些设计决策,我们首先看看Minecraft是如何处理这一问题的。我们将使用方块注册表作为例子,因为大多数其他注册表的工作方式相同。
-Registries generally register [singletons][singleton]. This means that all registry entries exist exactly once. For example, all stone blocks you see throughout the game are actually the same stone block, displayed many times. If you need the stone block, you can get it by referencing the registered block instance.
+注册表通常注册[单例][singleton]。这意味着所有注册表项实际上只存在一次。例如,你在游戏中看到的所有石块实际上都是同一个石块,被多次显示。如果你需要石块,可以通过引用已注册的方块实例来获取它。
-Minecraft registers all blocks in the `Blocks` class. Through the `register` method, `Registry#register()` is called, with the block registry at `BuiltInRegistries.BLOCK` being the first parameter. After all blocks are registered, Minecraft performs various checks based on the list of blocks, for example the self check that verifies that all blocks have a model loaded.
+Minecraft在`Blocks`类中注册所有方块。通过`register`方法,调用`Registry#register()`,其中第一个参数是方块注册表`BuiltInRegistries.BLOCK`。所有方块注册完成后,Minecraft会根据方块列表进行各种检查,例如验证所有方块是否已加载模型的自检。
-The main reason all of this works is that `Blocks` is classloaded early enough by Minecraft. Mods are not automatically classloaded by Minecraft, and thus workarounds are needed.
+这一切之所以能够工作,是因为`Blocks`类在Minecraft中足够早地被类加载。模组并不会被Minecraft自动类加载,因此需要一些变通方法。
-## Methods for Registering
+## 注册方法
-NeoForge offers two ways to register objects: the `DeferredRegister` class, and the `RegisterEvent`. Note that the former is a wrapper around the latter, and is recommended in order to prevent mistakes.
+NeoForge提供了两种注册对象的方式:`DeferredRegister`类和`RegisterEvent`。请注意,前者是后者的封装,并且为了防止错误,推荐使用。
### `DeferredRegister`
-We begin by creating our `DeferredRegister`:
+我们首先创建我们的`DeferredRegister`:
```java
public static final DeferredRegister BLOCKS = DeferredRegister.create(
- // The registry we want to use.
- // Minecraft's registries can be found in BuiltInRegistries, NeoForge's registries can be found in NeoForgeRegistries.
- // Mods may also add their own registries, refer to the individual mod's documentation or source code for where to find them.
+ // 我们想要使用的注册表。
+ // Minecraft的注册表可以在BuiltInRegistries中找到,NeoForge的注册表可以在NeoForgeRegistries中找到。
+ // 模组也可以添加它们自己的注册表,具体请参考各个模组的文档或源代码。
BuiltInRegistries.BLOCKS,
- // Our mod id.
+ // 我们的模组ID。
ExampleMod.MOD_ID
);
```
-We can then add our registry entries as static final fields (see [the article on Blocks][block] for what parameters to add in `new Block()`):
+然后,我们可以将我们的注册表项添加为静态最终字段(有关在`new Block()`中添加什么参数,请参阅[关于方块的文章][block]):
```java
public static final DeferredHolder EXAMPLE_BLOCK = BLOCKS.register(
- "example_block" // Our registry name.
- () -> new Block(...) // A supplier of the object we want to register.
+ "example_block" // 我们的注册名称。
+ () -> new Block(...) // 我们想要注册的对象的供应商。
);
```
-The class `DeferredHolder` holds our object. The type parameter `R` is the type of the registry we are registering to (in our case `Block`). The type parameter `T` is the type of our supplier. Since we directly register a `Block` in this example, we provide `Block` as the second parameter. If we were to register an object of a subclass of `Block`, for example `SlabBlock`, we would provide `SlabBlock` here instead.
+`DeferredHolder`类持有我们的对象。类型参数`R`是我们正在注册到的注册表的类型(在这个例子中是`Block`)。类型参数`T`是我们供应商的类型。由于我们在这个例子中直接注册了一个`Block`,我们提供了`Block`作为第二个参数。如果我们
-`DeferredHolder` is a subclass of `Supplier`. To get our registered object when we need it, we can call `DeferredHolder#get()`. The fact that `DeferredHolder` extends `Supplier` also allows us to use `Supplier` as the type of our field. That way, the above code block becomes the following:
+要注册一个`Block`的子类的对象,例如`SlabBlock`,我们将在此提供`SlabBlock`。
+
+`DeferredHolder`是`Supplier`的子类。当我们需要时可以调用`DeferredHolder#get()`来获取我们注册的对象。`DeferredHolder`扩展`Supplier`的事实也允许我们使用`Supplier`作为我们字段的类型。这样,上面的代码块变为以下内容:
```java
public static final Supplier EXAMPLE_BLOCK = BLOCKS.register(
- "example_block" // Our registry name.
- () -> new Block(...) // A supplier of the object we want to register.
+ "example_block" // 我们的注册名称。
+ () -> new Block(...) // 我们想要注册的对象的供应商。
);
```
-Be aware that a few places explicitly require a `Holder` or `DeferredHolder` and will not just accept any `Supplier`. If you need either of those two, it is best to change the type of your `Supplier` back to `Holder` or `DeferredHolder` as necessary.
+请注意,有些地方明确要求使用`Holder`或`DeferredHolder`,而不仅仅接受任何`Supplier`。如果你需要其中的两者之一,最好将你的`Supplier`的类型更改回`Holder`或`DeferredHolder`。
-Finally, since the entire system is a wrapper around registry events, we need to tell the `DeferredRegister` to attach itself to the registry events as needed:
+最后,由于整个系统是围绕注册事件的封装,我们需要告诉`DeferredRegister`根据需要将自己附加到注册事件上:
```java
-//This is our mod constructor
+// 这是我们的模组构造函数
public ExampleMod(IModEventBus bus) {
- //highlight-next-line
+ // 高亮下一行
ExampleBlocksClass.BLOCKS.register(bus);
- //Other stuff here
+ // 这里还有其他内容
}
```
:::info
-There are specialized variants of `DeferredRegister`s for blocks and items that provide helper methods, called [`DeferredRegister.Blocks`][defregblocks] and [`DeferredRegister.Items`][defregitems], respectively.
+有针对方块和物品的`DeferredRegister`的特化变体,它们提供辅助方法,分别称为[`DeferredRegister.Blocks`][defregblocks]和[`DeferredRegister.Items`][defregitems]。
:::
### `RegisterEvent`
-`RegisterEvent` is the second way to register objects. This [event][event] is fired for each registry, after the mod constructors (since those are where `DeferredRegister`s register their internal event handlers) and before the loading of configs. `RegisterEvent` is fired on the mod event bus.
+`RegisterEvent`是注册对象的第二种方式。这个[事件][event]在模组构造函数之后(因为这是`DeferredRegister`注册它们内部事件处理器的地方)和加载配置之前为每个注册表触发。`RegisterEvent`在模组事件总线上触发。
```java
@SubscribeEvent
public void register(RegisterEvent event) {
event.register(
- // This is the registry key of the registry.
- // Get these from BuiltInRegistries for vanilla registries,
- // or from NeoForgeRegistries.Keys for NeoForge registries.
+ // 这是注册表的注册键。
+ // 从BuiltInRegistries获取vanilla注册表的,
+ // 或从NeoForgeRegistries.Keys获取NeoForge注册表的。
BuiltInRegistries.BLOCKS,
- // Register your objects here.
+ // 在这里注册你的对象。
registry -> {
registry.register(new ResourceLocation(MODID, "example_block_1"), new Block(...));
registry.register(new ResourceLocation(MODID, "example_block_2"), new Block(...));
@@ -94,29 +96,31 @@ public void register(RegisterEvent event) {
}
```
-## Querying Registries
+## 查询注册表
-Sometimes, you will find yourself in situations where you want to get a registered object by a given id. Or, you want to get the id of a certain registered object. Since registries are basically maps of ids (`ResourceLocation`s) to distinct objects, i.e. a reversible map, both of these operations work:
+有时候,你可能会发现自己处于想要通过给定ID获取注册对象的情况,或者你想要获取某个注册对象的ID。由于注册表本质上是ID(`ResourceLocation`)到独立对象的映射,即可逆映射,这两种操作都是可行的:
```java
-BuiltInRegistries.BLOCKS.get(new ResourceLocation("minecraft", "dirt")); // returns the dirt block
-BuiltInRegistries.BLOCKS.getKey(Blocks.DIRT); // returns the resource location "minecraft:dirt"
+BuiltInRegistries.BLOCKS.get(new ResourceLocation("minecraft", "dirt")); // 返回泥土方块
+BuiltInRegistries.BLOCKS.getKey(Blocks.DIRT); // 返回资源位置"minecraft:dirt"
-// Assume that ExampleBlocksClass.EXAMPLE_BLOCK.get() is a Supplier with the id "yourmodid:example_block"
-BuiltInRegistries.BLOCKS.get(new ResourceLocation("yourmodid", "example_block")); // returns the example block
-BuiltInRegistries.BLOCKS.getKey(ExampleBlocksClass.EXAMPLE_BLOCK.get()); // returns the resource location "yourmodid:example_block"
+// 假设ExampleBlocksClass.EXAMPLE_BLOCK.get()是具有ID"yourmodid:example_block"的Supplier
+BuiltInRegistries.BLOCKS.get(new ResourceLocation("yourmodid", "example_block")); // 返回示例方块
+BuiltInRegistries.BLOCKS.getKey(ExampleBlocksClass.EXAMPLE_BLOCK.get()); // 返回资源位置"yourmodid:example_block"
```
-If you just want to check for the presence of an object, this is also possible, though only with keys:
+如果你只是想检查是否存在某个对象,这也是可能的,尽管只能用键:
```java
BuiltInRegistries.BLOCKS.containsKey(new ResourceLocation("minecraft", "dirt")); // true
-BuiltInRegistries.BLOCKS.containsKey(new ResourceLocation("create", "brass_ingot")); // true only if Create is installed
+BuiltInRegistries.BLOCKS.containsKey(new ResourceLocation("create", "brass_ingot")); // 如果安装了Create则为true
```
-As the last example shows, this is possible with any mod id, and thus a perfect way to check if a certain item from another mod exists.
+正如最后一个示例所示,这适用于任何模组ID,因此是检查另一个模组中是否存在某个物品的完美方式。
+
+最后,我们还可以迭代注册表中的所有条目,无论是键还
-Finally, we can also iterate over all entries in a registry, either over the keys or over the entries (entries use the Java `Map.Entry` type):
+是条目(条目使用Java的`Map.Entry`类型):
```java
for (ResourceLocation id : BuiltInRegistries.BLOCKS.keySet()) {
@@ -128,22 +132,22 @@ for (Map.Entry entry : BuiltInRegistries.BLOCKS.entrySe
```
:::note
-Query operations always use vanilla `Registry`s, not `DeferredRegister`s. This is because `DeferredRegister`s are merely registration utilities.
+查询操作始终使用vanilla `Registry`,而不是`DeferredRegister`。这是因为`DeferredRegister`只是注册工具。
:::
:::danger
-Query operations are only safe to use after registration has finished. **DO NOT QUERY REGISTRIES WHILE REGISTRATION IS STILL ONGOING!**
+查询操作只有在注册完成后才安全使用。**不要在注册仍在进行时查询注册表!**
:::
-## Custom Registries
+## 自定义注册表
-Custom registries allow you to specify additional systems that addon mods for your mod may want to plug into. For example, if your mod were to add spells, you could make the spells a registry and thus allow other mods to add spells to your mod, without you having to do anything else. It also allows you to do some things, such as syncing the entries, automatically.
+自定义注册表允许你指定其他模组可能想要接入的附加系统。例如,如果你的模组要添加效果,你可以使效果成为一个注册表,从而允许其他模组添加效果到你的模组中,而无需你做任何其他事情。它还允许你自动执行一些操作,如同步条目。
-Let's start by creating the [registry key][resourcekey] and the registry itself:
+让我们从创建[注册表键][resourcekey]和注册表本身开始:
```java
-// We use spells as an example for the registry here, without any details about what a spell actually is (as it doesn't matter).
-// Of course, all mentions of spells can and should be replaced with whatever your registry actually is.
+// 我们在这里使用效果作为注册表的例子,不涉及效果实际是什么(因为这不重要)。
+// 当然,所有提到的效果都可以并且应该替换为你的注册表实际是什么。
public static final ResourceKey> SPELL_REGISTRY_KEY = ResourceKey.createRegistryKey(new ResourceLocation("yourmodid", "spells"));
public static final Registry SPELL_REGISTRY = new RegistryBuilder<>(SPELL_REGISTRY_KEY)
// If you want to enable integer id syncing, for networking.
@@ -157,7 +161,7 @@ public static final Registry SPELL_REGISTRY = new Registry
.create();
```
-Then, tell the game that the registry exists by registering them to the root registry in `NewRegistryEvent`:
+然后,通过将注册表注册到 `NewRegistryEvent` 中的根注册表来告诉游戏注册表存在:
```java
@SubscribeEvent
@@ -166,8 +170,7 @@ static void registerRegistries(NewRegistryEvent event) {
}
```
-You can now register new registry contents like with any other registry, through both `DeferredRegister` and `RegisterEvent`:
-
+现在,您可以像使用任何其他注册表一样,通过`DeferredRegister`和`RegisterEvent`注册新的注册表内容:
```java
public static final DeferredRegister SPELLS = DeferredRegister.create("yourmodid", SPELL_REGISTRY);
public static final Supplier EXAMPLE_SPELL = SPELLS.register("example_spell", () -> new Spell(...));
@@ -181,20 +184,20 @@ public static void register(RegisterEvent event) {
}
```
-## Datapack Registries
+# 数据包注册表
-A datapack registry (also known as a dynamic registry or, after its main use case, worldgen registry) is a special kind of registry that loads data from [datapack][datapack] JSONs (hence the name) at world load, instead of loading them when the game starts. Default datapack registries most notably include most worldgen registries, among a few others.
+数据包注册表(也称为动态注册表或世界生成注册表)是一种特殊的注册表,它在世界加载时从数据包 JSON 文件中加载数据,而不是在游戏启动时加载。默认的数据包注册表主要包括大多数世界生成注册表和其他一些注册表。
-Datapack registries allow their contents to be specified in JSON files. This means that no code (other than [datagen][datagen] if you don't want to write the JSON files yourself) is necessary. Every datapack registry has a [`Codec`][codec] associated with it, which is used for serialization, and each registry's id determines its datapack path:
+数据包注册表允许通过 JSON 文件指定其内容。这意味着除了数据生成工具外,不需要任何代码(如果你不想自己编写 JSON 文件的话)。每个数据包注册表都有一个与之关联的编解码器(`Codec`),用于序列化,每个注册表的 ID 决定了其数据包路径:
-- Minecraft's datapack registries use the format `data/yourmodid/registrypath` (for example `data/yourmodid/worldgen/biomes`, where `worldgen/biomes` is the registry path).
-- All other datapack registries (NeoForge or modded) use the format `data/yourmodid/registrynamespace/registrypath` (for example `data/yourmodid/neoforge/loot_modifiers`, where `neoforge` is the registry namespace and `loot_modifiers` is the registry path).
+- Minecraft 的数据包注册表使用格式 `data/yourmodid/registrypath`(例如 `data/yourmodid/worldgen/biomes`,其中 `worldgen/biomes` 是注册表路径)。
+- 所有其他数据包注册表(NeoForge 或模组化的)使用格式 `data/yourmodid/registrynamespace/registrypath`(例如 `data/yourmodid/neoforge/loot_modifiers`,其中 `neoforge` 是注册表命名空间,`loot_modifiers` 是注册表路径)。
-Datapack registries can be obtained from a `RegistryAccess`. This `RegistryAccess` can be retrieved by calling `ServerLevel#registryAccess()` if on the server, or `Minecraft.getInstance().connection#registryAccess()` if on the client (the latter only works if you are actually connected to a world, as otherwise the connection will be null). The result of these calls can then be used like any other registry to get specific elements, or to iterate over the contents.
+可以从 `RegistryAccess` 获取数据包注册表。如果在服务器上,可以通过调用 `ServerLevel#registryAccess()` 来检索此 `RegistryAccess`;如果在客户端,可以通过调用 `Minecraft.getInstance().connection#registryAccess()` 来检索(后者仅在实际连接到世界时有效,否则连接将为 null)。然后可以像使用任何其他注册表一样使用这些调用的结果来获取特定元素或遍历内容。
-### Custom Datapack Registries
+### 自定义数据包注册表
-Custom datapack registries do not require a `Registry` to be constructed. Instead, they just need a registry key and at least one [`Codec`][codec] to (de-)serialize its contents. Reiterating on the spells example from before, registering our spell registry as a datapack registry looks something like this:
+自定义数据包注册表不需要构建 `Registry`。相反,它们只需要一个注册表键和至少一个编解码器(`Codec`)来序列化和反序列化其内容。根据之前的法术示例,将我们的法术注册表注册为数据包注册表的过程如下所示:
```java
public static final ResourceKey> SPELL_REGISTRY_KEY = ResourceKey.createRegistryKey(new ResourceLocation("yourmodid", "spells"));
@@ -202,51 +205,52 @@ public static final ResourceKey> SPELL_REGISTRY_KEY = ResourceKe
@SubscribeEvent
public static void registerDatapackRegistries(DataPackRegistryEvent.NewRegistry event) {
event.dataPackRegistry(
- // The registry key.
+ // 注册表键。
SPELL_REGISTRY_KEY,
- // The codec of the registry contents.
+ // 注册表内容的编解码器。
Spell.CODEC,
- // The network codec of the registry contents. Often identical to the normal codec.
- // May be a reduced variant of the normal codec that omits data that is not needed on the client.
- // May be null. If null, registry entries will not be synced to the client at all.
- // May be omitted, which is functionally identical to passing null (a method overload
- // with two parameters is called that passes null to the normal three parameter method).
+ // 网络编解码器。通常与普通编解码器相同。
+ // 可能是普通编解码器的简化版本,省略了客户端不需要的数据。
+ // 可能为 null。如果为 null,则注册表条目根本不会同步到客户端。
+ // 可以省略,这在功能上与传递 null 相同(调用了一个带有两个参数的方法重载,该重载向普通的三参数方法传递 null)。
Spell.CODEC
);
}
```
-### Data Generation for Datapack Registries
+### 数据包注册表的数据生成
-Since writing all the JSON files by hand is both tedious and error-prone, NeoForge provides a [data provider][datagenindex] to generate the JSON files for you. This works for both built-in and your own datapack registries.
+由于手工编写所有 JSON 文件既繁琐又容易出错,NeoForge 提供了一个数据提供器来为你生成 JSON 文件。这适用于内置的和你自己的数据包注册表。
-First, we create a `RegistrySetBuilder` and add our entries to it (one `RegistrySetBuilder` can hold entries for multiple registries):
+首先,我们创建一个 `RegistrySetBuilder` 并向其添加条目(一个 `RegistrySetBuilder` 可以包含多个注册表的条目):
```java
new RegistrySetBuilder()
.add(Registries.CONFIGURED_FEATURE, bootstrap -> {
- // Register configured features through the bootstrap context (see below)
+ // 通过引导上下文注册配置特性。
})
.add(Registries.PLACED_FEATURE, bootstrap -> {
- // Register placed features through the bootstrap context (see below)
+ // 通过引导上下文注册放置特性。
});
```
-The `bootstrap` lambda parameter is what we actually use to register our objects. It has the type `BootstrapContext`. To register an object, we call `#register` on it, like so:
+`bootstrap` lambda 参数是我们实际用来注册对象的。要注册一个对象,我们这样调用 `#register`:
```java
-// The resource key of our object.
+// 我们对象的资源键。
public static final ResourceKey> EXAMPLE_CONFIGURED_FEATURE = ResourceKey.create(
Registries.CONFIGURED_FEATURE,
- new ResourceLocation(MOD_ID, "example_configured_feature")
+ new ResourceLocation(MOD_ID, "example_configured_feature
+
+")
);
new RegistrySetBuilder()
.add(Registries.CONFIGURED_FEATURE, bootstrap -> {
bootstrap.register(
- // The resource key of our configured feature.
+ // 我们配置特性的资源键。
EXAMPLE_CONFIGURED_FEATURE,
- // The actual configured feature.
+ // 实际的配置特性。
new ConfiguredFeature<>(Feature.ORE, new OreConfiguration(...))
);
})
@@ -255,7 +259,7 @@ new RegistrySetBuilder()
});
```
-The `BootstrapContext` (name is typoed as `BootstapContext` in 1.20.4 and below) can also be used to lookup entries from another registry if needed:
+如果需要,`BootstrapContext`(在 1.20.4 及以下版本中名称误写为 `BootstapContext`)还可以用来从另一个注册表查找条目:
```java
public static final ResourceKey> EXAMPLE_CONFIGURED_FEATURE = ResourceKey.create(
@@ -274,27 +278,27 @@ new RegistrySetBuilder()
.add(Registries.PLACED_FEATURE, bootstrap -> {
HolderGetter> otherRegistry = bootstrap.lookup(Registries.CONFIGURED_FEATURE);
bootstrap.register(EXAMPLE_PLACED_FEATURE, new PlacedFeature(
- otherRegistry.getOrThrow(EXAMPLE_CONFIGURED_FEATURE), // Get the configured feature
- List.of() // No-op when placement happens - replace with whatever your placement parameters are
+ otherRegistry.getOrThrow(EXAMPLE_CONFIGURED_FEATURE), // 获取配置特性
+ List.of() // 放置发生时无操作 - 替换为你的放置参数
));
});
```
-Finally, we use our `RegistrySetBuilder` in an actual data provider, and register that data provider to the event:
+最后,我们在实际的数据提供器中使用我们的 `RegistrySetBuilder` 并将该数据提供器注册到事件中:
```java
@SubscribeEvent
static void onGatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
- // Only run datapack generation when server data is being generated
+ // 仅在生成服务器数据时运行数据包生成
event.includeServer(),
- // Create the provider
+ // 创建提供器
output -> new DatapackBuiltinEntriesProvider(
output,
event.getLookupProvider(),
- // Our registry set builder to generate the data from.
+ // 我们的注册表集生成器来生成数据。
new RegistrySetBuilder().add(...),
- // A set of mod ids we are generating. Usually only your own mod id.
+ // 我们正在生成的模组 ID 集合。通常只有你自己的模组 ID。
Set.of("yourmodid")
)
);
From 727475b9591e3158d2ae9b7068d6b211794f2606 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 15:29:16 +0800
Subject: [PATCH 29/87] Update sides.md
---
docs/concepts/sides.md | 52 ++++++++++++++++++++++--------------------
1 file changed, 27 insertions(+), 25 deletions(-)
diff --git a/docs/concepts/sides.md b/docs/concepts/sides.md
index 48712d430..e2154f25c 100644
--- a/docs/concepts/sides.md
+++ b/docs/concepts/sides.md
@@ -1,60 +1,62 @@
-# Sides
+# 游戏两侧的区分
-Like many other programs, Minecraft follows a client-server concept, where the client is responsible for displaying the data, while the server is responsible for updating them. When using these terms, we have a fairly intuitive understanding of what we mean... right?
+和许多其他程序一样,Minecraft 遵循客户端-服务器的概念,其中客户端负责显示数据,而服务器负责更新数据。当我们使用这些术语时,我们对其含义有一个相当直观的理解...对吗?
-Turns out, not so much. A lot of the confusion stems from Minecraft having two different concepts of sides, depending on the context: the physical and the logical side.
+事实证明,并非如此。很多混淆源于 Minecraft 有两种不同的“侧”的概念,这取决于上下文:物理侧和逻辑侧。
-## Logical vs. Physical Side
+## 逻辑侧与物理侧
-### The Physical Side
+### 物理侧
-When you open your Minecraft launcher, select a Minecraft installation and press play, you boot up a **physical client**. The word "physical" is used here in the sense of "this is a client program". This especially means that client-side functionality, such as all the rendering stuff, is available here and can be used as needed. In contrast, the **physical server**, also known as dedicated server, is what opens when you launch a Minecraft server JAR. While the Minecraft server comes with a rudimentary GUI, it is missing all client-only functionality. Most notably, this means that various client classes are missing from the server JAR. Calling these classes on the physical server will lead to missing class errors, i.e. crashes, so we need to safeguard against this.
+当你打开 Minecraft 启动器,选择一个 Minecraft 安装并按下播放时,你启动了一个**物理客户端**。这里使用“物理”一词是在“这是一个客户端程序”的意义上。这尤其意味着客户端功能,如所有渲染相关的功能,都可以在这里使用。相比之下,**物理服务器**,也称为专用服务器,是在你启动一个 Minecraft 服务器 JAR 时打开的。虽然 Minecraft 服务器带有一个基本的 GUI,但它缺少所有仅限客户端的功能。最值得注意的是,各种客户端类在服务器 JAR 中缺失。在物理服务器上调用这些类将导致缺少类错误,即崩溃,因此我们需要对此进行防护。
-### The Logical Side
+### 逻辑侧
-The logical side is mainly focused on the internal program structure of Minecraft. The **logical server** is where the game logic runs. Things like time and weather changing, entity ticking, entity spawning, etc. all run on the server. All kinds of data, such as inventory contents, are the server's responsibility as well. The **logical client**, on the other hand, is responsible for displaying everything there is to display. Minecraft keeps all the client code in an isolated `net.minecraft.client` package, and runs it in a separate thread called the Render Thread, while everything else is considered common (i.e. client and server) code.
+逻辑侧主要关注 Minecraft 的内部程序结构。**逻辑服务器**是游戏逻辑运行的地方。如时间和天气变化、实体更新、实体生成等都在服务器上运行。所有种类的数据,如库存内容,也都是服务器的责任。另一方面,**逻辑客户端**负责显示所有需要显示的内容。Minecraft 在一个名为 `net.minecraft.client` 的独立包中保留了所有客户端代码,并在一个名为渲染线程的独立线程中运行它,而其他所有内容都被视为公共代码(即客户端和服务器代码)。
-### What's the Difference?
+### 两者有何区别?
-The difference between physical and logical sides is best exemplified by two scenarios:
+物理侧和逻辑侧之间的区别最好通过两种情况来说明:
-- The player joins a **multiplayer** world. This is fairly straightforward: The player's physical (and logical) client connects to a physical (and logical) server somewhere else - the player does not care where; so long as they can connect, that's all the client knows of, and all the client needs to know.
-- The player joins a **singleplayer** world. This is where things get interesting. The player's physical client spins up a logical server and then, now in the role of the logical client, connects to that logical server on the same machine. If you are familiar with networking, you can think of it as a connection to `localhost` (only conceptually; there are no actual sockets or similar involved).
+- 玩家加入一个**多人游戏**世界。这相当直接:玩家的物理(和逻辑)客户端连接到别处的一个物理(和逻辑)服务器——玩家不关心在哪里;只要他们能连接,这就是所有客户端知道的,也是所有客户端需要知道的。
+- 玩家加入一个**单人游戏**世界。这里的情况变得有趣。玩家的物理客户端启动了一个逻辑服务器,然后现在作为逻辑客户端,连接到同一台机器上的那个逻辑服务器。如果你熟悉网络,你可以把它想象为连接到`localhost`(只是概念上的;没有实际的套接字或类似的东西涉及)。
-These two scenarios also show the main problem with this: If a logical server can work with your code, that alone doesn't guarantee that a physical server will be able to work with as well. This is why you should always test with dedicated servers to check for unexpected behavior. `NoClassDefFoundError`s and `ClassNotFoundException`s due to incorrect client and server separation are among the most common errors there are in modding. Another common mistake is working with static fields and accessing them from both logical sides; this is particularly tricky because there's usually no indication that something is wrong.
+这两种情况也显示了主要问题:如果一个逻辑服务器可以使用你的代码,这并不保证物理服务器也能同样使用。这就是为什么你应该始终使用专用服务器进行测试,以检查意外行为。由于客户端和服务器分离不当导致的`NoClassDefFoundError`和`ClassNotFoundException`是模组制作中最常见的错误之一。另一个常见的错误是使用静态字段,并从两个逻辑侧访问它们;这特别棘手,因为通常没有迹象表明有什么问题。
:::tip
-If you need to transfer data from one side to another, you must [send a packet][networking].
+如果你需要将数据从一侧传输到另一侧,你必须[发送一个数据包
+
+][networking]。
:::
-In the NeoForge codebase, the physical side is represented by an enum called `Dist`, while the logical side is represented by an enum called `LogicalSide`.
+在 NeoForge 代码库中,物理侧由一个名为 `Dist` 的枚举表示,而逻辑侧由一个名为 `LogicalSide` 的枚举表示。
:::info
-Historically, server JARs have had classes the client did not. This is not the case anymore in modern versions; physical servers are a subset of physical clients, if you will.
+从历史上看,服务器 JAR 拥有客户端没有的类。在现代版本中,这种情况已不复存在;如果愿意,可以认为物理服务器是物理客户端的一个子集。
:::
-## Performing Side-Specific Operations
+## 执行侧特定操作
### `Level#isClientSide()`
-This boolean check will be your most used way to check sides. Querying this field on a `Level` object establishes the **logical** side the level belongs to: If this field is `true`, the level is running on the logical client. If the field is `false`, the level is running on the logical server. It follows that the physical server will always contain `false` in this field, but we cannot assume that `false` implies a physical server, since this field can also be `false` for the logical server inside a physical client (i.e. a singleplayer world).
+这个布尔检查将是你最常用的检查侧的方式。在 `Level` 对象上查询此字段可以确定级别所属的**逻辑**侧:如果此字段为 `true`,则级别在逻辑客户端上运行。如果字段为 `false`,则级别在逻辑服务器上运行。据此,物理服务器将始终在此字段中包含 `false`,但我们不能假设 `false` 暗示物理服务器,因为此字段也可能在物理客户端内的逻辑服务器(即单人游戏世界)中为 `false`。
-Use this check whenever you need to determine if game logic and other mechanics should be run. For example, if you want to damage the player every time they click your block, or have your machine process dirt into diamonds, you should only do so after ensuring `#isClientSide` is `false`. Applying game logic to the logical client can cause desynchronization (ghost entities, desynchronized stats, etc.) in the best case, and crashes in the worst case.
+只有在需要确定是否运行游戏逻辑和其他机制时才使用此检查。例如,如果你想在玩家每次点击你的方块时对玩家造成伤害,或者让你的机器将泥土处理成钻石,你应该确保 `#isClientSide` 为 `false` 后再进行。在逻辑客户端应用游戏逻辑可能导致最好的情况下出现数据不同步(幽灵实体、不同步的统计数据等),在最坏的情况下导致崩溃。
:::tip
-This check should be used as your go-to default. Whenever you have a `Level` available, use this check.
+这个检查应该作为你的默认选择。每当你有一个 `Level` 可用时,就使用这个检查。
:::
### `FMLEnvironment.dist`
-`FMLEnvironment.dist` is the **physical** counterpart to a `Level#isClientSide()` check. If this field is `Dist.CLIENT`, you are on a physical client. If the field is `Dist.SERVER`, you are on a physical server.
+`FMLEnvironment.dist` 是 `Level#isClientSide()` 检查的**物理**对应项。如果此字段为 `Dist.CLIENT`,你就在物理客户端上。如果字段为 `Dist.SERVER`,你就在物理服务器上。
-Checking the physical environment is important when dealing with client-only classes. All calls to client-only code should always be encased in a check for `Dist.CLIENT`, and then call to a separate class to prevent accidental classloading:
+检查物理环境在处理仅限客户端的类时非常重要。所有对客户端代码的调用都应始终包含在对 `Dist.CLIENT` 的检查中,并然后调用一个单独的类以防止意外的类加载:
```java
public class SomeCommonClass {
public void someCommonMethod() {
- //SomeClientClass will be loaded if and only if you are on a physical client
+ // 仅当你在物理客户端上时,SomeClientClass 才会被加载
if (FMLEnvironment.dist == Dist.CLIENT) {
SomeClientClass.someClientMethod();
}
@@ -62,14 +64,14 @@ public class SomeCommonClass {
}
public class SomeClientClass {
- public void someClientMethod() {
+ public static void someClientMethod() {
Minecraft.getInstance().whatever();
}
}
```
:::tip
-Mods are generally expected to work on either side. This especially means that if you are developing a client-only mod, you should verify that the mod actually runs on a physical client, and no-op in the event that it does not.
+通常期望模组在任一侧都能工作。这特别意味着,如果你正在开发一个仅限客户端的模组,你应该验证该模组实际上在物理客户端上运行,并且在不运行的情况下无操作。
:::
[networking]: ../networking/index.md
From dc3cb4f04cc8ed01c567ce6036904a43f407a4d7 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 15:32:11 +0800
Subject: [PATCH 30/87] Update advancements.md
---
docs/datagen/advancements.md | 44 ++++++++++++++++++------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/docs/datagen/advancements.md b/docs/datagen/advancements.md
index 61504fb03..bca701e5c 100644
--- a/docs/datagen/advancements.md
+++ b/docs/datagen/advancements.md
@@ -1,24 +1,24 @@
-Advancement Generation
+# 成就生成
======================
-[Advancements] can be generated for a mod by constructing a new `AdvancementProvider` and providing `AdvancementSubProvider`s. Advancements can either be created and supplied manually or, for convenience, created using `Advancement$Builder`. The provider must be [added][datagen] to the `DataGenerator`.
+[成就] 可以通过构建一个新的 `AdvancementProvider` 并提供 `AdvancementSubProvider` 来为模组生成。成就可以手动创建和提供,或者为了方便,使用 `Advancement$Builder` 创建。提供者必须[添加][datagen]到 `DataGenerator` 中。
:::note
-Forge provides an extension for the `AdvancementProvider` called `ForgeAdvancementProvider` which integrates better for generating advancements. So, this documentation will use `ForgeAdvancementProvider` along with the sub provider interface `ForgeAdvancementProvider$AdvancementGenerator`.
+Forge 提供了一个扩展的 `AdvancementProvider`,名为 `ForgeAdvancementProvider`,它更适合生成成就。因此,本文档将使用 `ForgeAdvancementProvider` 以及子提供者接口 `ForgeAdvancementProvider$AdvancementGenerator`。
:::
```java
-// On the MOD event bus
+// 在 MOD 事件总线上
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
- // Tell generator to run only when server data are generating
+ // 仅在生成服务器数据时运行生成器
event.includeServer(),
output -> new ForgeAdvancementProvider(
output,
event.getLookupProvider(),
event.getExistingFileHelper(),
- // Sub providers which generate the advancements
+ // 生成成就的子提供者
List.of(subProvider1, subProvider2, /*...*/)
)
);
@@ -28,41 +28,41 @@ public void gatherData(GatherDataEvent event) {
`ForgeAdvancementProvider$AdvancementGenerator`
-----------------------------------------------
-A `ForgeAdvancementProvider$AdvancementGenerator` is responsible for generating advancements, containing a method which takes in a registry lookup, the writer (`Consumer`), and the existing file helper..
+`ForgeAdvancementProvider$AdvancementGenerator` 负责生成成就,包含一个方法,该方法接收注册表查找、写入者 (`Consumer`) 和现有文件助手。
```java
-// In some subclass of ForgeAdvancementProvider$AdvancementGenerator or as a lambda reference
+// 在 ForgeAdvancementProvider$AdvancementGenerator 的某个子类中或作为 lambda 引用
@Override
public void generate(HolderLookup.Provider registries, Consumer writer, ExistingFileHelper existingFileHelper) {
- // Build advancements here
+ // 在这里构建成就
}
```
`Advancement$Builder`
---------------------
-`Advancement$Builder` is a convenience implementation for creating `Advancement`s to generate. It allows the definition of the parent advancement, the display information, the rewards when the advancement has been completed, and the requirements to unlock the advancement. Only the requirements need to be specified to create an `Advancement`.
+`Advancement$Builder` 是一个便利的实现,用于创建用于生成的 `Advancement`。它允许定义父成就、显示信息、完成成就时的奖励以及解锁成就的要求。只需指定要求即可创建一个 `Advancement`。
-Although not required, there are a number of methods that are important to know of:
+虽然不是必需的,但有几个方法是重要的:
-Method | Description
+方法 | 描述
:---: | :---
-`parent` | Sets the advancement which this advancement is directly linked to. Can either specify the name of the advancement or the advancement itself if its generated by the modder.
-`display` | Sets the information to display to the chat, toast, and advancement screen.
-`rewards` | Sets the rewards obtained when this advancement is completed.
-`addCriterion` | Adds a condition to the advancement.
-`requirements` | Specifies if the conditions must all return true or at least one must return true. An additional overload can be used to mix-and-match those operations.
+`parent` | 设置此成就直接链接到的成就。可以指定成就的名称或如果由模组制作者生成,则指定成就本身。
+`display` | 设置显示在聊天、弹窗和成就屏幕上的信息。
+`rewards` | 设置完成此成就时获得的奖励。
+`addCriterion` | 为成就添加条件。
+`requirements` | 指定条件是否必须全部为真,或者至少有一个为真。可以使用额外的重载来混合这些操作。
-Once an `Advancement$Builder` is ready to be built, the `#save` method should be called which takes in the writer, the registry name of the advancement, and the file helper used to check whether the supplied parent exists.
+一旦 `Advancement$Builder` 准备好建造,应调用 `#save` 方法,该方法需要写入者、成就的注册名和用于检查提供的父项是否存在的文件助手。
```java
-// In some ForgeAdvancementProvider$AdvancementGenerator#generate(registries, writer, existingFileHelper)
+// 在某个 ForgeAdvancementProvider$AdvancementGenerator#generate(registries, writer, existingFileHelper) 中
Advancement example = Advancement.Builder.advancement()
- .addCriterion("example_criterion", triggerInstance) // How the advancement is unlocked
- .save(writer, name, existingFileHelper); // Add data to builder
+ .addCriterion("example_criterion", triggerInstance) // 如何解锁成就
+ .save(writer, name, existingFileHelper); // 将数据添加到构建器
```
-[advancements]: ../../resources/server/advancements.md
+[成就]: ../../resources/server/advancements.md
[datagen]: ../index.md#data-providers
[conditional]: ../../resources/server/conditional.md
From e8a6dd0a5e23bfca304283ca251d6dd72c67c0bb Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 15:33:10 +0800
Subject: [PATCH 31/87] Update glm.md
---
docs/datagen/glm.md | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/docs/datagen/glm.md b/docs/datagen/glm.md
index 1192b2377..e7aafcebe 100644
--- a/docs/datagen/glm.md
+++ b/docs/datagen/glm.md
@@ -1,23 +1,23 @@
-Global Loot Modifier Generation
+# 全局战利品修改器生成
===============================
-[Global Loot Modifiers (GLMs)][glm] can be generated for a mod by subclassing `GlobalLootModifierProvider` and implementing `#start`. Each GLM can be added generated by calling `#add` and specifying the name of the modifier and the [modifier instance][instance] to be serialized. After implementation, the provider must be [added][datagen] to the `DataGenerator`.
+通过继承 `GlobalLootModifierProvider` 并实现 `#start` 方法,可以为模组生成[全局战利品修改器 (GLMs)][glm]。通过调用 `#add` 并指定修改器的名称和将被序列化的[修改器实例][instance],可以添加生成每个 GLM。实现后,必须将提供者[添加][datagen]到 `DataGenerator`。
```java
-// On the MOD event bus
+// 在 MOD 事件总线上
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
- // Tell generator to run only when server data are generating
+ // 通知生成器仅在生成服务器数据时运行
event.includeServer(),
output -> new MyGlobalLootModifierProvider(output, MOD_ID)
);
}
-// In some GlobalLootModifierProvider#start
+// 在某个 GlobalLootModifierProvider#start 中
this.add("example_modifier", new ExampleModifier(
new LootItemCondition[] {
- WeatherCheck.weather().setRaining(true).build() // Executes when raining
+ WeatherCheck.weather().setRaining(true).build() // 在下雨时执行
},
"val1",
10,
From 77aa38091e31def0e05cd1aa3f866ecaa51f9926 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 15:38:39 +0800
Subject: [PATCH 32/87] Update loottables.md
---
docs/datagen/loottables.md | 84 +++++++++++++++++++-------------------
1 file changed, 43 insertions(+), 41 deletions(-)
diff --git a/docs/datagen/loottables.md b/docs/datagen/loottables.md
index 24bd34a29..da652a3ed 100644
--- a/docs/datagen/loottables.md
+++ b/docs/datagen/loottables.md
@@ -1,20 +1,20 @@
-Loot Table Generation
+# 战利品表生成
=====================
-[Loot tables][loottable] can be generated for a mod by constructing a new `LootTableProvider` and providing `LootTableProvider$SubProviderEntry`s. The provider must be [added][datagen] to the `DataGenerator`.
+通过构建一个新的 `LootTableProvider` 并提供 `LootTableProvider$SubProviderEntry`,可以为模组生成[战利品表][loottable]。提供者必须被[添加][datagen]到 `DataGenerator`。
```java
-// On the MOD event bus
+// 在 MOD 事件总线上
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
- // Tell generator to run only when server data are generating
+ // 告诉生成器仅在生成服务器数据时运行
event.includeServer(),
output -> new MyLootTableProvider(
output,
- // Specify registry names of tables that are required to generate, or can leave empty
+ // 指定需要生成的表的注册名称,或者可以留空
Collections.emptySet(),
- // Sub providers which generate the loot
+ // 生成战利品的子提供者
List.of(subProvider1, subProvider2, /*...*/)
)
);
@@ -24,122 +24,124 @@ public void gatherData(GatherDataEvent event) {
`LootTableSubProvider`
----------------------
-Each `LootTableProvider$SubProviderEntry` takes in a supplied `LootTableSubProvider`, which generates the loot table, for a given `LootContextParamSet`. The `LootTableSubProvider` contains a method which takes in the writer (`BiConsumer`) to generate a table.
+每个 `LootTableProvider$SubProviderEntry` 都接收一个 `LootTableSubProvider`,它为给定的 `LootContextParamSet` 生成战利品表。`LootTableSubProvider` 包含一个方法,该方法接收写入者(`BiConsumer`)来生成表。
```java
public class ExampleSubProvider implements LootTableSubProvider {
- // Used to create a factory method for the wrapping Supplier
+ // 用于创建封装 Supplier 的工厂方法
public ExampleSubProvider() {}
- // The method used to generate the loot tables
+ // 用于生成战利品表的方法
@Override
public void generate(BiConsumer writer) {
- // Generate loot tables here by calling writer#accept
+ // 在这里通过调用 writer#accept 生成战利品表
}
}
```
-The table can then be added to `LootTableProvider#getTables` for any available `LootContextParamSet`:
+然后可以将表添加到 `LootTableProvider#getTables` 中,适用于任何可用的 `LootContextParamSet`:
```java
-// In the list passed into the LootTableProvider constructor
+// 传递到 LootTableProvider 构造函数的列表中
new LootTableProvider.SubProviderEntry(
ExampleSubProvider::new,
- // Loot table generator for the 'empty' param set
+ // 为 'empty' 参数集生成战利品表
LootContextParamSets.EMPTY
)
```
-### `BlockLootSubProvider` and `EntityLootSubProvider` Subclasses
+### `BlockLootSubProvider` 和 `EntityLootSubProvider` 子类
-For `LootContextParamSets#BLOCK` and `#ENTITY`, there are special types (`BlockLootSubProvider` and `EntityLootSubProvider` respectively) which provide additional helper methods for creating and validating that there are loot tables.
+对于 `LootContextParamSets#BLOCK` 和 `#ENTITY`,有特殊类型(分别是 `BlockLootSubProvider` 和 `EntityLootSubProvider`),它们提供额外的辅助方法来创建和验证是否存在战利品表。
-The `BlockLootSubProvider`'s constructor takes in a list of items, which are explosion resistant to determine whether the loot table can be generated if a block is exploded, and a `FeatureFlagSet`, which determines whether the block is enabled so that a loot table is generated for it.
+`BlockLootSubProvider` 的构造函数接受一个物品列表,用于确定如果一个方块被爆炸时是否可以生成战利品表,以及一个 `FeatureFlagSet`,用于确定是否启用了方块以便为其生成战利品表。
```java
-// In some BlockLootSubProvider subclass
+// 在某个 BlockLootSubProvider 子类中
public MyBlockLootSubProvider() {
super(Collections.emptySet(), FeatureFlags.REGISTRY.allFlags());
}
```
-The `EntityLootSubProvider`'s constructor takes in a `FeatureFlagSet`, which determines whether the entity type is enabled so that a loot table is generated for it.
+`EntityLootSubProvider` 的构造函数接受一个 `FeatureFlagSet`,用于确定是否启用了实体类型以便为其生成战利品表。
```java
-// In some EntityLootSubProvider subclass
+// 在某个 EntityLootSubProvider 子类中
public MyEntityLootSubProvider() {
super(FeatureFlags.REGISTRY.allFlags());
}
```
-To use them, all registered objects must be supplied to either `BlockLootSubProvider#getKnownBlocks` and `EntityLootSubProvider#getKnownEntityTypes` respectively. These methods are to make sure all objects within the iterable has a loot table.
+要使用它们,所有已注册的对象必须分别提供给 `BlockLootSubProvider#getKnownBlocks` 和 `EntityLootSubProvider#getKnownEntityTypes`。这些方法确保迭代中的所有对象都有一个战利品表。
:::tip
-If `DeferredRegister` is being used to register a mod's objects, then the `#getKnown*` methods can be supplied the entries via `DeferredRegister#getEntries`:
+如果使用 `DeferredRegister` 来注册模组的对象,则 `#getKnown*` 方法可以通过 `DeferredRegister#getEntries` 提供条目:
```java
-// In some BlockLootSubProvider subclass for some DeferredRegister BLOCK_REGISTRAR
+// 在某个 BlockLootSubProvider 子类中,用于某个 DeferredRegister BLOCK_REGISTRAR
@Override
protected Iterable getKnownBlocks() {
- return BLOCK_REGISTRAR.getEntries() // Get all registered entries
- .stream() // Stream the wrapped objects
- .flatMap(RegistryObject::stream) // Get the object if available
- ::iterator; // Create the iterable
+ return BLOCK_REGISTRAR.getEntries() // 获取所有注册的条目
+ .stream() // 流式处理封装的对象
+ .flatMap(RegistryObject::stream) // 如果可用,则获取对象
+ ::iterator; // 创建迭代器
}
```
:::
-The loot tables themselves can be added by implementing the `#generate` method.
+通过实现 `#generate` 方法可以添加战利品表。
```java
-// In some BlockLootSubProvider subclass
+// 在某个 BlockLootSubProvider 子类中
@Override
-public void generate() {
- // Add loot tables here
+public void
+
+ generate() {
+ // 在这里添加战利品表
}
```
-Loot Table Builders
+战利品表生成器
-------------------
-To generate loot tables, they are accepted by the `LootTableSubProvider` as a `LootTable$Builder`. Afterwards, the specified `LootContextParamSet` is set in the `LootTableProvider$SubProviderEntry` and then built via `#build`. Before being built, the builder can specify entries, conditions, and modifiers which affect how the loot table functions.
+战利品表通过 `LootTableSubProvider` 接收为 `LootTable$Builder`。之后,指定的 `LootContextParamSet` 在 `LootTableProvider$SubProviderEntry` 中设置,然后通过 `#build` 构建。在构建之前,构建器可以指定条目、条件和修饰符,这些因素影响战利品表的功能。
:::note
-The functionality of loot tables is so expansive that it will not be covered by this documentation in its entirety. Instead, a brief description of each component will be mentioned. The specific subtypes of each component can be found using an IDE. Their implementations will be left as an exercise to the reader.
+战利品表的功能非常广泛,本文档无法全部涵盖。相反,每个组件将简要描述。每个组件的具体子类型可以使用 IDE 查找。它们的实现将留给读者作为练习。
:::
### LootTable
-Loot tables are the base object and can be transformed into the required `LootTable$Builder` using `LootTable#lootTable`. The loot table can be built with a list of pools (via `#withPool`) applied in the order they are specified along with functions (via `#apply`) to modify the resulting items of those pools.
+战利品表是基本对象,可以使用 `LootTable#lootTable` 转换为所需的 `LootTable$Builder`。战利品表可以通过指定的方式构建,包括一系列池(通过 `#withPool` 应用)以及函数(通过 `#apply`),用于修改这些池的结果物品。
### LootPool
-Loot pools represents a group to perform operations and can generate a `LootPool$Builder` using `LootPool#lootPool`. Each loot pool can specify the entries (via `#add`) which define the operations in the pool, the conditions (via `#when`) which define if the operations in the pool should be performed, and functions (via `#apply`) to modify the resulting items of the entries. Each pool can be executed as many times as specified (via `#setRolls`). Additionally, bonus executions can be specified (via `#setBonusRolls`) which is modified by the luck of the executor.
+战利品池代表一个执行操作的组,并可以使用 `LootPool#lootPool` 生成一个 `LootPool$Builder`。每个战利品池可以指定条目(通过 `#add`),这些条目定义池中的操作,条件(通过 `#when`)定义是否应执行池中的操作,以及函数(通过 `#apply`)修改条目的结果物品。每个池可以执行尽可能多的次数(通过 `#setRolls`)。此外,还可以指定额外的执行次数(通过 `#setBonusRolls`),这受到执行者幸运值的影响。
### LootPoolEntryContainer
-Loot entries define the operations to occur when selected, typically generating items. Each entry has an associated, [registered] `LootPoolEntryType`. They also have their own associated builders which subtype `LootPoolEntryContainer$Builder`. Multiple entries can execute at the same time (via `#append`) or sequentially until one fails (via `#then`). Additionally, entries can default to another entry on failure (via `#otherwise`).
+战利品条目定义了选中时要执行的操作,通常生成物品。每个条目都有一个相关的、[已注册][registered]的 `LootPoolEntryType`。它们还有自己的相关构建器,这些构建器是 `LootPoolEntryContainer$Builder` 的子类型。多个条目可以同时执行(通过 `#append`)或顺序执行,直到一个失败(通过 `#then`)。此外,条目可以在失败时默认为另一个条目(通过 `#otherwise`)。
### LootItemCondition
-Loot conditions define requirements which need to be met for some operation to execute. Each condition has an associated, [registered] `LootItemConditionType`. They also have their own associated builders which subtype `LootItemCondition$Builder`. By default, all loot conditions specified must return true for an operation to execute. Loot conditions can also be specified such that only one must return true instead (via `#or`). Additionally, the resulting output of a condition can be inverted (via `#invert`).
+战利品条件定义了执行某些操作所需满足的要求。每个条件都有一个相关的、[已注册][registered]的 `LootItemConditionType`。它们还有自己的相关构建器,这些构建器是 `LootItemCondition$Builder` 的子类型。默认情况下,指定的所有战利品条件必须为真,才能执行操作。也可以指定战利品条件,使得只需一个条件为真即可(通过 `#or`)。此外,条件的结果输出可以被反转(通过 `#invert`)。
### LootItemFunction
-Loot functions modify the result of an execution before passing it to the output. Each function has an associated, [registered] `LootItemFunctionType`. They also have their own associated builders which subtype `LootItemFunction$Builder`.
+战利品函数在将执行结果传递给输出之前修改结果。每个函数都有一个相关的、[已注册][registered]的 `LootItemFunctionType`。它们还有自己的相关构建器,这些构建器是 `LootItemFunction$Builder` 的子类型。
#### NbtProvider
-NBT providers are a special type of functions defined by `CopyNbtFunction`. They define where to pull tag information from. Each provider has an associated, [registered] `LootNbtProviderType`.
+NBT 提供者是由 `CopyNbtFunction` 定义的特殊类型函数。它们定义了从哪里拉取标签信息。每个提供者都有一个相关的、[已注册][registered]的 `LootNbtProviderType`。
### NumberProvider
-Number providers determine how many times a loot pool executes. Each provider has an associated, [registered] `LootNumberProviderType`.
+数字提供者决定战利品池执行的次数。每个提供者都有一个相关的、[已注册][registered]的 `LootNumberProviderType`。
#### ScoreboardNameProvider
-Scoreboard providers are a special type of number providers defined by `ScoreboardValue`. They define the name of the scoreboard to pull the number of rolls to execute from. Each provider has an associated, [registered] `LootScoreProviderType`.
+记分板提供者是由 `ScoreboardValue` 定义的一种特殊类型的数字提供者。它们定义了从哪个记分板拉取执行次数的名字。每个提供者都有一个关联的[已注册][registered]`LootScoreProviderType`。
[loottable]: ../../resources/server/loottables.md
[datagen]: ../index.md#data-providers
From a53dce72927f6bb1068bf53155fd84838af0055e Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 15:47:34 +0800
Subject: [PATCH 33/87] Update tags.md
---
docs/datagen/tags.md | 102 +++++++++++++++++++++----------------------
1 file changed, 51 insertions(+), 51 deletions(-)
diff --git a/docs/datagen/tags.md b/docs/datagen/tags.md
index f07ca2c9a..f0a8287ab 100644
--- a/docs/datagen/tags.md
+++ b/docs/datagen/tags.md
@@ -1,16 +1,16 @@
-Tag Generation
+标签生成
==============
-[Tags] can be generated for a mod by subclassing `TagsProvider` and implementing `#addTags`. After implementation, the provider must be [added][datagen] to the `DataGenerator`.
+通过子类化 `TagsProvider` 并实现 `#addTags` 方法,可以为一个模组生成[标签]。在实现之后,必须将提供者[添加][datagen]到 `DataGenerator` 中。
```java
-// On the MOD event bus
+// 在 MOD 事件总线上
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
- // Tell generator to run only when server data are generating
+ // 仅在生成服务器数据时运行生成器
event.includeServer(),
- // Extends net.neoforged.neoforge.common.data.BlockTagsProvider
+ // 扩展 net.neoforged.neoforge.common.data.BlockTagsProvider
output -> new MyBlockTagsProvider(
output,
event.getLookupProvider(),
@@ -24,75 +24,75 @@ public void gatherData(GatherDataEvent event) {
`TagsProvider`
--------------
-The tags provider has two methods used for generating tags: creating a tag with objects and other tags via `#tag`, or using tags from other object types to generate the tag data via `#getOrCreateRawBuilder`.
+标签提供者有两种用于生成标签的方法:通过 `#tag` 创建带有对象和其他标签的标签,或者使用其他对象类型的标签生成标签数据通过 `#getOrCreateRawBuilder`。
:::note
-Typically, a provider will not call `#getOrCreateRawBuilder` directly unless a registry contains a representation of objects from a different registry (blocks have item representations to obtain the blocks in the inventory).
+通常,提供者不会直接调用 `#getOrCreateRawBuilder`,除非注册表包含来自不同注册表的对象的表示(方块有物品表示以获取存储在库存中的方块)。
:::
-When `#tag` is called, a `TagAppender` is created which acts as a chainable consumer of elements to add to the tag:
+当调用 `#tag` 时,将创建一个 `TagAppender`,它作为一种可链接的元素消费者添加到标签中:
-Method | Description
-:---: | :---
-`add` | Adds an object to a tag through its resource key.
-`addOptional` | Adds an object to a tag through its name. If the object is not present, then the object will be skipped when loading.
-`addTag` | Adds a tag to a tag through its tag key. All elements within the inner tag are now a part of the outer tag.
-`addOptionalTag` | Adds a tag to a tag through its name. If the tag is not present, then the tag will be skipped when loading.
-`replace` | When `true`, all previously loaded entries added to this tag from other datapacks will be discarded. If a datapack is loaded after this one, then it will still append the entries to the tag.
-`remove` | Removes an object or tag from a tag through its name or key.
+方法 | 描述
+:---: | :---
+`add` | 通过其资源键将对象添加到标签中。
+`addOptional` | 通过其名称将对象添加到标签中。如果对象不存在,则在加载时将跳过该对象。
+`addTag` | 通过其标签键将标签添加到标签中。内部标签中的所有元素现在都是外部标签的一部分。
+`addOptionalTag` | 通过其名称将标签添加到标签中。如果标签不存在,则在加载时将跳过该标签。
+`replace` | 当为 `true` 时,将丢弃从其他数据包添加到此标签中的所有先前加载的条目。如果在加载此数据包之后加载了一个数据包,则仍将将条目附加到标签。
+`remove` | 通过其名称或键从标签中删除对象或标签。
```java
-// In some TagProvider#addTags
+// 在某些 TagProvider#addTags 中
this.tag(EXAMPLE_TAG)
- .add(EXAMPLE_OBJECT) // Adds an object to the tag
- .addOptional(new ResourceLocation("othermod", "other_object")) // Adds an object from another mod to the tag
+ .add(EXAMPLE_OBJECT) // 向标签中添加对象
+ .addOptional(new ResourceLocation("othermod", "other_object")) // 向标签中添加来自其他模组的对象
this.tag(EXAMPLE_TAG_2)
- .addTag(EXAMPLE_TAG) // Adds a tag to the tag
- .remove(EXAMPLE_OBJECT) // Removes an object from this tag
+ .addTag(EXAMPLE_TAG) // 向标签中添加标签
+ .remove(EXAMPLE_OBJECT) // 从此标签中移除对象
```
:::important
-If the mod's tags softly depends on another mod's tags (the other mod may or may not be present at runtime), the other mods' tags should be referenced using the optional methods.
+如果模组的标签在某些情况下依赖于其他模组的标签(其他模组可能在运行时存在或不存在),则应使用可选的方法引用其他模组的标签。
:::
-### Existing Providers
+### 现有提供者
-Minecraft contains a few tag providers for certain registries that can be subclassed instead. Additionally, some providers contain additional helper methods to more easily create tags.
+Minecraft 包含一些特定注册表的标签提供者,可以进行子类化。此外,一些提供者包含附加的辅助方法,以更轻松地创建标签。
-Registry Object Type | Tag Provider
-:---: | :---
-`Block` | `BlockTagsProvider`\*
-`Item` | `ItemTagsProvider`
-`EntityType` | `EntityTypeTagsProvider`
-`Fluid` | `FluidTagsProvider`
-`GameEvent` | `GameEventTagsProvider`
-`Biome` | `BiomeTagsProvider`
+注册表对象类型 | 标签提供者
+:---: | :---
+`Block` | `BlockTagsProvider`\*
+`Item` | `ItemTagsProvider`
+`EntityType` | `EntityTypeTagsProvider`
+`Fluid` | `FluidTagsProvider`
+`GameEvent` | `GameEventTagsProvider`
+`Biome` | `BiomeTagsProvider`
`FlatLevelGeneratorPreset` | `FlatLevelGeneratorPresetTagsProvider`
-`WorldPreset` | `WorldPresetTagsProvider`
-`Structure` | `StructureTagsProvider`
-`PoiType` | `PoiTypeTagsProvider`
-`BannerPattern` | `BannerPatternTagsProvider`
-`CatVariant` | `CatVariantTagsProvider`
-`PaintingVariant` | `PaintingVariantTagsProvider`
-`Instrument` | `InstrumentTagsProvider`
-`DamageType` | `DamageTypeTagsProvider`
+`WorldPreset` | `WorldPresetTagsProvider`
+`Structure` | `StructureTagsProvider`
+`PoiType` | `PoiTypeTagsProvider`
+`BannerPattern` | `BannerPatternTagsProvider`
+`CatVariant` | `CatVariantTagsProvider`
+`PaintingVariant` | `PaintingVariantTagsProvider`
+`Instrument` | `InstrumentTagsProvider`
+`DamageType` | `DamageTypeTagsProvider`
-\* `BlockTagsProvider` is a Forge added `TagsProvider`.
+\* `BlockTagsProvider` 是 Forge 添加的 `TagsProvider`。
#### `ItemTagsProvider#copy`
-Blocks have item representations to obtain them in the inventory. As such, many of the block tags can also be an item tag. To easily generate item tags to have the same entries as block tags, the `#copy` method can be used which takes in the block tag to copy from and the item tag to copy to.
+方块具有物品表示以在库存中获取它们。因此,许多方块标签也可以是物品标签。为了轻松生成具有与方块标签相同条目的物品标签,可以使用 `#copy` 方法,该方法接受要从中复制的方块标签和要复制到的物品标签。
```java
-//In ItemTagsProvider#addTags
+// 在 ItemTagsProvider#addTags 中
this.copy(EXAMPLE_BLOCK_TAG, EXAMPLE_ITEM_TAG);
```
-Custom Tag Providers
+自定义标签提供者
--------------------
-A custom tag provider can be created via a `TagsProvider` subclass which takes in the registry key to generate tags for.
+可以通过一个接受注册表键以生成标签的 `TagsProvider` 子类来创建自定义标签提供者。
```java
public RecipeTypeTagsProvider(PackOutput output, CompletableFuture registries, ExistingFileHelper fileHelper) {
@@ -100,12 +100,12 @@ public RecipeTypeTagsProvider(PackOutput output, CompletableFuture registries, ExistingFileHelper fileHelper) {
super(
output,
@@ -118,6 +118,6 @@ public AttributeTagsProvider(PackOutput output, CompletableFuture
Date: Thu, 25 Apr 2024 15:48:04 +0800
Subject: [PATCH 34/87] Update tags.md
---
docs/datagen/tags.md | 102 +++++++++++++++++++++----------------------
1 file changed, 51 insertions(+), 51 deletions(-)
diff --git a/docs/datagen/tags.md b/docs/datagen/tags.md
index f0a8287ab..f07ca2c9a 100644
--- a/docs/datagen/tags.md
+++ b/docs/datagen/tags.md
@@ -1,16 +1,16 @@
-标签生成
+Tag Generation
==============
-通过子类化 `TagsProvider` 并实现 `#addTags` 方法,可以为一个模组生成[标签]。在实现之后,必须将提供者[添加][datagen]到 `DataGenerator` 中。
+[Tags] can be generated for a mod by subclassing `TagsProvider` and implementing `#addTags`. After implementation, the provider must be [added][datagen] to the `DataGenerator`.
```java
-// 在 MOD 事件总线上
+// On the MOD event bus
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
- // 仅在生成服务器数据时运行生成器
+ // Tell generator to run only when server data are generating
event.includeServer(),
- // 扩展 net.neoforged.neoforge.common.data.BlockTagsProvider
+ // Extends net.neoforged.neoforge.common.data.BlockTagsProvider
output -> new MyBlockTagsProvider(
output,
event.getLookupProvider(),
@@ -24,75 +24,75 @@ public void gatherData(GatherDataEvent event) {
`TagsProvider`
--------------
-标签提供者有两种用于生成标签的方法:通过 `#tag` 创建带有对象和其他标签的标签,或者使用其他对象类型的标签生成标签数据通过 `#getOrCreateRawBuilder`。
+The tags provider has two methods used for generating tags: creating a tag with objects and other tags via `#tag`, or using tags from other object types to generate the tag data via `#getOrCreateRawBuilder`.
:::note
-通常,提供者不会直接调用 `#getOrCreateRawBuilder`,除非注册表包含来自不同注册表的对象的表示(方块有物品表示以获取存储在库存中的方块)。
+Typically, a provider will not call `#getOrCreateRawBuilder` directly unless a registry contains a representation of objects from a different registry (blocks have item representations to obtain the blocks in the inventory).
:::
-当调用 `#tag` 时,将创建一个 `TagAppender`,它作为一种可链接的元素消费者添加到标签中:
+When `#tag` is called, a `TagAppender` is created which acts as a chainable consumer of elements to add to the tag:
-方法 | 描述
-:---: | :---
-`add` | 通过其资源键将对象添加到标签中。
-`addOptional` | 通过其名称将对象添加到标签中。如果对象不存在,则在加载时将跳过该对象。
-`addTag` | 通过其标签键将标签添加到标签中。内部标签中的所有元素现在都是外部标签的一部分。
-`addOptionalTag` | 通过其名称将标签添加到标签中。如果标签不存在,则在加载时将跳过该标签。
-`replace` | 当为 `true` 时,将丢弃从其他数据包添加到此标签中的所有先前加载的条目。如果在加载此数据包之后加载了一个数据包,则仍将将条目附加到标签。
-`remove` | 通过其名称或键从标签中删除对象或标签。
+Method | Description
+:---: | :---
+`add` | Adds an object to a tag through its resource key.
+`addOptional` | Adds an object to a tag through its name. If the object is not present, then the object will be skipped when loading.
+`addTag` | Adds a tag to a tag through its tag key. All elements within the inner tag are now a part of the outer tag.
+`addOptionalTag` | Adds a tag to a tag through its name. If the tag is not present, then the tag will be skipped when loading.
+`replace` | When `true`, all previously loaded entries added to this tag from other datapacks will be discarded. If a datapack is loaded after this one, then it will still append the entries to the tag.
+`remove` | Removes an object or tag from a tag through its name or key.
```java
-// 在某些 TagProvider#addTags 中
+// In some TagProvider#addTags
this.tag(EXAMPLE_TAG)
- .add(EXAMPLE_OBJECT) // 向标签中添加对象
- .addOptional(new ResourceLocation("othermod", "other_object")) // 向标签中添加来自其他模组的对象
+ .add(EXAMPLE_OBJECT) // Adds an object to the tag
+ .addOptional(new ResourceLocation("othermod", "other_object")) // Adds an object from another mod to the tag
this.tag(EXAMPLE_TAG_2)
- .addTag(EXAMPLE_TAG) // 向标签中添加标签
- .remove(EXAMPLE_OBJECT) // 从此标签中移除对象
+ .addTag(EXAMPLE_TAG) // Adds a tag to the tag
+ .remove(EXAMPLE_OBJECT) // Removes an object from this tag
```
:::important
-如果模组的标签在某些情况下依赖于其他模组的标签(其他模组可能在运行时存在或不存在),则应使用可选的方法引用其他模组的标签。
+If the mod's tags softly depends on another mod's tags (the other mod may or may not be present at runtime), the other mods' tags should be referenced using the optional methods.
:::
-### 现有提供者
+### Existing Providers
-Minecraft 包含一些特定注册表的标签提供者,可以进行子类化。此外,一些提供者包含附加的辅助方法,以更轻松地创建标签。
+Minecraft contains a few tag providers for certain registries that can be subclassed instead. Additionally, some providers contain additional helper methods to more easily create tags.
-注册表对象类型 | 标签提供者
-:---: | :---
-`Block` | `BlockTagsProvider`\*
-`Item` | `ItemTagsProvider`
-`EntityType` | `EntityTypeTagsProvider`
-`Fluid` | `FluidTagsProvider`
-`GameEvent` | `GameEventTagsProvider`
-`Biome` | `BiomeTagsProvider`
+Registry Object Type | Tag Provider
+:---: | :---
+`Block` | `BlockTagsProvider`\*
+`Item` | `ItemTagsProvider`
+`EntityType` | `EntityTypeTagsProvider`
+`Fluid` | `FluidTagsProvider`
+`GameEvent` | `GameEventTagsProvider`
+`Biome` | `BiomeTagsProvider`
`FlatLevelGeneratorPreset` | `FlatLevelGeneratorPresetTagsProvider`
-`WorldPreset` | `WorldPresetTagsProvider`
-`Structure` | `StructureTagsProvider`
-`PoiType` | `PoiTypeTagsProvider`
-`BannerPattern` | `BannerPatternTagsProvider`
-`CatVariant` | `CatVariantTagsProvider`
-`PaintingVariant` | `PaintingVariantTagsProvider`
-`Instrument` | `InstrumentTagsProvider`
-`DamageType` | `DamageTypeTagsProvider`
+`WorldPreset` | `WorldPresetTagsProvider`
+`Structure` | `StructureTagsProvider`
+`PoiType` | `PoiTypeTagsProvider`
+`BannerPattern` | `BannerPatternTagsProvider`
+`CatVariant` | `CatVariantTagsProvider`
+`PaintingVariant` | `PaintingVariantTagsProvider`
+`Instrument` | `InstrumentTagsProvider`
+`DamageType` | `DamageTypeTagsProvider`
-\* `BlockTagsProvider` 是 Forge 添加的 `TagsProvider`。
+\* `BlockTagsProvider` is a Forge added `TagsProvider`.
#### `ItemTagsProvider#copy`
-方块具有物品表示以在库存中获取它们。因此,许多方块标签也可以是物品标签。为了轻松生成具有与方块标签相同条目的物品标签,可以使用 `#copy` 方法,该方法接受要从中复制的方块标签和要复制到的物品标签。
+Blocks have item representations to obtain them in the inventory. As such, many of the block tags can also be an item tag. To easily generate item tags to have the same entries as block tags, the `#copy` method can be used which takes in the block tag to copy from and the item tag to copy to.
```java
-// 在 ItemTagsProvider#addTags 中
+//In ItemTagsProvider#addTags
this.copy(EXAMPLE_BLOCK_TAG, EXAMPLE_ITEM_TAG);
```
-自定义标签提供者
+Custom Tag Providers
--------------------
-可以通过一个接受注册表键以生成标签的 `TagsProvider` 子类来创建自定义标签提供者。
+A custom tag provider can be created via a `TagsProvider` subclass which takes in the registry key to generate tags for.
```java
public RecipeTypeTagsProvider(PackOutput output, CompletableFuture registries, ExistingFileHelper fileHelper) {
@@ -100,12 +100,12 @@ public RecipeTypeTagsProvider(PackOutput output, CompletableFuture registries, ExistingFileHelper fileHelper) {
super(
output,
@@ -118,6 +118,6 @@ public AttributeTagsProvider(PackOutput output, CompletableFuture
Date: Thu, 25 Apr 2024 16:05:36 +0800
Subject: [PATCH 35/87] Update tags.md
---
docs/datagen/tags.md | 100 +++++++++++++++++++++----------------------
1 file changed, 50 insertions(+), 50 deletions(-)
diff --git a/docs/datagen/tags.md b/docs/datagen/tags.md
index f07ca2c9a..d72c35a66 100644
--- a/docs/datagen/tags.md
+++ b/docs/datagen/tags.md
@@ -1,16 +1,16 @@
-Tag Generation
-==============
+标签生成
+======
-[Tags] can be generated for a mod by subclassing `TagsProvider` and implementing `#addTags`. After implementation, the provider must be [added][datagen] to the `DataGenerator`.
+通过继承`TagsProvider`并实现`#addTags`方法,可以为一个mod生成[标签]。实现后,必须将提供器[添加][datagen]到`DataGenerator`中。
```java
-// On the MOD event bus
+// 在MOD事件总线上
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
- // Tell generator to run only when server data are generating
+ // 通知生成器仅在生成服务器数据时运行
event.includeServer(),
- // Extends net.neoforged.neoforge.common.data.BlockTagsProvider
+ // 继承自net.neoforged.neoforge.common.data.BlockTagsProvider
output -> new MyBlockTagsProvider(
output,
event.getLookupProvider(),
@@ -24,75 +24,75 @@ public void gatherData(GatherDataEvent event) {
`TagsProvider`
--------------
-The tags provider has two methods used for generating tags: creating a tag with objects and other tags via `#tag`, or using tags from other object types to generate the tag data via `#getOrCreateRawBuilder`.
+标签提供器有两种用于生成标签的方法:通过`#tag`使用对象和其他标签创建一个标签,或者通过`#getOrCreateRawBuilder`使用其他对象类型的标签来生成标签数据。
:::note
-Typically, a provider will not call `#getOrCreateRawBuilder` directly unless a registry contains a representation of objects from a different registry (blocks have item representations to obtain the blocks in the inventory).
+通常,除非一个注册表包含来自不同注册表的对象的表示(例如,方块有项目表示以在库存中获得方块),否则提供器不会直接调用`#getOrCreateRawBuilder`。
:::
-When `#tag` is called, a `TagAppender` is created which acts as a chainable consumer of elements to add to the tag:
+调用`#tag`时,会创建一个`TagAppender`,它作为链式消费者,用于向标签添加元素:
-Method | Description
-:---: | :---
-`add` | Adds an object to a tag through its resource key.
-`addOptional` | Adds an object to a tag through its name. If the object is not present, then the object will be skipped when loading.
-`addTag` | Adds a tag to a tag through its tag key. All elements within the inner tag are now a part of the outer tag.
-`addOptionalTag` | Adds a tag to a tag through its name. If the tag is not present, then the tag will be skipped when loading.
-`replace` | When `true`, all previously loaded entries added to this tag from other datapacks will be discarded. If a datapack is loaded after this one, then it will still append the entries to the tag.
-`remove` | Removes an object or tag from a tag through its name or key.
+方法 | 描述
+:---: | :---
+`add` | 通过其资源键将一个对象添加到标签中。
+`addOptional` | 通过其名称将一个对象添加到标签中。如果对象不存在,则加载时将跳过该对象。
+`addTag` | 通过其标签键将一个标签添加到标签中。内标签中的所有元素现在都是外标签的一部分。
+`addOptionalTag` | 通过其名称将一个标签添加到标签中。如果标签不存在,则加载时将跳过该标签。
+`replace` | 当为`true`时,此标签从其他数据包添加的所有先前加载的条目将被丢弃。如果在此之后加载了一个数据包,那么它仍然会将条目追加到标签中。
+`remove` | 通过其名称或键从标签中移除一个对象或标签。
```java
-// In some TagProvider#addTags
+// 在某个TagProvider#addTags中
this.tag(EXAMPLE_TAG)
- .add(EXAMPLE_OBJECT) // Adds an object to the tag
- .addOptional(new ResourceLocation("othermod", "other_object")) // Adds an object from another mod to the tag
+ .add(EXAMPLE_OBJECT) // 将一个对象添加到标签中
+ .addOptional(new ResourceLocation("othermod", "other_object")) // 向标签添加来自其他mod的对象
this.tag(EXAMPLE_TAG_2)
- .addTag(EXAMPLE_TAG) // Adds a tag to the tag
- .remove(EXAMPLE_OBJECT) // Removes an object from this tag
+ .addTag(EXAMPLE_TAG) // 将一个标签添加到另一个标签
+ .remove(EXAMPLE_OBJECT) // 从此标签中移除一个对象
```
:::important
-If the mod's tags softly depends on another mod's tags (the other mod may or may not be present at runtime), the other mods' tags should be referenced using the optional methods.
+如果你的mod的标签对其他mod的标签有软依赖(也就是说,其他mod可能在运行时不存在),那么你应该使用可选的方法来引用其他mod的标签。
:::
-### Existing Providers
+### 现有的供应商
-Minecraft contains a few tag providers for certain registries that can be subclassed instead. Additionally, some providers contain additional helper methods to more easily create tags.
+Minecraft中包含了一些可以被子类化的特定注册表的标签供应商。另外,一些供应商包含了额外的辅助方法,可以更容易地创建标签。
-Registry Object Type | Tag Provider
+注册对象类型 | 标签供应商
:---: | :---
-`Block` | `BlockTagsProvider`\*
-`Item` | `ItemTagsProvider`
-`EntityType` | `EntityTypeTagsProvider`
-`Fluid` | `FluidTagsProvider`
-`GameEvent` | `GameEventTagsProvider`
-`Biome` | `BiomeTagsProvider`
-`FlatLevelGeneratorPreset` | `FlatLevelGeneratorPresetTagsProvider`
-`WorldPreset` | `WorldPresetTagsProvider`
-`Structure` | `StructureTagsProvider`
-`PoiType` | `PoiTypeTagsProvider`
-`BannerPattern` | `BannerPatternTagsProvider`
-`CatVariant` | `CatVariantTagsProvider`
-`PaintingVariant` | `PaintingVariantTagsProvider`
-`Instrument` | `InstrumentTagsProvider`
-`DamageType` | `DamageTypeTagsProvider`
-
-\* `BlockTagsProvider` is a Forge added `TagsProvider`.
+`方块` | `BlockTagsProvider`\*
+`物品` | `ItemTagsProvider`
+`实体类型` | `EntityTypeTagsProvider`
+`流体` | `FluidTagsProvider`
+`游戏事件` | `GameEventTagsProvider`
+`生物群系` | `BiomeTagsProvider`
+`平面世界生成预设` | `FlatLevelGeneratorPresetTagsProvider`
+`世界预设` | `WorldPresetTagsProvider`
+`结构` | `StructureTagsProvider`
+`兴趣点类型` | `PoiTypeTagsProvider`
+`旗帜图案` | `BannerPatternTagsProvider`
+`猫的品种` | `CatVariantTagsProvider`
+`画的种类` | `PaintingVariantTagsProvider`
+`乐器` | `InstrumentTagsProvider`
+`伤害类型` | `DamageTypeTagsProvider`
+
+\* `BlockTagsProvider` 是Forge所添加的 `TagsProvider`。
#### `ItemTagsProvider#copy`
-Blocks have item representations to obtain them in the inventory. As such, many of the block tags can also be an item tag. To easily generate item tags to have the same entries as block tags, the `#copy` method can be used which takes in the block tag to copy from and the item tag to copy to.
+方块在物品栏中有物品形式的表示。因此,许多的方块标签也可以是物品标签。为了方便地生成与方块标签具有相同条目的物品标签,可以使用 `#copy` 方法,此方法接收要复制的方块标签和要复制到的物品标签。
```java
-//In ItemTagsProvider#addTags
+// 在 ItemTagsProvider#addTags 中
this.copy(EXAMPLE_BLOCK_TAG, EXAMPLE_ITEM_TAG);
```
-Custom Tag Providers
+自定义标签提供者
--------------------
-A custom tag provider can be created via a `TagsProvider` subclass which takes in the registry key to generate tags for.
+通过 `TagsProvider` 的子类,可以创建自定义的标签提供者,这需要传入注册键以生成标签。
```java
public RecipeTypeTagsProvider(PackOutput output, CompletableFuture registries, ExistingFileHelper fileHelper) {
@@ -100,12 +100,12 @@ public RecipeTypeTagsProvider(PackOutput output, CompletableFuture registries, ExistingFileHelper fileHelper) {
super(
output,
From d2cefb41ae6d9ac9e36be2159d616ed37c20b27f Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 16:17:06 +0800
Subject: [PATCH 36/87] Update recipes.md
---
docs/datagen/recipes.md | 140 ++++++++++++++++++++--------------------
1 file changed, 69 insertions(+), 71 deletions(-)
diff --git a/docs/datagen/recipes.md b/docs/datagen/recipes.md
index e4246eee6..0abd31642 100644
--- a/docs/datagen/recipes.md
+++ b/docs/datagen/recipes.md
@@ -1,16 +1,16 @@
-Recipe Generation
+配方生成
=================
-Recipes can be generated for a mod by subclassing `RecipeProvider` and implementing `#buildRecipes`. A recipe is supplied for data generation once a `FinishedRecipe` view is accepted by the consumer. `FinishedRecipe`s can either be created and supplied manually or, for convenience, created using a `RecipeBuilder`.
+可以通过继承 `RecipeProvider` 并实现 `#buildRecipes` 来为模组生成配方。一旦消费者接受了 `FinishedRecipe` 视图,就会为数据生成提供配方。 `FinishedRecipe` 可以手动创建和提供,或者为方便起见,使用 `RecipeBuilder` 创建。
-After implementation, the provider must be [added][datagen] to the `DataGenerator`.
+实现后,必须将提供者[添加][datagen]到 `DataGenerator`。
```java
-// On the MOD event bus
+// 在MOD事件总线上
@SubscribeEvent
public void gatherData(GatherDataEvent event) {
event.getGenerator().addProvider(
- // Tell generator to run only when server data are generating
+ // 告诉生成器只在服务器数据生成时运行
event.includeServer(),
MyRecipeProvider::new
);
@@ -20,157 +20,155 @@ public void gatherData(GatherDataEvent event) {
`RecipeBuilder`
---------------
-`RecipeBuilder` is a convenience implementation for creating `FinishedRecipe`s to generate. It provides basic definitions for unlocking, grouping, saving, and getting the result of a recipe. This is done through `#unlockedBy`, `#group`, `#save`, and `#getResult` respectively.
+`RecipeBuilder` 是创建 `FinishedRecipe` 以便于生成的便利实现。它提供了解锁、分组、保存和获取配方结果的基本定义。分别通过 `#unlockedBy`、 `#group`、 `#save` 和 `#getResult` 实现。
:::important
-[`ItemStack` outputs][stack] in recipes are not supported within vanilla recipe builders. A `FinishedRecipe` must be built in a different manner for existing vanilla recipe serializers to generate this data.
+在原生配方构建器中不支持配方的 [`ItemStack` 输出][stack]。必须以不同的方式构建 `FinishedRecipe`,以便现有的原生配方序列化器可以生成这些数据。
:::
:::warning
-The item results being generated must have a valid `RecipeCategory` specified; otherwise, a `NullPointerException` will be thrown.
+正在生成的物品结果必须有一个有效的 `RecipeCategory` 指定,否则会抛出 `NullPointerException`。
:::
-All recipe builders except for [`SpecialRecipeBuilder`] require an advancement criteria to be specified. All recipes generate a criteria unlocking the recipe if the player has used the recipe previously. However, an additional criteria must be specified that allows the player to obtain the recipe without any prior knowledge. If any of the criteria specified is true, then the played will obtain the recipe for the recipe book.
+除了 [`SpecialRecipeBuilder`],所有的配方构建器都需要指定一个进步条件。所有的配方都会生成一个条件,如果玩家之前使用过这个配方,就会解锁这个配方。然而,必须指定一个额外的条件,允许玩家在没有任何先验知识的情况下获取到配方。如果指定的任何一个条件为真,那么玩家就会在配方书中获取到配方。
:::tip
-Recipe criteria commonly use `InventoryChangeTrigger` to unlock their recipe when certain items are present in the user's inventory.
+配方条件通常使用 `InventoryChangeTrigger` 来在用户的库存中存在某些物品时解锁配方。
:::
### ShapedRecipeBuilder
-`ShapedRecipeBuilder` is used to generate shaped recipes. The builder can be initialized via `#shaped`. The recipe group, input symbol pattern, symbol definition of ingredients, and the recipe unlock criteria can be specified before saving.
+`ShapedRecipeBuilder` 用于生成有形状的配方。构建器可以通过 `#shaped` 初始化。可以在保存之前指定配方组、输入符号模式、成分的符号定义和配方解锁条件。
```java
-// In RecipeProvider#buildRecipes(writer)
+// 在 RecipeProvider#buildRecipes(writer) 中
ShapedRecipeBuilder builder = ShapedRecipeBuilder.shaped(RecipeCategory.MISC, result)
- .pattern("a a") // Create recipe pattern
- .define('a', item) // Define what the symbol represents
- .unlockedBy("criteria", criteria) // How the recipe is unlocked
- .save(writer); // Add data to builder
+ .pattern("a a") // 创建配方模式
+ .define('a', item) // 定义符号代表的物品
+ .unlockedBy("criteria", criteria) // 配方的解锁方式
+ .save(writer); // 将数据添加到构建器中
```
-#### Additional Validation Checks
+#### 额外的验证检查
-Shaped recipes have some additional validation checks performed before building:
+在构建之前,有形状的配方会进行一些额外的验证检查:
-* A pattern must be defined and take in more than one item.
-* All pattern rows must be the same width.
-* A symbol cannot be defined more than once.
-* The space character (`' '`) is reserved for representing no item in a slot and, as such, cannot be defined.
-* A pattern must use all symbols defined by the user.
+* 必须定义一个模式,并且需要输入超过一个物品。
+* 所有模式行的宽度必须相同。
+* 一个符号不能被定义多次。
+* 空格字符 (`' '`) 是为了表示插槽中没有物品而保留的,因此不能被定义。
+* 模式必须使用用户定义的所有符号。
### ShapelessRecipeBuilder
-`ShapelessRecipeBuilder` is used to generate shapeless recipes. The builder can be initialized via `#shapeless`. The recipe group, input ingredients, and the recipe unlock criteria can be specified before saving.
+`ShapelessRecipeBuilder` 用于生成无形状的配方。可以通过 `#shapeless` 初始化构建器。在保存之前,可以指定配方组、输入成分和配方解锁条件。
```java
-// In RecipeProvider#buildRecipes(writer)
+// 在 RecipeProvider#buildRecipes(writer) 中
ShapelessRecipeBuilder builder = ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, result)
- .requires(item) // Add item to the recipe
- .unlockedBy("criteria", criteria) // How the recipe is unlocked
- .save(writer); // Add data to builder
+ .requires(item) // 将物品添加到配方中
+ .unlockedBy("criteria", criteria) // 配方的解锁方式
+ .save(writer); // 将数据添加到构建器中
```
### SimpleCookingRecipeBuilder
-`SimpleCookingRecipeBuilder` is used to generate smelting, blasting, smoking, and campfire cooking recipes. Additionally, custom cooking recipes using the `SimpleCookingSerializer` can also be data generated using this builder. The builder can be initialized via `#smelting`, `#blasting`, `#smoking`, `#campfireCooking`, or `#cooking` respectively. The recipe group and the recipe unlock criteria can be specified before saving.
+`SimpleCookingRecipeBuilder` 用于生成熔炼、爆炸、烟熏和营火烹饪配方。此外,使用 `SimpleCookingSerializer` 的自定义烹饪配方也可以使用这个构建器进行数据生成。可以分别通过 `#smelting`、 `#blasting`、 `#smoking`、 `#campfireCooking` 或 `#cooking` 初始化构建器。在保存之前,可以指定配方组和配方解锁条件。
```java
-// In RecipeProvider#buildRecipes(writer)
+// 在 RecipeProvider#buildRecipes(writer) 中
SimpleCookingRecipeBuilder builder = SimpleCookingRecipeBuilder.smelting(input, RecipeCategory.MISC, result, experience, cookingTime)
- .unlockedBy("criteria", criteria) // How the recipe is unlocked
- .save(writer); // Add data to builder
+ .unlockedBy("criteria", criteria) // 配方的解锁方式
+ .save(writer); // 将数据添加到构建器中
```
### SingleItemRecipeBuilder
-`SingleItemRecipeBuilder` is used to generate stonecutting recipes. Additionally, custom single item recipes using a serializer like `SingleItemRecipe$Serializer` can also be data generated using this builder. The builder can be initialized via `#stonecutting` or through the constructor respectively. The recipe group and the recipe unlock criteria can be specified before saving.
+`SingleItemRecipeBuilder` 用于生成石切配方。此外,使用类似 `SingleItemRecipe$Serializer` 的序列化器的自定义单物品配方也可以使用这个构建器进行数据生成。可以通过 `#stonecutting` 或者构造函数分别初始化构建器。在保存之前,可以指定配方组和配方解锁条件。
```java
-// In RecipeProvider#buildRecipes(writer)
+// 在 RecipeProvider#buildRecipes(writer) 中
SingleItemRecipeBuilder builder = SingleItemRecipeBuilder.stonecutting(input, RecipeCategory.MISC, result)
- .unlockedBy("criteria", criteria) // How the recipe is unlocked
- .save(writer); // Add data to builder
+ .unlockedBy("criteria", criteria) // 配方的解锁方式
+ .save(writer); // 将数据添加到构建器中
```
-Non-`RecipeBuilder` Builders
+非 `RecipeBuilder` 构建器
----------------------------
-Some recipe builders do not implement `RecipeBuilder` due to lacking features used by all previously mentioned recipes.
+一些配方构建器由于缺少所有先前提到的配方使用的功能而不实现 `RecipeBuilder`。
### SmithingTransformRecipeBuilder
-`SmithingTransformRecipeBuilder` is used to generate smithing recipes which transform an item. Additionally, custom recipes using a serializer like `SmithingTransformRecipe$Serializer` can also be data generated using this builder. The builder can be initialized via `#smithing` or through the constructor respectively. The recipe unlock criteria can be specified before saving.
+`SmithingTransformRecipeBuilder` 用于生成将物品转化的铁匠配方。此外,使用类似 `SmithingTransformRecipe$Serializer` 的序列化器的自定义配方也可以使用这个构建器进行数据生成。可以通过 `#smithing` 或者构造函数分别初始化构建器。在保存之前,可以指定配方解锁条件。
```java
-// In RecipeProvider#buildRecipes(writer)
+// 在 RecipeProvider#buildRecipes(writer) 中
SmithingTransformRecipeBuilder builder = SmithingTransformRecipeBuilder.smithing(template, base, addition, RecipeCategory.MISC, result)
- .unlocks("criteria", criteria) // How the recipe is unlocked
- .save(writer, name); // Add data to builder
+ .unlocks("criteria", criteria) // 配方的解锁方式
+ .save(writer, name); // 将数据添加到构建器中
```
### SmithingTrimRecipeBuilder
-`SmithingTrimRecipeBuilder` is used to generate smithing recipes for armor trims. Additionally, custom upgrade recipes using a serializer like `SmithingTrimRecipe$Serializer` can also be data generated using this builder. The builder can be initialized via `#smithingTrim` or through the constructor respectively. The recipe unlock criteria can be specified before saving.
+`SmithingTrimRecipeBuilder` 用于生成用于装甲修剪的铁匠配方。此外,使用类似 `SmithingTrimRecipe$Serializer` 的序列化器的自定义升级配方也可以使用这个构建器进行数据生成。可以通过 `#smithingTrim` 或者构造函数分别初始化构建器。在保存之前,可以指定配方解锁条件。
```java
-// In RecipeProvider#buildRecipes(writer)
+// 在 RecipeProvider#buildRecipes(writer) 中
SmithingTrimRecipe builder = SmithingTrimRecipe.smithingTrim(template, base, addition, RecipeCategory.MISC)
- .unlocks("criteria", criteria) // How the recipe is unlocked
- .save(writer, name); // Add data to builder
+ .unlocks("criteria", criteria) // 配方的解锁方式
+ .save(writer, name); // 将数据添加到构建器中
```
### SpecialRecipeBuilder
-`SpecialRecipeBuilder` is used to generate empty JSONs for dynamic recipes that cannot easily be constrained to the recipe JSON format (dying armor, firework, etc.). The builder can be initialized via `#special`.
+`SpecialRecipeBuilder` 用于为不能轻易约束到配方 JSON 格式(如染色护甲、焰火等)的动态配方生成空的 JSON。可以通过 `#special` 初始化构建器。
```java
-// In RecipeProvider#buildRecipes(writer)
+// 在 RecipeProvider#buildRecipes(writer) 中
SpecialRecipeBuilder.special(dynamicRecipeSerializer)
- .save(writer, name); // Add data to builder
+ .save(writer, name); // 将数据添加到构建器中
```
-
-Conditional Recipes
+条件性配方
-------------------
-[Conditional recipes][conditional] can also be data generated via `ConditionalRecipe$Builder`. The builder can be obtained using `#builder`.
+[条件性配方][conditional] 也可以通过 `ConditionalRecipe$Builder` 进行数据生成。可以使用 `#builder` 获取构建器。
-Conditions for each recipe can be specified by first calling `#addCondition` and then calling `#addRecipe` after all conditions have been specified. This process can be repeated as many times as the programmer would like.
+可以先调用 `#addCondition` 来指定每个配方的条件,然后在所有条件都指定后调用 `#addRecipe`。这个过程可以重复多次,由程序员自行决定。
-After all recipes have been specified, advancements can be added for each recipe at the end using `#generateAdvancement`. Alternatively, the conditional advancement can be set using `#setAdvancement`.
+在所有配方都指定之后,可以在最后使用 `#generateAdvancement` 为每个配方添加进步(advancements)。或者,可以使用 `#setAdvancement` 设置条件性进步。
```java
-// In RecipeProvider#buildRecipes(writer)
+// 在 RecipeProvider#buildRecipes(writer) 中
ConditionalRecipe.builder()
- // Add the conditions for the recipe
+ // 添加配方的条件
.addCondition(...)
- // Add recipe to return when conditions are true
+ // 当条件为真时返回配方
.addRecipe(...)
- // Add the next conditions for the next recipe
+ // 添加下一个配方的条件
.addCondition(...)
- // Add next recipe to return when the next conditions are true
+ // 当下一个条件为真时返回下一个配方
.addRecipe(...)
- // Create conditional advancement which uses the conditions
- // and unlocking advancement in the recipes above
+ // 创建使用上述配方中的条件和解锁进步的条件性进步
.generateAdvancement()
.build(writer, name);
```
### IConditionBuilder
-To simplify adding conditions to conditional recipes without having to construct the instances of each condition instance manually, the extended `RecipeProvider` can implement `IConditionBuilder`. The interface adds methods to easily construct condition instances.
+为了简化向条件性配方添加条件,而不必手动构造每个条件实例,扩展的 `RecipeProvider` 可以实现 `IConditionBuilder`。接口添加了轻松构造条件实例的方法。
```java
-// In ConditionalRecipe$Builder#addCondition
+// 在 ConditionalRecipe$Builder#addCondition 中
(
- // If either 'examplemod:example_item'
- // OR 'examplemod:example_item2' exists
- // AND
- // NOT FALSE
+ // 如果 'examplemod:example_item'
+ // 或者 'examplemod:example_item2' 存在
+ // 并且
+ // 非FALSE
- // Methods are defined by IConditionBuilder
+ // 方法由 IConditionBuilder 定义
and(
or(
itemExists("examplemod", "example_item"),
@@ -183,13 +181,13 @@ To simplify adding conditions to conditional recipes without having to construct
)
```
-Custom Recipe Serializers
+自定义配方序列化器
-------------------------
-Custom recipe serializers can be data generated by creating a builder that can construct a `FinishedRecipe`. The finished recipe encodes the recipe data and its unlocking advancement, when present, to JSON. Additionally, the name and serializer of the recipe is also specified to know where to write to and what can decode the object when loading. Once a `FinishedRecipe` is constructed, it simply needs to be passed to the `Consumer` supplied by `RecipeProvider#buildRecipes`.
+通过创建一个可以构造 `FinishedRecipe` 的构建器,可以数据生成自定义配方序列化器。完成的配方将配方数据编码为JSON,并在存在时将其解锁进步也编码为JSON。此外,还需要指定配方的名称和序列化器,以知道写入位置以及加载时能解码对象的内容。一旦构造了 `FinishedRecipe`,只需将其传递给 `RecipeProvider#buildRecipes` 提供的 `Consumer`。
:::tip
-`FinishedRecipe`s are flexible enough that any object transformation can be data generated, not just items.
+`FinishedRecipe` 足够灵活,可以数据生成任何对象转换,不仅仅是物品。
:::
[datagen]: ../index.md#data-providers
From 05b23718fa27162dcd2ecb247c0b22877448e1e6 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 16:27:04 +0800
Subject: [PATCH 37/87] Update neo_maps.md
---
docs/datamaps/neo_maps.md | 47 +++++++++++++++++++++++++--------------
1 file changed, 30 insertions(+), 17 deletions(-)
diff --git a/docs/datamaps/neo_maps.md b/docs/datamaps/neo_maps.md
index 5a709c22c..988278dab 100644
--- a/docs/datamaps/neo_maps.md
+++ b/docs/datamaps/neo_maps.md
@@ -1,10 +1,13 @@
-# Built-in Data Maps
-NeoForge provides a few data maps that mostly replace hardcoded in-code vanilla maps.
-These data maps can be found in `NeoForgeDataMaps`, and are always *optional* to ensure compatibility with vanilla clients.
+# 内置数据映射
+
+NeoForge 提供了一些数据映射,这些映射主要取代硬编码的代码内普通映射。
+这些数据映射可以在 `NeoForgeDataMaps` 中找到,并且始终是*可选的*以确保与普通客户端的兼容性。
## `neoforge:compostables`
-NeoForge provides a data map that allows configuring composter values, as a replacement for `ComposterBlock#COMPOSTABLES` (which is now ignored).
-This data map is located at `neoforge/data_maps/item/compostables.json` and its objects have the following structure:
+
+NeoForge 提供了一个允许配置 Composter 值的数据映射,作为`ComposterBlock#COMPOSTABLES`(现在已被忽略)的替代品。
+该数据映射位于`neoforge/data_maps/item/compostables.json`,其对象具有以下结构:
+
```js
{
// A 0 to 1 (inclusive) float representing the chance that the item will update the level of the composter
@@ -13,6 +16,7 @@ This data map is located at `neoforge/data_maps/item/compostables.json` and its
```
Example:
+
```js
{
"values": {
@@ -25,8 +29,10 @@ Example:
```
## `neoforge:furnace_fuels`
-NeoForge provides a data map that allows configuring item burn times.
-This data map is located at `neoforge/data_maps/item/furnace_fuels.json` and its objects have the following structure:
+
+NeoForge 提供了一个数据映射,允许配置物品的燃烧时间。
+该数据图位于`neoforge/data_maps/item/furnace_fuels.json`,其对象具有以下结构:
+
```js
{
// A positive integer representing the item's burn time, in ticks
@@ -35,6 +41,7 @@ This data map is located at `neoforge/data_maps/item/furnace_fuels.json` and its
```
Example:
+
```js
{
"values": {
@@ -47,17 +54,19 @@ Example:
```
:::note
-Other in-code methods like `IItemExtension#getBurnTime` will take priority over the data map, so it is recommended that you use the data map for simple, static burn times even in your mod so that users can configure them.
+其他像 `IItemExtension#getBurnTime` 这样的内部代码方法将优先于数据映射,所以建议您在您的mod中使用数据映射来设置简单、静态的燃烧时间,这样用户可以按照他们的需求进行配置。
:::
:::warning
-Vanilla adds a burn time to logs and planks in the `minecraft:logs` and `minecraft:planks` tag. However, those tags also contain Nether wood, so a removal for elements in `#minecraft:non_flammable_wood` is added.
-However, the removal does not affect any values added by other packs or mods, so if you want to change the values for the wood tags you will need to add a removal for the non flammable tag yourself.
+
+原版游戏为 `minecraft:logs` 和 `minecraft:planks` 标签中的原木和木板添加了燃烧时间。但是,这些标签也包含了下界木材,因此添加了对 `#minecraft:non_flammable_wood` 中元素的移除。 然而,这种移除不会影响其他数据包或模组添加的任何值,所以如果您想改变木材标签的值,您需要自己添加对不可燃木材标签的移除。
+
:::
## `neoforge:parrot_imitations`
-NeoForge provides a data map that allows configuring the sounds produced by parrots when they want to imitate a mob, as a replacement for `Parrot#MOB_SOUND_MAP` (which is now ignored).
-This data map is located at `neoforge/data_maps/entity_type/parrot_imitations.json` and its objects have the following structure:
+
+NeoForge 提供了一个数据映射,允许配置鹦鹉在模仿怪物时产生的声音,这可以替代 `Parrot#MOB_SOUND_MAP`(现在已被忽视)。这个数据映射位于 `neoforge/data_maps/entity_type/parrot_imitations.json`,其对象具有以下结构:
+
```js
{
// The ID of the sound that parrots will produce when imitating the mob
@@ -66,6 +75,7 @@ This data map is located at `neoforge/data_maps/entity_type/parrot_imitations.js
```
Example:
+
```js
{
"values": {
@@ -78,8 +88,8 @@ Example:
```
## `neoforge:raid_hero_gifts`
-NeoForge provides a data map that allows configuring the gift that a villager with a certain `VillagerProfession` may gift you if you stop the raid, as a replacement for `GiveGiftToHero#GIFTS` (which is now ignored)
-This data map is located at `neoforge/data_maps/villager_profession/raid_hero_gifts.json` and its objects have the following structure:
+
+NeoForge 提供了一个数据映射,允许配置如果你阻止了突袭,具有某个 `VillagerProfession` 的村民可能会赠送给你的礼物,这将替代 `GiveGiftToHero#GIFTS`(现在已经被忽略了)。这个数据映射位于 `neoforge/data_maps/villager_profession/raid_hero_gifts.json`,其对象具有以下结构:
```js
{
@@ -93,8 +103,9 @@ This data map is located at `neoforge/data_maps/villager_profession/raid_hero_gi
```
## `neoforge:vibration_frequencies`
-NeoForge provides a data map that allows configuring the shulker vibration frequencies emitted by game events, as a replacement for `VibrationSystem#VIBRATION_FREQUENCY_FOR_EVENT` (which is now ignored).
-This data map is located at `neoforge/data_maps/game_event/vibration_frequencies.json` and its objects have the following structure:
+
+NeoForge 提供了一个数据映射,允许配置游戏事件发出的潜影贝探头频率,这将替代 `VibrationSystem#VIBRATION_FREQUENCY_FOR_EVENT`(现在已经被忽视了)。这个数据映射位于 `neoforge/data_maps/game_event/vibration_frequencies.json`,其对象具有以下结构:
+
```js
{
// An integer between 1 and 15 (inclusive) that indicates the vibration frequency of the event
@@ -103,6 +114,7 @@ This data map is located at `neoforge/data_maps/game_event/vibration_frequencies
```
Example:
+
```js
{
"values": {
@@ -112,4 +124,5 @@ Example:
}
}
}
-```
\ No newline at end of file
+```
+
From 2332af700d3bbb3166611423b5aa6b697fb5f86a Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 16:30:24 +0800
Subject: [PATCH 38/87] Update structure.md
---
docs/datamaps/structure.md | 74 +++++++++++++++++++-------------------
1 file changed, 37 insertions(+), 37 deletions(-)
diff --git a/docs/datamaps/structure.md b/docs/datamaps/structure.md
index 431b6a4c0..36bb29e69 100644
--- a/docs/datamaps/structure.md
+++ b/docs/datamaps/structure.md
@@ -1,41 +1,41 @@
-# JSON Structure
-For the purposes of this page, we will use a data map which is an object with two float keys: `amount` and `chance` as an example. The codec for that object can be found [here](./index.md#registration).
+# JSON结构
+对于此页面,我们将使用一个数据映射作为例子,其对象具有两个浮点键:`amount` 和 `chance`。该对象的编码可以在[这里](./index.md#registration)找到。
-## Location
-Data maps are loaded from a JSON file located at `mapNamespace/data_maps/registryNamespace/registryPath/mapPath.json`, where:
-- `mapNamespace` is the namespace of the ID of the data map
-- `mapPath` is the path of the ID of the data map
-- `registryNamespace` is the namespace of the ID of the registry
-- `registryPath` is the path of the ID of the registry
+## 地址
+数据映射加载自位于 `mapNamespace/data_maps/registryNamespace/registryPath/mapPath.json` 的JSON文件,其中:
+- `mapNamespace` 是数据映射ID的命名空间
+- `mapPath` 是数据映射ID的路径
+- `registryNamespace` 是注册表ID的命名空间
+- `registryPath` 是注册表ID的路径
:::note
-The registry namespace is ommited if it is `minecraft`.
+如果是 `minecraft`,则省略注册表命名空间。
:::
-Examples:
-- For a data map named `mymod:drop_healing` for the `minecraft:item` registry (as in the example), the path will be `mymod/data_maps/item/drop_healing.json`.
-- For a data map named `somemod:somemap` for the `minecraft:block` registry, the path will be `somemod/data_maps/block/somemap.json`.
-- For a data map named `example:stuff` for the `somemod:custom` registry, the path will be `example/data_maps/somemod/custom/stuff.json`.
+示例:
+- 对于名为 `mymod:drop_healing` 的数据映射,用于 `minecraft:item` 注册表(如示例中),路径将是 `mymod/data_maps/item/drop_healing.json`。
+- 对于名为 `somemod:somemap` 的数据映射,用于 `minecraft:block` 注册表,路径将是 `somemod/data_maps/block/somemap.json`。
+- 对于名为 `example:stuff` 的数据映射,用于 `somemod:custom` 注册表,路径将是 `example/data_maps/somemod/custom/stuff.json`。
-## Global `replace` field
-The JSON file has an optional, global `replace` field, which is similar to tags, and when `true` will remove all previously attached values of that data map. This is useful for datapacks that want to completely change the entire data map.
+## 全局 `replace` 字段
+JSON文件具有一个可选的全局 `replace` 字段,类似于标签,当其为 `true` 时,将移除该数据映射的所有先前附加值。这对于想要完全改变整个数据映射的数据包非常有用。
-## Loading conditions
-Data map files support [loading conditions](../resources/server/conditional) both at root-level and at entry-level through a `neoforge:conditions` array.
+## 加载条件
+数据映射文件支持在根级别和条目级别通过 `neoforge:conditions` 数组支持[加载条件](../resources/server/conditional)。
-## Adding values
-Values can be attached to objects using the `values` map. Each key will represent either the ID of an individual registry entry to attach the value to, or a tag key, preceeded by `#`. If it is a tag, the same value will be attached to all entries in that tag.
-The key will be the object to attach.
+## 添加值
+可以使用 `values` 映射将值附加到对象。每个键将代表要附加值的单个注册表条目的ID,或者一个以 `#` 开头的标签键。如果是一个标签,那么相同的值将附加到该标签的所有条目上。
+键将是要附加的对象。
```js
{
"values": {
- // Attach a value to the carrot item
+ // 为胡萝卜项附加一个值
"minecraft:carrot": {
"amount": 12,
"chance": 1
},
- // Attach a value to all items in the logs tag
+ // 将一个值附加到 logs 标签的所有项上
"#minecraft:logs": {
"amount": 1,
"chance": 0.1
@@ -45,15 +45,15 @@ The key will be the object to attach.
```
:::info
-The above structure will invoke mergers in the case of [advanced data maps](./index.md#advanced-data-maps). If you do not want to invoke the merger for a specific object, then you will have to use a structure similar to this one:
+上述结构将在[高级数据映射](./index.md#advanced-data-maps)的情况下调用合并器。如果你不想为特定的对象调用合并器,那么你将不得不使用类似于这样的结构:
```js
{
"values": {
- // Overwrite the value of the carrot item
+ // 覆盖胡萝卜项的值
"minecraft:carrot": {
- // highlight-next-line
+ // 高亮下一行
"replace": true,
- // The new value will be under a value sub-object
+ // 新的值将在 value 子对象下
"value": {
"amount": 12,
"chance": 1
@@ -64,40 +64,40 @@ The above structure will invoke mergers in the case of [advanced data maps](./in
```
:::
-## Removing values
+## 移除值
-A JSON file can also remove values previously attached to objects, through the use of the `remove` array:
+JSON文件也可以通过使用 `remove` 数组,从对象中移除先前附加的值:
```js
{
- // Remove the value attached to apples and potatoes
+ // 移除附加到苹果和土豆的值
"remove": ["minecraft:apple", "minecraft:potato"]
}
```
-The array contains a list of registry entry IDs or tags to remove the value from.
+数组包含一系列要从其中移除值的注册表条目ID或标签。
:::warning
-Removals happen after the values in the current JSON file have been attached, so you can use the removal feature to remove a value attached to an object through a tag:
+移除操作在当前JSON文件的值被附加后进行,所以你可以使用移除功能来移除通过标签附加到对象的值:
```js
{
"values": {
"#minecraft:logs": 12
},
- // Remove the value from the acacia log, so that all logs but acacia have the value 12 attached to them
+ // 从金合欢原木移除值,这样所有原木除了金合欢都将附加值 12
"remove": ["minecraft:acacia_log"]
}
```
:::
:::info
-In the case of [advanced data maps](./index.md#advanced-data-maps) that provide a custom remover, the arguments of the remover can be provided by transforming the `remove` array into a map.
-Let's assume that the remover object is serialized as a string and removes the value with a given key for a `Map`-based data map:
+在提供自定义移除器的[高级数据映射](./index.md#advanced-data-maps)的情况下,可以通过将 `remove` 数组转换为映射来提供移除器的参数。
+假设移除器对象被串行化为字符串,并且为基于 `Map` 的数据映射移除具有给定键的值:
```js
{
"remove": {
- // The remover will be deserialized from the value (`somekey1` in this case)
- // and applied to the value attached to the carrot item
+ // 移除器将从值(这种情况下为 `somekey1`)反串行化
+ // 并应用于附加到胡萝卜项的值
"minecraft:carrot": "somekey1"
}
}
```
-:::
\ No newline at end of file
+:::
From dc1a6325bdebf07a2649a8ec987657324404b34b Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 18:54:56 +0800
Subject: [PATCH 39/87] Update index.md
---
docs/datamaps/index.md | 148 ++++++++++++++++++++---------------------
1 file changed, 74 insertions(+), 74 deletions(-)
diff --git a/docs/datamaps/index.md b/docs/datamaps/index.md
index 3886d4ff6..7bfc2089a 100644
--- a/docs/datamaps/index.md
+++ b/docs/datamaps/index.md
@@ -1,24 +1,24 @@
-# Data Maps
+# 数据映射
-A registry data map contains data-driven, reloadable objects that can be attached to a registry object.
-This system allows more easily data-driving game behaviour, as they provide functionality such as syncing or conflict resolution, leading to a better and more configurable user experience.
+注册表数据映射包含可附加到注册表对象的数据驱动、可重载的对象。
+这个系统允许更容易地数据驱动游戏行为,因为它们提供了如同步或冲突解决等功能,从而带来更好、更可配置的用户体验。
-You can think of tags as registry object ➜ boolean maps, while data maps are more flexible registry object ➜ object maps.
+你可以将标签看作注册表对象 ➜ 布尔映射,而数据映射则是更灵活的注册表对象 ➜ 对象映射。
-A data map can be attached to both static, built-in, registries and dynamic data-driven datapack registries.
+数据映射可以附加到静态的内置注册表和动态的数据驱动的数据包注册表上。
-Data maps support reloading through the use of the `/reload` command or any other means that reload server resources.
+数据映射支持通过使用 `/reload` 命令或任何其他重新加载服务器资源的方法来重新加载。
-## Registration
-A data map type should be statically created and then registered to the `RegisterDataMapTypesEvent` (which is fired on the [mod event bus](../concepts/events)). The `DataMapType` can be created using a `DataMapType$Builder`, through `DataMapType#builder`.
+## 注册
+数据映射类型应该静态创建,然后注册到 `RegisterDataMapTypesEvent`(在 [mod事件总线](../concepts/events)上触发)。`DataMapType` 可以使用 `DataMapType$Builder` 通过 `DataMapType#builder` 创建。
-The builder provides a `synced` method which can be used to mark a data map as synced and have it sent to clients.
+构建器提供了一个 `synced` 方法,可以用来标记数据映射为同步并将其发送给客户端。
-A simple `DataMapType` has two generic arguments: `R` (the type of the registry the data map is for) and `T` (the values that are being attached). A data map of `SomeObject`s that are attached to `Item`s can, as such, be represented as `DataMapType- `.
+一个简单的 `DataMapType` 有两个泛型参数:`R`(数据映射所针对的注册表的类型)和 `T`(被附加的值)。因此,可以将附加到 `Item` 的 `SomeObject` 的数据映射表示为 `DataMapType
- `。
-Data maps are serialized and deserialized using [Codecs](../datastorage/codecs.md).
+数据映射使用 [编解码器](../datastorage/codecs.md) 进行序列化和反序列化。
-Let's take the following record representing the data map value as an example:
+以以下表示数据映射值的记录为例:
```java
public record DropHealing(
float amount, float chance
@@ -31,54 +31,54 @@ public record DropHealing(
```
:::warning
-The value (`T`) should be an *immutable* object, as otherwise weird behaviour can be caused if the object is attached to all entries within a tag (since no copy is created).
+值 (`T`) 应为 *不可变* 对象,否则如果对象附加到标签内的所有条目,则可能导致奇怪的行为(因为不会创建副本)。
:::
-For the purposes of this example, we will use this data map to heal players when they drop an item.
-The `DataMapType` can be created as such:
+为了本例的目的,我们将使用此数据映射在玩家丢弃物品时治疗玩家。
+`DataMapType` 可以这样创建:
```java
public static final DataMapType
- DROP_HEALING = DataMapType.builder(
new ResourceLocation("mymod:drop_healing"), Registries.ITEM, DropHealing.CODEC
).build();
```
-and then registered to the `RegisterDataMapTypesEvent` using `RegisterDataMapTypesEvent#register`.
+然后使用 `RegisterDataMapTypesEvent#register` 注册到 `RegisterDataMapTypesEvent`。
-## Syncing
-A synced data map will have its values synced to clients. A data map can be marked as synced using `DataMapType$Builder#synced(Codec networkCodec, boolean mandatory)`.
-The values of the data map will then be synced using the `networkCodec`.
-If the `mandatory` flag is set to `true`, clients that do not support the data map (including Vanilla clients) will not be able to connect to the server, nor vice-versa. A non-mandatory data map on the other hand is optional, so it will not prevent any clients from joining.
+## 同步
+同步的数据映射将会将其值同步到客户端。可以使用 `DataMapType$Builder#synced(Codec networkCodec, boolean mandatory)` 标记数据映射为同步。
+然后将使用 `networkCodec` 同步数据映射的值。
+如果 `mandatory` 标志设置为 `true`,则不支持数据映射的客户端(包括 Vanilla 客户端)将无法连接到服务器,反之亦然。另一方面,非强制性的数据映射是可选的,因此它不会阻止任何客户端加入。
:::tip
-A separate network codec allows for packet sizes to be smaller, as you can choose what data to send, and in what format. Otherwise the default codec can be used.
+单独的网络编解码器允许包大小更小,因为你可以选择发送哪些数据以及以什么格式发送。否则可以使用默认编解码器。
:::
-## JSON Structure and location
-Data maps are loaded from a JSON file located at `mapNamespace/data_maps/registryNamespace/registryPath/mapPath.json`, where:
-- `mapNamespace` is the namespace of the ID of the data map
-- `mapPath` is the path of the ID of the data map
-- `registryNamespace` is the namespace of the ID of the registry; if the namespace is `minecraft`, this value will be omitted
-- `registryPath` is the path of the ID of the registry
+## JSON结构和位置
+数据映射从位于 `mapNamespace/data_maps/registryNamespace/registryPath/mapPath.json` 的JSON文件加载,其中:
+- `mapNamespace` 是数据映射ID的命名空间
+- `mapPath` 是数据映射ID的路径
+- `registryNamespace` 是注册表ID的命名空间;如果命名空间是 `minecraft`,则此值将被省略
+- `registryPath` 是注册表ID的路径
-For more information, please [check out the dedicated page](./structure.md).
+更多信息,请[查看专用页面](./structure.md)。
-## Usage
-As data maps can be used on any registry, they can be queried through `Holder`s, and not through the actual registry objects.
-You can query a data map value using `Holder#getData(DataMapType)`. If that object doesn't have a value attached, the method will return `null`.
+## 使用
+由于数据映射可以用于任何注册表,因此可以通过 `Holder` 查询它们,而不是通过实际的注册表对象。
+你可以使用 `Holder#getData(DataMapType)` 查询数据映射值。如果该对象没有附加值,方法将返回 `null`。
:::note
-Only reference holders will return a value in that method. `Direct` holders will **not**. Generally, you will only encounter reference holders (which are returned by methods such as `Registry#wrapAsHolder`, `Registry#getHolder` or the different `builtInRegistryHolder` methods).
+只有引用持有者会在该方法中返回值。`直接` 持有者 **不会**。通常,你只会遇到引用持有者(它们由 `Registry#wrapAsHolder`、`Registry#getHolder` 或不同的 `builtInRegistryHolder` 方法返回)。
:::
-To continue the example above, we can implement our intended behaviour as follows:
+为了继续上面的示例,我们可以如下实现我们预期的行为:
```java
public static void onItemDrop(final ItemTossEvent event) {
final ItemStack stack = event.getEntity().getItem();
- // ItemStack has a getItemHolder method that will return a Holder
- which points to the item the stack is of
- //highlight-next-line
+ // ItemStack 有一个 getItemHolder 方法,它将返回一个指向堆叠物的物品的 Holder
-
+ //高亮下一行
final DropHealing value = stack.getItemHolder().getData(DROP_HEALING);
- // Since getData returns null if the item will not have a drop healing value attached, we guard against it being null
+ // 由于 getData 如果物品没有附加 drop healing 值将返回 null,我们保护它不为 null
if (value != null) {
- // And here we simply use the values
+ // 这里我们简单地使用值
if (event.getPlayer().level().getRandom().nextFloat() > value.chance()) {
event.getPlayer().heal(value.amount());
}
@@ -86,43 +86,43 @@ public static void onItemDrop(final ItemTossEvent event) {
}
```
-## Advanced data maps
-Advanced data maps are data maps which have additional functionality. Namely, the ability of merging values and selectively removing them, through a remover. Implementing some form of merging and removers is highly recommended for data maps whose values are collection-likes (like `Map`s or `List`s).
+## 高级数据映射
+高级数据映射是具有额外功能的数据映射。即,通过移除器合并值和选择性地移除它们的能力。对于值类似于集合(如 `Map` 或 `List`)的数据映射,强烈推荐实现某种形式的合并和移除器。
-`AdvancedDataMapType` have one more generic besides `T` and `R`: `VR extends DataMapValueRemover`. This additional generic allows you to datagen remove objects with increased type safety.
+`AdvancedDataMapType` 除了 `T` 和 `R` 之外还有一个泛型:`VR extends DataMapValueRemover`。这个额外的泛型允许你通过提高类型安全性来生成移除对象。
-### Creation
-You create an `AdvancedDataMapType` using `AdvancedDataMapType#builder`. Unlike the normal builder, the builder returned by that method will have two more methods (`merger` and `remover`), and it will return an `AdvancedDataMapType`. Registration methods remain the same.
+### 创建
+你可以使用 `AdvancedDataMapType#builder` 创建 `AdvancedDataMapType`。与普通构建器不同,该方法返回的构建器将有两个额外的方法(`merger` 和 `remover`),并且它将返回一个 `AdvancedDataMapType`。注册方法保持不变。
-### Mergers
-An advanced data map can provide a `DataMapValueMerger` through `AdvancedDataMapType#merger`. This merger will be used to handle conflicts between data packs that attempt to attach a value to the same object.
-The merger will be given the two conflicting values, and their sources (as an `Either, ResourceKey>` since values can be attached to all entries within a tag, not just individual entries), and is expected to return the value that will actually be attached.
-Generally, mergers should simply merge the values, and should not perform "hard" overwrites unless necessary (i.e. if merging isn't possible). If a pack wants to bypass the merger, it can do so by specifying the object-level `replace` field.
+### 合并器
+高级数据映射可以通过 `AdvancedDataMapType#merger` 提供一个 `DataMapValueMerger`。这个合并器将用于处理尝试将值附加到同一对象的数据包之间的冲突。
+合并器将给出两个冲突的值及其来源(作为 `Either, ResourceKey>`,因为值可以附加到标签内的所有条目,而不仅仅是个别条目),并期望返回实际附加的值。
+通常,合并器应简单地合并值,并且除非必要(即如果合并不可能),否则不应执行“硬”覆盖。如果一个包想要绕过合并器,它可以通过指定对象级别的 `replace` 字段来实现。
-Let's imagine a scenario where we have a data map that attaches integers to items:
+假设我们有一个将整数附加到物品的数据映射的情况:
```java
public class IntMerger implements DataMapValueMerger
- {
@Override
public Integer merge(Registry
- registry, Either, ResourceKey
- > first, Integer firstValue, Either, ResourceKey
- > second, Integer secondValue) {
- //highlight-next-line
+ //高亮下一行
return firstValue + secondValue;
}
}
```
-The above merger will merge the values if two datapacks attach to the same object. So if the first pack attaches the value `12` to `minecraft:carrot`, and the second pack attaches the value `15` to `minecraft:carrot`, the final value will be `27`. However, if the second pack specifies the object-level `replace` field, the final value will be `15` as the merger won't be invoked.
+如果两个数据包附加到同一对象,则上述合并器将合并值。所以如果第一个包将值 `12` 附加到 `minecraft:carrot`,第二个包将值 `15` 附加到 `minecraft:carrot`,最终的值将是 `27`。然而,如果第二个包指定对象级别的 `replace` 字段,最终值将是 `15`,因为不会调用合并器。
-NeoForge provides some default mergers for merging lists, sets and maps in `DataMapValueMerger`.
+NeoForge 为合并列表、集合和映射提供了一些默认的合并器,位于 `DataMapValueMerger` 中。
-The default merger (`DataMapValueMerger#defaultMerger`) has the typical behaviour you'd expect from normal data packs, where the newest value (which comes from the highest datapack) overwrites the previous value.
+默认合并器(`DataMapValueMerger#defaultMerger`)具有你期望的普通数据包的典型行为,其中最新的值(来自最高的数据包)将覆盖之前的值。
-### Removers
-An advanced data map can provide a `DataMapValueRemover` through `AdvancedDataMapType#remover`. The remover will allow selective removals of data map values, effectively decomposition.
-While by default a datapack can only remove the whole object attached to a registry entry, with a remover it can remove just speciffic values from the attached object (i.e. just the entry with a given key in the case of a map, or the entry with a specific property in the case of a list).
+### 移除器
+高级数据映射可以通过 `AdvancedDataMapType#remover` 提供一个 `DataMapValueRemover`。移除器将允许选择性地移除数据映射值,有效地进行分解。
+虽然默认情况下一个数据包只能移除附加到注册表条目的整个对象,但有了移除器,它可以只从附加对象中移除特定的值(即,在映射的情况下,只移除具有给定键的项,或在列表的情况下,只移除具有特定属性的项)。
-The codec that is passed to the builder will decode remover instances. These removers will then be given the value currently attached and its source, and are expected to create a new object to replace the old value.
-Alternatively, an empty `Optional` will lead to the value being completely removed.
+传递给构建器的编解码器将解码移除器实例。然后这些移除器将给出当前附加的值及其来源,并期望创建一个新对象来替换旧值。
+或者,一个空的 `Optional` 将导致值被完全移除。
-An example of a remover that will remove a value with a specific key from a `Map`-based data map:
+一个从基于 `Map` 的数据映射中移除具有特定键的值的移除器示例:
```java
public record MapRemover(String key) implements DataMapValueRemover
- > {
public static final Codec CODEC = Codec.STRING.xmap(MapRemover::new, MapRemover::key);
@@ -136,36 +136,36 @@ public record MapRemover(String key) implements DataMapValueRemover
-
Date: Thu, 25 Apr 2024 18:55:30 +0800
Subject: [PATCH 40/87] Update index.md
---
docs/datamaps/index.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/datamaps/index.md b/docs/datamaps/index.md
index 7bfc2089a..d368ceb3f 100644
--- a/docs/datamaps/index.md
+++ b/docs/datamaps/index.md
@@ -165,7 +165,7 @@ public record MapRemover(String key) implements DataMapValueRemover
-
Date: Thu, 25 Apr 2024 18:58:37 +0800
Subject: [PATCH 41/87] Update attachments.md
---
docs/datastorage/attachments.md | 90 ++++++++++++++++-----------------
1 file changed, 45 insertions(+), 45 deletions(-)
diff --git a/docs/datastorage/attachments.md b/docs/datastorage/attachments.md
index 6f2aace5a..408710921 100644
--- a/docs/datastorage/attachments.md
+++ b/docs/datastorage/attachments.md
@@ -1,103 +1,103 @@
-# Data Attachments
+# 数据附件
-The data attachment system allows mods to attach and store additional data on block entities, chunks, entities, and item stacks.
+数据附件系统允许模组在方块实体、区块、实体和物品堆叠上附加和存储额外数据。
-_To store additional level data, you can use [SavedData](saveddata)._
+_要存储额外的关卡数据,您可以使用 [SavedData](saveddata)。_
-## Creating an attachment type
+## 创建附件类型
-To use the system, you need to register an `AttachmentType`.
-The attachment type contains the following configuration:
-- A default value supplier to create the instance when the data is first accessed. Also used to compare stacks that have the data with stacks that don't have it.
-- An optional serializer if the attachment should be persisted.
-- (If a serializer was configured) The `copyOnDeath` flag to automatically copy entity data on death (see below).
-- (Advanced) (If a serializer was configured) A custom `comparator` to use when checking if the data is the same for two item stacks.
+要使用系统,您需要注册一个 `AttachmentType`。
+附件类型包含以下配置:
+- 当数据第一次被访问时创建实例的默认值供应器。也用于比较有数据的堆叠和没有数据的堆叠。
+- 如果附件需要持久化,则需要一个可选的序列化器。
+- (如果配置了序列化器)`copyOnDeath` 标志,用于在死亡时自动复制实体数据(见下文)。
+- (高级)(如果配置了序列化器)自定义 `comparator`,用于检查两个物品堆叠的数据是否相同。
:::tip
-If you don't want your attachment to persist, do not provide a serializer.
+如果您不希望您的附件持久化,不要提供序列化器。
:::
-There are a few ways to provide an attachment serializer: directly implementing `IAttachmentSerializer`, implementing `INBTSerializable` and using the static `AttachmentSerializer.serializable()` method to create the builder, or providing a codec to the builder.
+有几种方法提供附件序列化器:直接实现 `IAttachmentSerializer`,实现 `INBTSerializable` 并使用静态的 `AttachmentSerializer.serializable()` 方法创建构建器,或向构建器提供编解码器。
:::warning
-Avoid serialization with codecs for item stack attachments, as it is comparatively slow.
+避免使用编解码器序列化物品堆叠附件,因为它相对较慢。
:::
-In any case, the attachment **must be registered** to the `NeoForgeRegistries.ATTACHMENT_TYPES` registry. Here is an example:
+无论哪种方式,附件 **必须被注册** 到 `NeoForgeRegistries.ATTACHMENT_TYPES` 注册表中。以下是一个示例:
```java
-// Create the DeferredRegister for attachment types
+// 为附件类型创建 DeferredRegister
private static final DeferredRegister> ATTACHMENT_TYPES = DeferredRegister.create(NeoForgeRegistries.ATTACHMENT_TYPES, MOD_ID);
-// Serialization via INBTSerializable
+// 通过 INBTSerializable 序列化
private static final Supplier> HANDLER = ATTACHMENT_TYPES.register(
"handler", () -> AttachmentType.serializable(() -> new ItemStackHandler(1)).build());
-// Serialization via codec
+// 通过编解码器序列化
private static final Supplier> MANA = ATTACHMENT_TYPES.register(
"mana", () -> AttachmentType.builder(() -> 0).serialize(Codec.INT).build());
-// No serialization
+// 无序列化
private static final Supplier> SOME_CACHE = ATTACHMENT_TYPES.register(
"some_cache", () -> AttachmentType.builder(() -> new SomeCache()).build()
);
-// In your mod constructor, don't forget to register the DeferredRegister to your mod bus:
+// 在您的 mod 构造函数中,不要忘记将 DeferredRegister 注册到您的 mod 总线:
ATTACHMENT_TYPES.register(modBus);
```
-## Using the attachment type
+## 使用附件类型
-Once the attachment type is registered, it can be used on any holder object.
-Calling `getData` if no data is present will attach a new default instance.
+一旦附件类型注册后,它可以在任何持有对象上使用。
+如果没有数据,调用 `getData` 将附加一个新的默认实例。
```java
-// Get the ItemStackHandler if it already exists, else attach a new one:
+// 如果已存在 ItemStackHandler,则获取它,否则附加一个新的:
ItemStackHandler stackHandler = stack.getData(HANDLER);
-// Get the current player mana if it is available, else attach 0:
+// 获取当前玩家的法力值(如果有),否则附加 0:
int playerMana = player.getData(MANA);
-// And so on...
+// 等等...
```
-If attaching a default instance is not desired, a `hasData` check can be added:
+如果不希望附加一个默认实例,可以添加一个 `hasData` 检查:
```java
-// Check if the stack has the HANDLER attachment before doing anything.
+// 检查堆叠是否有 HANDLER 附件,然后再进行任何操作。
if (stack.hasData(HANDLER)) {
ItemStackHandler stackHandler = stack.getData(HANDLER);
- // Do something with stack.getData(HANDLER).
+ // 对 stack.getData(HANDLER) 做些什么。
}
```
-The data can also be updated with `setData`:
+数据也可以用 `setData` 更新:
```java
-// Increment mana by 10.
+// 将法力值增加 10。
player.setData(MANA, player.getData(MANA) + 10);
```
:::important
-Usually, block entities and chunks need to be marked as dirty when they are modified (with `setChanged` and `setUnsaved(true)`). This is done automatically for calls to `setData`:
+通常,当修改方块实体和区块时需要将其标记为脏数据(使用 `setChanged` 和 `setUnsaved(true)`)。这对于 `setData` 的调用是自动完成的:
```java
-chunk.setData(MANA, chunk.getData(MANA) + 10); // will call setUnsaved automatically
+chunk.setData(MANA, chunk.getData(MANA) + 10); // 将自动调用 setUnsaved
```
-but if you modify some data that you obtained from `getData` (including a newly created default instance) then you must mark block entities and chunks as dirty explicitly:
+但如果您修改了从 `getData` 获取的数据(包括新创建的默认实例),则必须显式地将方块实体和区块标记为脏数据:
```java
var mana = chunk.getData(MUTABLE_MANA);
mana.set(10);
-chunk.setUnsaved(true); // must be done manually because we did not use setData
+chunk.setUnsaved(true); // 必须手动完成,因为我们没有使用 setData
```
:::
-## Sharing data with the client
-Currently, only serializable item stack attachments are synced between the client and the server.
-This is done automatically.
+## 与客户端共享数据
+目前,只有可序列化的物品堆叠附件在客户端和服务器之间同步。
+这是自动完成的。
-To sync block entity, chunk, or entity attachments to a client, you need to [send a packet to the client][network] yourself.
-For chunks, you can use `ChunkWatchEvent.Sent` to know when to send chunk data to a player.
+要将方块实体、区块或实体附件同步到客户端,你需要自己[向客户端发送数据包][network]。
+对于区块,您可以使用 `ChunkWatchEvent.Sent` 来知道何时向玩家发送区块数据。
-## Copying data on player death
-By default, entity data attachments are not copied on player death.
-To automatically copy an attachment on player death, set `.copyOnDeath()` in the attachment builder.
+## 在玩家死亡时复制数据
+默认情况下,实体数据附件在玩家死亡时不会被复制。
+要在玩家死亡时自动复制附件,请在附件构建器中设置 `.copyOnDeath()`。
-More complex handling can be implemented via `PlayerEvent.Clone` by reading the data from the original entity and assigning it to the new entity. In this event, the `#isWasDeath` method can be used to distinguish between respawning after death and returning from the End. This is important because the data will already exist when returning from the End, so care has to be taken to not duplicate values in this case.
+更复杂的处理可以通过 `PlayerEvent.Clone` 实现,通过从原始实体中读取数据并将其分配给新实体。在此事件中,可以使用 `#isWasDeath` 方法区分死亡后重生和从末地返回。这很重要,因为从末地返回时数据已经存在,因此要注意在这种情况下不要重复值。
-For example:
+例如:
```java
NeoForge.EVENT_BUS.register(PlayerEvent.Clone.class, event -> {
if (event.isWasDeath() && event.getOriginal().hasData(MY_DATA)) {
@@ -106,4 +106,4 @@ NeoForge.EVENT_BUS.register(PlayerEvent.Clone.class, event -> {
});
```
-[network]: ../networking/index.md
\ No newline at end of file
+[network]: ../networking/index.md
From dfc419e44e5d61c2d1997fbc961ee0fdb353b5c0 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 19:16:06 +0800
Subject: [PATCH 42/87] Update capabilities.md
---
docs/datastorage/capabilities.md | 307 ++++++++++++++-----------------
1 file changed, 143 insertions(+), 164 deletions(-)
diff --git a/docs/datastorage/capabilities.md b/docs/datastorage/capabilities.md
index 94fff8c71..ecbd044a7 100644
--- a/docs/datastorage/capabilities.md
+++ b/docs/datastorage/capabilities.md
@@ -1,299 +1,281 @@
-# Capabilities
+# 功能
-Capabilities allow exposing features in a dynamic and flexible way without having to resort to directly implementing many interfaces.
+功能(Capabilities)允许以动态和灵活的方式公开特性,无需直接实现许多接口。
-In general terms, each capability provides a feature in the form of an interface.
+通常来说,每个功能都以接口的形式提供一个特性。
-NeoForge adds capability support to blocks, entities, and item stacks.
-This will be explained in more detail in the following sections.
+NeoForge 为方块、实体和物品堆叠添加了功能支持。
+这将在以下部分中更详细地解释。
-## Why use capabilities
+## 为什么使用功能
-Capabilities are designed to separate **what** a block, entity or item stack can do from **how** it does it.
-If you are wondering whether capabilities are the right tool for a job, ask yourself the following questions:
-1. Do I only care about **what** a block, entity or item stack can do, but not about **how** it does it?
-2. Is the **what**, the behavior, only available for some blocks, entities, or item stacks, but not all of them?
-3. Is the **how**, the implementation of that behavior, dependent on the specific block, entity or item stack?
+功能旨在将**能做什么**与**如何做**分离开来,适用于方块、实体或物品堆叠。
+如果您正在考虑功能是否适合某项工作,请问自己以下问题:
+1. 我只关心方块、实体或物品堆叠能做什么,而不关心它如何做吗?
+2. 这个 **能做什么**,也就是行为,是否只对某些方块、实体或物品堆叠有效,而不是所有?
+3. 这个 **如何做**,即行为的实现,是否依赖于具体的方块、实体或物品堆叠?
-Here are a few examples of good capability usage:
-- *"I want my fluid container to be compatible with fluid containers from other mods, but I don't know the specifics of each fluid container."* - Yes, use the `IFluidHandler` capability.
-- *"I want to count how many items are in some entity, but I do not know how the entity might store them."* - Yes, use the `IItemHandler` capability.
-- *"I want to fill some item stack with power, but I do not know how the item stack might store it."* - Yes, use the `IEnergyStorage` capability.
-- *"I want to apply some color to whatever block a player is currently targeting, but I do not know how the block will be transformed."* - Yes. NeoForge does not provide a capability to color blocks, but you can implement one yourself.
+以下是一些良好的功能使用示例:
+- *“我希望我的流体容器能与其他模组的流体容器兼容,但我不知道每个流体容器的具体情况。”* - 是的,使用 `IFluidHandler` 功能。
+- *“我想计算某个实体中有多少物品,但我不知道实体可能如何存储它们。”* - 是的,使用 `IItemHandler` 功能。
+- *“我想给某个物品堆叠充能,但我不知道物品堆叠可能如何存储能量。”* - 是的,使用 `IEnergyStorage` 功能。
+- *“我想对玩家当前瞄准的任何方块应用颜色,但我不知道方块将如何变化。”* - 是的。NeoForge 没有提供给方块上色的功能,但你可以自己实现。
-Here is an example of discouraged capability usage:
-- *"I want to check if an entity is within the range of my machine."* - No, use a helper method instead.
+以下是不推荐使用功能的示例:
+- *“我想检查某个实体是否在我的机器范围内。”* - 不,使用帮助方法代替。
-## NeoForge-provided capabilities
+## NeoForge 提供的功能
-NeoForge provides capabilities for the following three interfaces: `IItemHandler`, `IFluidHandler` and `IEnergyStorage`.
+NeoForge 为以下三个接口提供了功能:`IItemHandler`,`IFluidHandler` 和 `IEnergyStorage`。
-`IItemHandler` exposes an interface for handling inventory slots. The capabilities of type `IItemHandler` are:
-- `Capabilities.ItemHandler.BLOCK`: automation-accessible inventory of a block (for chests, machines, etc).
-- `Capabilities.ItemHandler.ENTITY`: inventory contents of an entity (extra player slots, mob/creature inventories/bags).
-- `Capabilities.ItemHandler.ENTITY_AUTOMATION`: automation-accessible inventory of an entity (boats, minecarts, etc).
-- `Capabilities.ItemHandler.ITEM`: contents of an item stack (portable backpacks and such).
+`IItemHandler` 公开了处理库存槽的接口。`IItemHandler` 类型的功能有:
+- `Capabilities.ItemHandler.BLOCK`:方块的自动化可访问库存(用于箱子、机器等)。
+- `Capabilities.ItemHandler.ENTITY`:实体的库存内容(额外的玩家槽位、怪物/生物的库存/包)。
+- `Capabilities.ItemHandler.ENTITY_AUTOMATION`:实体的自动化可访问库存(船、矿车等)。
+- `Capabilities.ItemHandler.ITEM`:物品堆叠的内容(便携背包等)。
-`IFluidHandler` exposes an interface for handling fluid inventories. The capabilities of type `IFluidHandler` are:
-- `Capabilities.FluidHandler.BLOCK`: automation-accessible fluid inventory of a block.
-- `Capabilities.FluidHandler.ENTITY`: fluid inventory of an entity.
-- `Capabilities.FluidHandler.ITEM`: fluid inventory of an item stack.
-This capability is of the special `IFluidHandlerItem` type due to the way buckets hold fluids.
+`IFluidHandler` 公开了处理流体库存的接口。`IFluidHandler` 类型的功能有:
+- `Capabilities.FluidHandler.BLOCK`:方块的自动化可访问流体库存。
+- `Capabilities.FluidHandler.ENTITY`:实体的流体库存。
+- `Capabilities.FluidHandler.ITEM`:物品堆叠的流体库存。
+这个功能是特殊的 `IFluidHandlerItem` 类型,因为桶装液体的方式有所不同。
-`IEnergyStorage` exposes an interface for handling energy containers. It is based on the RedstoneFlux API by TeamCoFH. The capabilities of type `IEnergyStorage` are:
-- `Capabilities.EnergyStorage.BLOCK`: energy contained inside a block.
-- `Capabilities.EnergyStorage.ENTITY`: energy containing inside an entity.
-- `Capabilities.EnergyStorage.ITEM`: energy contained inside an item stack.
+`IEnergyStorage` 公开了处理能量容器的接口。它基于 TeamCoFH 的 RedstoneFlux API。`IEnergyStorage` 类型的功能有:
+- `Capabilities.EnergyStorage.BLOCK`:方块内部的能量。
+- `Capabilities.EnergyStorage.ENTITY`:实体内部的能量。
+- `Capabilities.EnergyStorage.ITEM`:物品堆叠内部的能量。
-## Creating a capability
+## 创建功能
-NeoForge supports capabilities for blocks, entities, and item stacks.
-
-Capabilities allow looking up implementations of some APIs with some dispatching logic. The following kinds of capabilities are implemented in NeoForge:
-- `BlockCapability`: capabilities for blocks and block entities; behavior depends on the specific `Block`.
-- `EntityCapability`: capabilities for entities: behavior dependends on the specific `EntityType`.
-- `ItemCapability`: capabilities for item stacks: behavior depends on the specific `Item`.
+NeoForge为方块、实体和物品堆叠支持功能性。功能性允许在一定逻辑下查找某些API的实现。在NeoForge中实现了以下几种功能性:
+- `BlockCapability`:适用于方块和方块实体的功能性;行为依赖于特定的`Block`。
+- `EntityCapability`:适用于实体的功能性;行为依赖于特定的`EntityType`。
+- `ItemCapability`:适用于物品堆叠的功能性;行为依赖于特定的`Item`。
:::tip
-For compatibility with other mods,
-we recommend using the capabilities provided by NeoForge in the `Capabilities` class if possible.
-Otherwise, you can create your own as described in this section.
+为了与其他模组兼容,如果可能的话,我们建议使用NeoForge在`Capabilities`类中提供的功能性。否则,您可以按照本节所述创建自己的功能性。
:::
-Creating a capability is a single function call, and the resulting object should be stored in a `static final` field.
-The following parameters must be provided:
-- The name of the capability.
-Creating a capability with the same name multiple times will always return the same object.
-Capabilities with different names are **completely independent**, and can be used for different purposes.
-- The behavior type that is being queried. This is the `T` type parameter.
-- The type for additional context in the query. This is the `C` type parameter.
+创建功能性是单个函数调用,结果对象应该存储在一个`static final`字段中。必须提供以下参数:
+- 功能性的名称。多次创建相同名称的功能性将始终返回相同的对象。不同名称的功能性是**完全独立的**,可以用于不同的目的。
+- 正在查询的行为类型。这是`T`类型参数。
+- 查询中的附加上下文类型。这是`C`类型参数。
-For example, here is how a capability for side-aware block `IItemHandler`s might be declared:
+例如,以下是如何声明侧向感知方块`IItemHandler`的功能性:
```java
public static final BlockCapability ITEM_HANDLER_BLOCK =
BlockCapability.create(
- // Provide a name to uniquely identify the capability.
+ // 提供一个名称以唯一标识功能性。
new ResourceLocation("mymod", "item_handler"),
- // Provide the queried type. Here, we want to look up `IItemHandler` instances.
+ // 提供查询的类型。在这里,我们希望查找`IItemHandler`实例。
IItemHandler.class,
- // Provide the context type. We will allow the query to receive an extra `Direction side` parameter.
+ // 提供上下文类型。我们将允许查询接收额外的`Direction side`参数。
Direction.class);
```
-A `@Nullable Direction` is so common for blocks that there is a dedicated helper:
+对于方块来说,`@Nullable Direction`是如此常见,以至于有一个专门的助手函数:
+
```java
public static final BlockCapability ITEM_HANDLER_BLOCK =
BlockCapability.createSided(
- // Provide a name to uniquely identify the capability.
+ // 提供一个名称以唯一标识功能性。
new ResourceLocation("mymod", "item_handler"),
- // Provide the queried type. Here, we want to look up `IItemHandler` instances.
+ // 提供查询的类型。在这里,我们希望查找`IItemHandler`实例。
IItemHandler.class);
```
-If no context is required, `Void` should be used.
-There is also a dedicated helper for context-less capabilities:
+如果不需要上下文,则应使用`Void`。对于无上下文的功能性也有专门的助手函数:
+
```java
public static final BlockCapability ITEM_HANDLER_NO_CONTEXT =
BlockCapability.createVoid(
- // Provide a name to uniquely identify the capability.
+ // 提供一个名称以唯一标识功能性。
new ResourceLocation("mymod", "item_handler_no_context"),
- // Provide the queried type. Here, we want to look up `IItemHandler` instances.
+ // 提供查询的类型。在这里,我们希望查找`IItemHandler`实例。
IItemHandler.class);
```
-For entities and item stacks, similar methods exist in `EntityCapability` and `ItemCapability` respectively.
+对于实体和物品堆叠,`EntityCapability`和`ItemCapability`分别存在类似的方法。
+
+## 查询功能性
+一旦我们在一个静态字段中拥有了`BlockCapability`、`EntityCapability`或`ItemCapability`对象,我们就可以查询一个功能性。
-## Querying capabilities
-Once we have our `BlockCapability`, `EntityCapability`, or `ItemCapability` object in a static field, we can query a capability.
+对于实体和物品堆叠,我们可以尝试使用`getCapability`找到功能性的实现。如果结果是`null`,则没有可用的实现。
-For entities and item stacks, we can try to find implementations of a capability with `getCapability`.
-If the result is `null`, there no implementation is available.
+例如:
-For example:
```java
var object = entity.getCapability(CAP, context);
if (object != null) {
- // Use object
+ // 使用object
}
```
```java
var object = stack.getCapability(CAP, context);
if (object != null) {
- // Use object
+ // 使用object
}
```
-Block capabilities are used a bit differently because blocks without a block entity can have capabilities as well.
-The query is now performed on a `level`, with the `pos`ition that we are looking for as an additional parameter:
+方块功能性的使用略有不同,因为没有方块实体的方块也可以拥有功能性。现在,查询是在一个`level`上进行的,有一个我们正在寻找的`pos`位置作为附加参数:
+
```java
var object = level.getCapability(CAP, pos, context);
if (object != null) {
- // Use object
+ // 使用object
}
```
-If the block entity and/or the block state is known, they can be passed to save on query time:
+如果已知方块实体和/或方块状态,可以传递它们以节省查询时间:
+
```java
var object = level.getCapability(CAP, pos, blockState, blockEntity, context);
if (object != null) {
- // Use object
+ // 使用object
}
```
-To give a more concrete example, here is how one might query an `IItemHandler` capability for a block, from the `Direction.NORTH` side:
+为了给出一个更具体的示例,以下是如何从`Direction.NORTH`侧查询方块的`IItemHandler`功能性:
+
```java
IItemHandler handler = level.getCapability(Capabilities.ItemHandler.BLOCK, pos, Direction.NORTH);
if (handler != null) {
- // Use the handler for some item-related operation.
+ // 使用handler进行某些物品相关操作。
}
```
-## Block capability caching
-When a capability is looked up, the system will perform the following steps under the hood:
-1. Fetch block entity and block state if they were not supplied.
-2. Fetch registered capability providers. (More on this below).
-3. Iterate the providers and ask them if they can provide the capability.
-4. One of the providers will return a capability instance, potentially allocating a new object.
+当查询某个功能性时,系统会在后台执行以下步骤:
+1. 如果它们没有被提供的话,获取方块实体和方块状态。
+2. 获取注册的功能性提供者。(下文会有更多相关信息)
+3. 遍历提供者并询问他们是否能提供该功能性。
+4. 提供者中的一个将返回功能性实例,可能会分配一个新对象。
-The implementation is rather efficient, but for queries that are performed frequently,
-for example every game tick, these steps can take a significant amount of server time.
-The `BlockCapabilityCache` system provides a dramatic speedup for capabilities that are frequently queried at a given position.
+尽管实现相当高效,但对于频繁进行的查询,例如每个游戏刻,这些步骤可能会占用大量服务器时间。`BlockCapabilityCache` 系统为在特定位置频繁查询的能力提供了巨大的速度提升。
:::tip
-Generally, a `BlockCapabilityCache` will be created once and then stored in a field of the object performing frequent capability queries.
-When and where exactly you store the cache is up to you.
+通常,`BlockCapabilityCache` 会被创建一次,然后存储在执行频繁功能性查询的对象的字段中。何时何地存储缓存取决于您。
:::
-To create a cache, call `BlockCapabilityCache.create` with the capability to query, the level, the position, and the query context.
+要创建缓存,请使用要查询的功能性,级别,位置和查询上下文调用 `BlockCapabilityCache.create`。
```java
-// Declare the field:
+// 声明字段:
private BlockCapabilityCache capCache;
-// Later, for example in `onLoad` for a block entity:
+// 稍后,例如在方块实体的 `onLoad` 中:
this.capCache = BlockCapabilityCache.create(
- Capabilities.ItemHandler.BLOCK, // capability to cache
- level, // level
- pos, // target position
- Direction.NORTH // context
+ Capabilities.ItemHandler.BLOCK, // 要缓存的功能性
+ level, // 世界级别
+ pos, // 目标位置
+ Direction.NORTH // 上下文
);
```
-Querying the cache is then done with `getCapability()`:
+然后通过 `getCapability()` 查询缓存:
```java
IItemHandler handler = this.capCache.getCapability();
if (handler != null) {
- // Use the handler for some item-related operation.
+ // 对某些与物品相关的操作使用 handler。
}
```
-**The cache is automatically cleared by the garbage collector, there is no need to unregister it.**
+**缓存会被垃圾收集器自动清除,无需注销。**
-It is also possible to receive notifications when the capability object changes!
-This includes capabilities changing (`oldHandler != newHandler`), becoming unavailable (`null`) or becoming available again (not `null` anymore).
+也可以接收到功能性对象变更的通知!这包括功能性变化(`oldHandler != newHandler`)、变得不可用(`null`)或再次变得可用(不再是 `null`)。
-The cache then needs to be created with two additional parameters:
-- A validity check, that is used to determine if the cache is still valid.
-In the simplest usage as a block entity field, `() -> !this.isRemoved()` will do.
-- An invalidation listener, that is called when the capability changes.
-This is where you can react to capability changes, removals, or appearances.
+创建缓存时需要两个额外的参数:
+- 一个有效性检查,用于确定缓存是否仍然有效。
+在作为方块实体字段的最简单用法中,`() -> !this.isRemoved()` 就可以了。
+- 一个失效监听器,当功能性改变时被调用。
+这是您可以对功能性变更、移除或出现做出反应的地方。
```java
-// With optional invalidation listener:
+// 带有可选的失效监听器:
this.capCache = BlockCapabilityCache.create(
- Capabilities.ItemHandler.BLOCK, // capability to cache
- level, // level
- pos, // target position
- Direction.NORTH, // context
- () -> !this.isRemoved(), // validity check (because the cache might outlive the object it belongs to)
- () -> onCapInvalidate() // invalidation listener
+ Capabilities.ItemHandler.BLOCK, // 要缓存的功能性
+ level, // 世界级别
+ pos, // 目标位置
+ Direction.NORTH, // 上下文
+ () -> !this.isRemoved(), // 有效性检查(因为缓存可能会比它所属的对象更久存在)
+ () -> onCapInvalidate() // 失效监听器
);
```
-## Block capability invalidation
+## 方块功能性失效
:::info
-Invalidation is exclusive to block capabilities. Entity and item stack capabilities cannot be cached and do not need to be invalidated.
+失效功能是专门针对方块功能性的。实体和物品堆叠的功能性不能被缓存,因此不需要失效处理。
:::
-To make sure that caches can correctly update their stored capability, **modders must call `level.invalidateCapabilities(pos)` whenever a capability changes, appears, or disappears**.
+为了确保缓存可以正确更新它们存储的功能性,**模组开发者必须在功能性改变、出现或消失时调用 `level.invalidateCapabilities(pos)`**。
```java
-// whenever a capability changes, appears, or disappears:
+// 每当一个功能性改变、出现或消失时:
level.invalidateCapabilities(pos);
```
-NeoForge already handles common cases such as chunk load/unloads and block entity creation/removal,
-but other cases need to be handled explicitly by modders.
-For example, modders must invalidate capabilities in the following cases:
-- If a previously returned capability is no longer valid.
-- If a capability-providing block (without a block entity) is placed or changes state, by overriding `onPlace`.
-- If a capability-providing block (without a block entity) is removed, by overriding `onRemove`.
+NeoForge已经处理了常见情况,例如区块的加载/卸载和方块实体的创建/移除,但其他情况需要模组开发者明确处理。例如,模组开发者必须在以下情况中使功能性失效:
+- 如果先前返回的功能性不再有效。
+- 如果放置或状态变化的功能性提供方块(没有方块实体),通过覆写 `onPlace`。
+- 如果移除的功能性提供方块(没有方块实体),通过覆写 `onRemove`。
-For a plain block example, refer to the `ComposterBlock.java` file.
+对于一个简单的方块示例,参考 `ComposterBlock.java` 文件。
-For more information, refer to the javadoc of [`IBlockCapabilityProvider`][block-cap-provider].
+更多信息,请参考 [`IBlockCapabilityProvider`][block-cap-provider] 的 javadoc。
-## Registering capabilities
-A capability _provider_ is what ultimately supplies a capability.
-A capability provider is function that can either return a capability instance, or `null` if it cannot provide the capability.
-Providers are specific to:
-- the given capability that they are providing for, and
-- the block instance, block entity type, entity type, or item instance that they are providing for.
+## 注册功能性
+功能性*提供者*是最终提供功能性的东西。功能性提供者是一个函数,可以返回一个功能性实例,或者如果不能提供功能性,就返回 `null`。提供者特定于:
+- 它们为之提供服务的给定功能性,以及
+- 它们为之提供服务的方块实例、方块实体类型、实体类型或物品实例。
-They need to be registered in the `RegisterCapabilitiesEvent`.
+它们需要在 `RegisterCapabilitiesEvent` 中注册。
-Block providers are registered with `registerBlock`. For example:
+方块提供者使用 `registerBlock` 进行注册。例如:
```java
private static void registerCapabilities(RegisterCapabilitiesEvent event) {
event.registerBlock(
- Capabilities.ItemHandler.BLOCK, // capability to register for
- (level, pos, state, be, side) -> ,
- // blocks to register for
+ Capabilities.ItemHandler.BLOCK, // 注册的功能性
+ (level, pos, state, be, side) -> <返回 IItemHandler>,
+ // 注册的方块
MY_ITEM_HANDLER_BLOCK,
MY_OTHER_ITEM_HANDLER_BLOCK);
}
```
-In general, registration will be specific to some block entity types, so the `registerBlockEntity` helper method is provided as well:
+通常,注册将特定于一些方块实体类型,因此提供了 `registerBlockEntity` 辅助方法:
```java
event.registerBlockEntity(
- Capabilities.ItemHandler.BLOCK, // capability to register for
- MY_BLOCK_ENTITY_TYPE, // block entity type to register for
- (myBlockEntity, side) -> );
+ Capabilities.ItemHandler.BLOCK, // 注册的功能性
+ MY_BLOCK_ENTITY_TYPE, // 注册的方块实体类型
+ (myBlockEntity, side) -> <为 myBlockEntity 和 side 返回 IItemHandler>);
```
-:::danger
-If the capability previously returned by a block or block entity provider is no longer valid,
-**you must invalidate the caches** by calling `level.invalidateCapabilities(pos)`.
-Refer to the [invalidation section][invalidation] above for more information.
-:::
+如果之前由方块或方块实体提供者返回的功能性不再有效,**您必须通过调用 `level.invalidateCapabilities(pos)` 来使缓存失效**。有关更多信息,请参考上文的[失效部分][invalidation]。
-Entity registration is similar, using `registerEntity`:
+实体的注册类似,使用 `registerEntity`:
```java
event.registerEntity(
- Capabilities.ItemHandler.ENTITY, // capability to register for
- MY_ENTITY_TYPE, // entity type to register for
- (myEntity, context) -> );
+ Capabilities.ItemHandler.ENTITY, // 要注册的功能性
+ MY_ENTITY_TYPE, // 要注册的实体类型
+ (myEntity, context) -> <返回 myEntity 的 IItemHandler>);
```
-Item registration is similar too. Note that the provider receives the stack:
+物品的注册也类似。注意,提供者接收堆叠:
```java
event.registerItem(
- Capabilities.ItemHandler.ITEM, // capability to register for
- (itemStack, context) -> ,
- // items to register for
+ Capabilities.ItemHandler.ITEM, // 要注册的功能性
+ (itemStack, context) -> <返回 itemStack 的 IItemHandler>,
+ // 要注册的物品
MY_ITEM,
MY_OTHER_ITEM);
```
-## Registering capabilities for all objects
+## 为所有对象注册功能性
-If for some reason you need to register a provider for all blocks, entities, or items,
-you will need to iterate the corresponding registry and register the provider for each object.
+如果由于某种原因您需要为所有方块、实体或物品注册一个提供者,您将需要遍历相应的注册表并为每个对象注册提供者。
-For example, NeoForge uses this system to register a fluid handler capability for all `BucketItem`s (excluding subclasses):
+例如,NeoForge使用这个系统为所有的 `BucketItem`(不包括子类)注册一个流体处理器功能性:
```java
-// For reference, you can find this code in the `CapabilityHooks` class.
+// 作为参考,您可以在 `CapabilityHooks` 类中找到这段代码。
for (Item item : BuiltInRegistries.ITEM) {
if (item.getClass() == BucketItem.class) {
event.registerItem(Capabilities.FluidHandler.ITEM, (stack, ctx) -> new FluidBucketWrapper(stack), item);
@@ -301,20 +283,17 @@ for (Item item : BuiltInRegistries.ITEM) {
}
```
-Providers are asked for a capability in the order that they are registered.
-Should you want to run before a provider that NeoForge already registers for one of your objects,
-register your `RegisterCapabilitiesEvent` handler with a higher priority.
-For example:
+按照注册的顺序请求提供者提供功能性。如果您想在NeoForge已经为您的某个对象注册的提供者之前运行,请使用更高优先级注册您的 `RegisterCapabilitiesEvent` 处理器。例如:
```java
modBus.addListener(RegisterCapabilitiesEvent.class, event -> {
event.registerItem(
Capabilities.FluidHandler.ITEM,
(stack, ctx) -> new MyCustomFluidBucketWrapper(stack),
- // blocks to register for
+ // 要注册的方块
MY_CUSTOM_BUCKET);
-}, EventPriority.HIGH); // use HIGH priority to register before NeoForge!
+}, EventPriority.HIGH); // 使用 HIGH 优先级在 NeoForge 之前注册!
```
-See [`CapabilityHooks`][capability-hooks] for a list of the providers registered by NeoForge itself.
+查看 [`CapabilityHooks`][capability-hooks] 以获取 NeoForge 本身注册的提供者列表。
[block-cap-provider]: https://github.com/neoforged/NeoForge/blob/1.20.x/src/main/java/net/neoforged/neoforge/capabilities/IBlockCapabilityProvider.java
[capability-hooks]: https://github.com/neoforged/NeoForge/blob/1.20.x/src/main/java/net/neoforged/neoforge/capabilities/CapabilityHooks.java
From b0f05f0548894f8b8746b6560ab23d92fce3a5f4 Mon Sep 17 00:00:00 2001
From: DaZiDian <113085496+DaZiDian@users.noreply.github.com>
Date: Thu, 25 Apr 2024 19:29:57 +0800
Subject: [PATCH 43/87] Update codecs.md
---
docs/datastorage/codecs.md | 323 +++++++++++++++++++------------------
1 file changed, 164 insertions(+), 159 deletions(-)
diff --git a/docs/datastorage/codecs.md b/docs/datastorage/codecs.md
index 0d08b3dd6..4009381bb 100644
--- a/docs/datastorage/codecs.md
+++ b/docs/datastorage/codecs.md
@@ -1,125 +1,126 @@
-# Codecs
+# 编解码器
-Codecs are a serialization tool from Mojang's [DataFixerUpper] used to describe how objects can be transformed between different formats, such as `JsonElement`s for JSON and `Tag`s for NBT.
+编解码器是 Mojang 的 [DataFixerUpper] 库中的一种序列化工具,用于描述对象在不同格式之间的转换方式,如将对象从 `JsonElement` 的 JSON 格式转换为 NBT 的 `Tag` 格式。
-## Using Codecs
+## 使用编解码器
-Codecs are primarily used to encode, or serialize, Java objects to some data format type and decode, or deserialize, formatted data objects back to its associated Java type. This is typically accomplished using `Codec#encodeStart` and `Codec#parse`, respectively.
+编解码器主要用于将 Java 对象编码(或序列化)成某种数据格式,并将格式化的数据对象解码(或反序列化)回其关联的 Java 类型。这通常通过 `Codec#encodeStart` 和 `Codec#parse` 来实现。
-### DynamicOps
+### 动态操作
-To determine what intermediate file format to encode and decode to, both `#encodeStart` and `#parse` require a `DynamicOps` instance to define the data within that format.
+为了确定将数据编码和解码至哪种中间文件格式,`#encodeStart` 和 `#parse` 都需要一个 `DynamicOps` 实例来定义该格式中的数据。
-The [DataFixerUpper] library contains `JsonOps` to codec JSON data stored in [`Gson`'s][gson] `JsonElement` instances. `JsonOps` supports two versions of `JsonElement` serialization: `JsonOps#INSTANCE` which defines a standard JSON file, and `JsonOps#COMPRESSED` which allows data to be compressed into a single string.
+[DataFixerUpper] 库包含了 `JsonOps`,用于对存储在 [`Gson`][gson] 的 `JsonElement` 实例中的 JSON 数据进行编解码。`JsonOps` 支持两种 `JsonElement` 序列化版本:`JsonOps#INSTANCE` 定义了标准的 JSON 文件,而 `JsonOps#COMPRESSED` 允许将数据压缩成单一字符串。
```java
-// Let exampleCodec represent a Codec
-// Let exampleObject be a ExampleJavaObject
-// Let exampleJson be a JsonElement
+// 假设 exampleCodec 代表一个 Codec
+// 假设 exampleObject 为一个 ExampleJavaObject
+// 假设 exampleJson 为一个 JsonElement
-// Encode Java object to regular JsonElement
+// 将 Java 对象编码为常规 JsonElement
exampleCodec.encodeStart(JsonOps.INSTANCE, exampleObject);
-// Encode Java object to compressed JsonElement
+// 将 Java 对象编码为压缩的 JsonElement
exampleCodec.encodeStart(JsonOps.COMPRESSED, exampleObject);
-// Decode JsonElement into Java object
-// Assume JsonElement was parsed normally
+// 将 JsonElement 解码为 Java 对象
+// 假设 JsonElement 是正常解析的
exampleCodec.parse(JsonOps.INSTANCE, exampleJson);
```
-Minecraft also provides `NbtOps` to codec NBT data stored in `Tag` instances. This can be referenced using `NbtOps#INSTANCE`.
+Minecraft 还提供了 `NbtOps` 用于对存储在 `Tag` 实例中的 NBT 数据进行编解码。可以通过 `NbtOps#INSTANCE` 来引用。
```java
-// Let exampleCodec represent a Codec
-// Let exampleObject be a ExampleJavaObject
-// Let exampleNbt be a Tag
+// 假设 exampleCodec 代表一个 Codec
+// 假设 exampleObject 为一个 ExampleJavaObject
+// 假设 exampleNbt 为一个 Tag
-// Encode Java object to Tag
+// 将 Java 对象编码为 Tag
exampleCodec.encodeStart(JsonOps.INSTANCE, exampleObject);
-// Decode Tag into Java object
+// 将 Tag 解码为 Java 对象
exampleCodec.parse(JsonOps.INSTANCE, exampleNbt);
```
-#### Format Conversion
+#### 格式转换
-`DynamicOps` can also be used separately to convert between two different encoded formats. This can be done using `#convertTo` and supplying the `DynamicOps` format and the encoded object to convert.
+`DynamicOps` 还可以单独用来在两种不同的编码格式之间转换。这可以通过使用 `#convertTo` 并提供 `DynamicOps` 格式和要转换的编码对象来完成。
```java
-// Convert Tag to JsonElement
-// Let exampleTag be a Tag
+// 将 Tag 转换为 JsonElement
+// 假设 exampleTag 为一个 Tag
JsonElement convertedJson = NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, exampleTag);
```
-### DataResult
+### 数据结果
-Encoded or decoded data using codecs return a `DataResult` which holds the converted instance or some error data depending on whether the conversion was successful. When the conversion is successful, the `Optional` supplied by `#result` will contain the successfully converted object. If the conversion fails, the `Optional` supplied by `#error` will contain the `PartialResult`, which holds the error message and a partially converted object depending on the codec.
+使用编解码器编码或解码数据时返回的 `DataResult` 将根据转换是否成功,持有转换后的实例或一些错误数据。当转换成功时,由 `#result` 提供的 `Optional` 将包含成功转换的对象。如果转换失败,由 `#error` 提供的 `Optional` 将包含 `PartialResult`,后者持有错误消息和根据编解码器部分转换的对象。
-Additionally, there are many methods on `DataResult` that can be used to transform the result or error into the desired format. For example, `#resultOrPartial` will return an `Optional` containing the result on success, and the partially converted object on failure. The method takes in a string consumer to determine how to report the error message if present.
+此外,`DataResult` 上有许多方法可以用来将结果或错误转换为所需格式。例如,`#resultOrPartial` 将返回一个 `Optional`,在成功时包含结果,在失败时包含部分转换的对象。此方法接受一个字符串消费者以确定如何报告错误消息(如果存在)。
```java
-// Let exampleCodec represent a Codec
-// Let exampleJson be a JsonElement
+// 假设 exampleCodec 代表一个 Codec
+// 假设 exampleJson 为一个 JsonElement
-// Decode JsonElement into Java object
+// 将 JsonElement 解码为 Java 对象
DataResult result = exampleCodec.parse(JsonOps.INSTANCE, exampleJson);
result
- // Get result or partial on error, report error message
- .resultOrPartial(errorMessage -> /* Do something with error message */)
- // If result or partial is present, do something
- .ifPresent(decodedObject -> /* Do something with decoded object */);
-```
+ // 获取结果或部分错误时的错误消息
+ .resultOrPartial(errorMessage -> /* 处理错误消息 */)
+ // 如果结果或部分存在,则进行某些操作
+ .ifPresent(decodedObject
-## Existing Codecs
+ -> /* 处理解码对象 */);
+```
-### Primitives
+## 现有编解码器
-The `Codec` class contains static instances of codecs for certain defined primitives.
+### 原始类型
-Codec | Java Type
-:---: | :---
-`BOOL` | `Boolean`
-`BYTE` | `Byte`
-`SHORT` | `Short`
-`INT` | `Integer`
-`LONG` | `Long`
-`FLOAT` | `Float`
-`DOUBLE` | `Double`
-`STRING` | `String`
-`BYTE_BUFFER` | `ByteBuffer`
-`INT_STREAM` | `IntStream`
-`LONG_STREAM` | `LongStream`
-`PASSTHROUGH` | `Dynamic>`\*
-`EMPTY` | `Unit`\*\*
+`Codec` 类包含了一些定义的原始类型的静态编解码器实例。
-\* `Dynamic` is an object which holds a value encoded in a supported `DynamicOps` format. These are typically used to convert encoded object formats into other encoded object formats.
+| 编解码器 | Java 类型 |
+|------------|--------|
+| `BOOL` | `Boolean` |
+| `BYTE` | `Byte` |
+| `SHORT` | `Short` |
+| `INT` | `Integer` |
+| `LONG` | `Long` |
+| `FLOAT` | `Float` |
+| `DOUBLE` | `Double` |
+| `STRING` | `String` |
+| `BYTE_BUFFER` | `ByteBuffer` |
+| `INT_STREAM` | `IntStream` |
+| `LONG_STREAM` | `LongStream` |
+| `PASSTHROUGH` | `Dynamic>` |
+| `EMPTY` | `Unit` |
-\*\* `Unit` is an object used to represent `null` objects.
+* `Dynamic` 是一个在支持的 `DynamicOps` 格式中编码值的对象。这些通常用于将编码对象格式转换为其他编码对象格式。
+* `Unit` 是用于表示 `null` 对象的对象。
-### Vanilla and Forge
+### 原版和 Forge
-Minecraft and Forge define many codecs for objects that are frequently encoded and decoded. Some examples include `ResourceLocation#CODEC` for `ResourceLocation`s, `ExtraCodecs#INSTANT_ISO8601` for `Instant`s in the `DateTimeFormatter#ISO_INSTANT` format, and `CompoundTag#CODEC` for `CompoundTag`s.
+Minecraft 和 Forge 定义了许多常见对象的编解码器。一些示例包括用于 `ResourceLocation` 的 `ResourceLocation#CODEC`,用于 `DateTimeFormatter#ISO_INSTANT` 格式的 `Instant` 的 `ExtraCodecs#INSTANT_ISO8601`,以及用于 `CompoundTag` 的 `CompoundTag#CODEC`。
-:::caution
-`CompoundTag`s cannot decode lists of numbers from JSON using `JsonOps`. `JsonOps`, when converting, sets a number to its most narrow type. `ListTag`s force a specific type for its data, so numbers with different types (e.g. `64` would be `byte`, `384` would be `short`) will throw an error on conversion.
+:::警告
+使用 `JsonOps` 的 `CompoundTag` 不能从 JSON 解码数字列表。`JsonOps` 在转换时会将数字设置为其最窄类型。`ListTag` 强制其数据使用特定类型,因此不同类型的数字(例如 `64` 会是 `byte`,`384` 会是 `short`)在转换时会引发错误。
:::
-Vanilla and Forge registries also have codecs for the type of object the registry contains (e.g. `Registry#BLOCK` or `ForgeRegistries#BLOCKS` have a `Codec`). `Registry#byNameCodec` and `IForgeRegistry#getCodec` will encode the registry object to their registry name, or an integer identifier if compressed. Vanilla registries also have a `Registry#holderByNameCodec` which encodes to a registry name and decodes to the registry object wrapped in a `Holder`.
+原版和 Forge 注册也有针对注册表所包含对象类型的编解码器(例如 `Registry#BLOCK` 或 `ForgeRegistries#BLOCKS` 有一个 `Codec`)。`Registry#byNameCodec` 和 `IForgeRegistry#getCodec` 会将注册表对象编码为其注册名,或者如果压缩,则为整数标识符。原版注册表还有一个 `Registry#holderByNameCodec`,它将编码为注册名并解码为被 `Holder` 包装的注册表对象。
-## Creating Codecs
+## 创建编解码器
-Codecs can be created for encoding and decoding any object. For understanding purposes, the equivalent encoded JSON will be shown.
+可以为任何对象创建编解码器。为了便于理解,将显示等效的编码 JSON。
-### Records
+### 记录
-Codecs can define objects through the use of records. Each record codec defines any object with explicit named fields. There are many ways to create a record codec, but the simplest is via `RecordCodecBuilder#create`.
+编解码器可以通过使用记录来定义对象。每个记录编解码器定义了具有明确命名字段的任何对象。创建记录编解码器的方法有很多,但最简单的是通过 `RecordCodecBuilder#create`。
-`RecordCodecBuilder#create` takes in a function which defines an `Instance` and returns an application (`App`) of the object. A correlation can be drawn to creating a class *instance* and the constructors used to *apply* the class to the constructed object.
+`RecordCodecBuilder#create` 接受一个函数,该函数定义了一个 `Instance` 并返回一个应用(`App`)到构建对象的对象。这可以与创建类*实例*和用于*应用*类的构造函数联系起来。
```java
-// Some object to create a codec for
+// 一个需要创建编解码器的对象
public class SomeObject {
public SomeObject(String s, int i, boolean b) { /* ... */ }
@@ -132,168 +133,172 @@ public class SomeObject {
}
```
-#### Fields
+#### 字段
+
+`Instance` 可以使用 `#group` 定义多达 16 个字段。每个字段必须是一个定义了对象被制造的实例及对象类型的应用。满足此要求的最简单方式是使用 `Codec`,设置字段的解码名称,并设置用于编码字段的 getter。
-An `Instance` can define up to 16 fields using `#group`. Each field must be an application defining the instance the object is being made for and the type of the object. The simplest way to meet this requirement is by taking a `Codec`, setting the name of the field to decode from, and setting the getter used to encode the field.
+字段可以使用 `#fieldOf` 从 `Codec` 创建,如果字段是必需的,或使用 `#optionalFieldOf` 创建,如果字段被包装在 `Optional` 中或默认存在。任一方法都需要包含编码对象中字段名称的字符串。然后可以使用 `#forGetter` 设置用于编码字段的 getter,它接受一个函数,该函数给定对象,返回字段数据。
-A field can be created from a `Codec` using `#fieldOf`, if the field is required, or `#optionalFieldOf`, if the field is wrapped in an `Optional` or defaulted. Either method requires a string containing the name of the field in the encoded object. The getter used to encode the field can then be set using `#forGetter`, taking in a function which given the object, returns the field data.
+从那里
-From there, the resulting product can be applied via `#apply` to define how the instance should construct the object for the application. For ease of convenience, the grouped fields should be listed in the same order they appear in the constructor such that the function can simply be a constructor method reference.
+,生成的产品可以通过 `#apply` 应用,以定义如何为应用构建对象。为了方便起见,分组字段应按照它们在构造函数中出现的顺序列出,以便函数可以简单地是一个构造函数方法引用。
```java
-public static final Codec RECORD_CODEC = RecordCodecBuilder.create(instance -> // Given an instance
- instance.group( // Define the fields within the instance
- Codec.STRING.fieldOf("s").forGetter(SomeObject::s), // String
- Codec.INT.optionalFieldOf("i", 0).forGetter(SomeObject::i), // Integer, defaults to 0 if field not present
- Codec.BOOL.fieldOf("b").forGetter(SomeObject::b) // Boolean
- ).apply(instance, SomeObject::new) // Define how to create the object
+public static final Codec RECORD_CODEC = RecordCodecBuilder.create(instance -> // 给定一个实例
+ instance.group( // 在实例中定义字段
+ Codec.STRING.fieldOf("s").forGetter(SomeObject::s), // 字符串
+ Codec.INT.optionalFieldOf("i", 0).forGetter(SomeObject::i), // 整数,默认为 0(如果字段不存在)
+ Codec.BOOL.fieldOf("b").forGetter(SomeObject::b) // 布尔
+ ).apply(instance, SomeObject::new) // 定义如何创建对象
);
```
```js
-// Encoded SomeObject
+// 编码后的 SomeObject
{
"s": "value",
"i": 5,
"b": false
}
-// Another encoded SomeObject
+// 另一个编码后的 SomeObject
{
"s": "value2",
- // i is omitted, defaults to 0
+ // i 被省略,默认为 0
"b": true
}
```
-### Transformers
+### 转换器
-Codecs can be transformed into equivalent, or partially equivalent, representations through mapping methods. Each mapping method takes in two functions: one to transform the current type into the new type, and one to transform the new type back to the current type. This is done through the `#xmap` function.
+编解码器可以通过映射方法转换成等效或部分等效的表现形式。每个映射方法接收两个函数:一个用于将当前类型转换为新类型,另一个用于将新类型转换回当前类型。这是通过 `#xmap` 函数完成的。
```java
-// A class
+// 一个类
public class ClassA {
public ClassB toB() { /* ... */ }
}
-// Another equivalent class
+// 另一个等效的类
public class ClassB {
public ClassA toA() { /* ... */ }
}
-// Assume there is some codec A_CODEC
+// 假设存在某个编解码器 A_CODEC
public static final Codec B_CODEC = A_CODEC.xmap(ClassA::toB, ClassB::toA);
```
-If a type is partially equivalent, meaning that there are some restrictions during conversion, there are mapping functions which return a `DataResult` which can be used to return an error state whenever an exception or invalid state is reached.
+如果类型部分等效,即转换过程中存在某些限制,则存在返回 `DataResult` 的映射函数,可用于在遇到异常或无效状态时返回错误状态。
-Is A Fully Equivalent to B | Is B Fully Equivalent to A | Transform Method
-:---: | :---: | :---
-Yes | Yes | `#xmap`
-Yes | No | `#flatComapMap`
-No | Yes | `#comapFlatMap`
-No | No | `#flatXMap`
+是否 A 完全等同于 B | 是否 B 完全等同于 A | 转换方法
+:---: | :---: | :---
+是 | 是 | `#xmap`
+是 | 否 | `#flatComapMap`
+否 | 是 | `#comapFlatMap`
+否 | 否 | `#flatXMap`
```java
-// Given an string codec to convert to a integer
-// Not all strings can become integers (A is not fully equivalent to B)
-// All integers can become strings (B is fully equivalent to A)
+// 给定一个字符串编解码器转换为整数
+// 并非所有字符串都可以变成整数(A 与 B 非完全等效)
+// 所有整数都可以变成字符串(B 与 A 完全等效)
public static final Codec INT_CODEC = Codec.STRING.comapFlatMap(
- s -> { // Return data result containing error on failure
+ s -> { // 返回失败时包含错误的数据结果
try {
return DataResult.success(Integer.valueOf(s));
} catch (NumberFormatException e) {
- return DataResult.error(s + " is not an integer.");
+ return DataResult.error(s + " 不是一个整数。");
}
},
- Integer::toString // Regular function
+ Integer::toString // 常规函数
);
```
```js
-// Will return 5
+// 将返回 5
"5"
-// Will error, not an integer
+// 将错误,不是整数
"value"
```
-#### Range Codecs
+#### 范围编解码器
-Range codecs are an implementation of `#flatXMap` which returns an error `DataResult` if the value is not inclusively between the set minimum and maximum. The value is still provided as a partial result if outside the bounds. There are implementations for integers, floats, and doubles via `#intRange`, `#floatRange`, and `#doubleRange` respectively.
+范围编解码器是 `#flatXMap` 的实现,如果值不在设定的最小值和最大值之间,则返回错误的 `DataResult`。如果值超出范围,仍会提供部分结果。分别有整数、浮点和双精度通过 `#intRange`、`#floatRange` 和 `#doubleRange` 实现。
```java
-public static final Codec RANGE_CODEC = Codec.intRange(0, 4);
+public static final Codec RANGE_CODEC = Codec.intRange(0, 4);
```
```js
-// Will be valid, inside [0, 4]
+// 将有效,在 [0, 4] 内
4
-// Will error, outside [0, 4]
+// 将错误,在 [0, 4] 外
5
```
-### Defaults
+### 默认值
-If the result of encoding or decoding fails, a default value can be supplied instead via `Codec#orElse` or `Codec#orElseGet`.
+如果编码或解码的结果失败,可以通过 `Codec#orElse` 或 `Codec#orElseGet` 提供默认值。
```java
-public static final Codec DEFAULT_CODEC = Codec.INT.orElse(0); // Can also be a supplied value via #orElseGet
+public static final Codec DEFAULT_CODEC = Codec.INT.orElse(0); // 也可以通过 #orElseGet 提供值
```
```js
-// Not an integer, defaults to 0
+// 不是整数,默认为 0
"value"
```
-### Unit
+### 单位
-A codec which supplies an in-code value and encodes to nothing can be represented using `Codec#unit`. This is useful if a codec uses a non-encodable entry within the data object.
+一个编解码器,提供代码中的值并不编码任何东西,可以使用 `Codec#unit` 表示。如果编解码器在数据对象中使用了一个不可编码的条目,这非常有用。
```java
public static final Codec> UNIT_CODEC = Codec.unit(
- () -> ForgeRegistries.BLOCKS // Can also be a raw value
+ () -> ForgeRegistries.BLOCKS // 也可以是原始值
);
```
```js
-// Nothing here, will return block registry codec
+// 这里没有任何内容,将返回方块注册表编解码器
```
-### List
+### 列表
-A codec for a list of objects can be generated from an object codec via `Codec#listOf`.
+可以从对象编解码器生成一个对象列表的编解码器,通过 `Codec#listOf` 实现。
```java
-// BlockPos#CODEC is a Codec
+// BlockPos#CODEC 是一个 Codec
public static final Codec
> LIST_CODEC = BlockPos.CODEC.listOf();
```
```js
-// Encoded List
+// 编码的 List
[
[1, 2, 3], // BlockPos(1, 2, 3)
[4, 5, 6], // BlockPos(4, 5, 6)
[7, 8, 9] // BlockPos(7, 8, 9)
]
-```
+``
+
+`
-List objects decoded using a list codec are stored in an **immutable** list. If a mutable list is needed, a [transformer] should be applied to the list codec.
+使用列表编解码器解码的列表对象存储在一个**不可变**列表中。如果需要可变列表,则应该对列表编解码器应用[变换器]。
-### Map
+### 映射
-A codec for a map of keys and value objects can be generated from two codecs via `Codec#unboundedMap`. Unbounded maps can specify any string-based or string-transformed value to be a key.
+可以通过两个编解码器生成键和值对象映射的编解码器,通过 `Codec#unboundedMap` 实现。无界映射可以指定任何基于字符串的或转换为字符串的值作为键。
```java
-// BlockPos#CODEC is a Codec
+// BlockPos#CODEC 是一个 Codec
public static final Codec