Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Chinese translation for NeoForged and NeoGradle documentation #18

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/translation/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Translations
============

# Translations of NeoForged Documentation

The following is a list of translated versions of NeoForged Documentation so as to offer a better reading experience for readers in different language regions.

:::caution
Note that the translations may not be 100% appropriate due to the ability limit of translators or untracked updates of original English documentation. If there's trouble during your reading with the content, try refering to the original documentation for solution and any corrects are welcome relating to bridging the translation gaps.

If you have any questions with translated documentation, contact the maintainer of the translation first.
:::

# List of Translations

### [Chinese (Simplified)][zh_CN]
* Maintainer: [src_resources][zh_CN-maintainer]
* Repository: [link][zh_CN-repo]

[zh_CN]: ./zh_CN/index.md
[zh_CN-maintainer]: https://github.com/srcres258
[zh_CN-repo]: https://github.com/srcres258/neo-doc
112 changes: 112 additions & 0 deletions docs/translation/zh_CN/advanced/accesstransformers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
访问转换器
=========

访问转换器(简称AT)允许扩大可见性并修改类、方法和字段的`final`标志。它们允许模组开发者访问和修改其控制之外的类中不可访问的成员。

[规范文档][specs]可以在Minecraft Forge GitHub上查看。

添加AT
------

在你的模组项目中添加一个访问转换器就像在`build.gradle`中添加一行一样简单:

```groovy
// 此代码块也是指定映射版本的位置
minecraft {
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
}
```

添加或修改访问转换器后,必须刷新Gradle项目才能使转换生效。

在开发过程中,AT文件可以位于上面一行指定的任何位置。然而,当在非开发环境中加载时,Forge只会在JAR文件中搜索`META-INF/accesstransformer.cfg`的确切路径。

注释
----

`#`之后直到行尾的所有文本都将被视为注释,不会被解析。

访问修饰符
---------

访问修饰符指定给定目标将转换为什么样的新成员可见性。按可见性降序:

* `public` - 对其包内外的所有类可见
* `protected` - 仅对包内和子类中的类可见
* `default` - 仅对包内的类可见
* `private` - 仅对类内部可见

一个特殊的修饰符`+f`和`-f`可以附加到前面提到的修饰符中,以分别添加或删除`final`修饰符,这可以在应用时防止子类化、方法重写或字段修改。

!!! 警告
指令只修改它们直接引用的方法;任何重写方法都不会进行访问转换。建议确保转换后的方法没有限制可见性的未转换重写,这将导致JVM抛出错误(Error)。

可以安全转换的方法示例有`private`方法、`final`方法(或`final`类中的方法)和`static`方法。

目标和指令
---------

!!! 重要
在Minecraft类上使用访问转换器时,字段和方法必须使用SRG名称。

### 类
转换为目标类:
```
<access modifier> <fully qualified class name>
```
内部类是通过将外部类的完全限定名称和内部类的名称与分隔符`$`组合来表示的。

### 字段
转换为目标字段:
```
<access modifier> <fully qualified class name> <field name>
```

### 方法
目标方法需要一种特殊的语法来表示方法参数和返回类型:
```
<access modifier> <fully qualified class name> <method name>(<parameter types>)<return type>
```

#### 指定类型

也称为“描述符”:有关更多技术细节,请参阅[Java虚拟机规范,SE 8,第4.3.2和4.3.3节][jvmdescriptors]。

* `B` - `byte`,有符号字节
* `C` - `char`,UTF-16 Unicode字符
* `D` - `double`,双精度浮点值
* `F` - `float`,单精度浮点值
* `I` - `integer`,32位整数
* `J` - `long`,64位整数
* `S` - `short`,有符号short
* `Z` - `boolean`,`true`或`false`值
* `[` - 代表数组的一个维度
* 例如:`[[S`指`short[][]`
* `L<class name>;` - 代表一个引用类型
* 例如:`Ljava/lang/String;`指`java.lang.String`引用类型 _(注意左斜杠的使用而非句点)_
* `(` - 代表方法描述符,应在此处提供参数,如果不存在参数,则不提供任何参数
* 例如:`<method>(I)Z`指的是一个需要整数参数并返回布尔值的方法
* `V` - 指示方法不返回值,只能在方法描述符的末尾使用
* 例如:`<method>()V`指的是一个没有参数且不返回任何值的方法

示例
----

```
# 将Crypt中的ByteArrayToKeyFunction接口转换为public
public net.minecraft.util.Crypt$ByteArrayToKeyFunction

# 将MinecraftServer中的'random'转换为protected并移除final修饰符
protected-f net.minecraft.server.MinecraftServer f_129758_ #random

# 将Util中的'makeExecutor'方法转换为public,
# 接受一个String并返回一个ExecutorService
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; #makeExecutor

# 将UUIDUtil中的'leastMostToIntArray'方法转换为public
# 接受两个long参数并返回一个int[]
public net.minecraft.core.UUIDUtil m_235872_(JJ)[I #leastMostToIntArray
```

[specs]: https://github.com/MinecraftForge/AccessTransformers/blob/master/FMLAT.md
[jvmdescriptors]: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2
28 changes: 28 additions & 0 deletions docs/translation/zh_CN/blockentities/ber.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
BlockEntityRenderer
===================

`BlockEntityRenderer`(简称`BER`)用于以静态烘焙模型(JSON、OBJ、B3D等)无法表示的方式渲染方块。方块实体渲染器要求方块具有`BlockEntity`。

创建一个BER
----------

要创建BER,请创建一个继承自`BlockEntityRenderer`的类。它采用一个泛型参数来指定方块的`BlockEntity`类。该泛型参数用于BER的`render`方法。

对于任意一个给定的`BlockEntityType`,仅存在一个BER。因此,特定于存档中单个实例的值应该存储在传递给渲染器的方块实体中,而不是存储在BER本身中。例如,如果将逐帧递增的整数存储在BER中,则对于该存档中该类型的每个方块实体也会逐帧递增。

### `render`

为了渲染方块实体,每帧都调用此方法。

#### 参数
* `blockEntity`: 这是正在渲染的方块实体的实例。
* `partialTick`: 在帧的摩擦过程中,从上一次完整刻度开始经过的时间量。
* `poseStack`: 一个栈,包含偏移到方块实体当前位置的四维矩阵条目。
* `bufferSource`: 能够访问顶点Consumer的渲染缓冲区。
* `combinedLight`: 方块实体上当前亮度值的整数。
* `combinedOverlay`: 设置为方块实体的当前overlay的整数,通常为`OverlayTexture#NO_OVERLAY`或655,360。

注册一个BER
----------

要注册BER,你必须订阅模组事件总线上的`EntityRenderersEvent$RegisterRenderers`事件,并调用`#registerBlockEntityRenderer`。
135 changes: 135 additions & 0 deletions docs/translation/zh_CN/blockentities/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# 方块实体

`BlockEntities`类似于绑定到某一方块的简化的`Entities`。
它们能用于存储动态数据、执行基于游戏刻的任务和动态渲染。
原版Minecraft中的一些例子是处理箱子的物品栏、熔炉的熔炼逻辑或信标的区域效果。
模组中存在更高级的示例,例如采石场(如BC)、分拣机(如IC2)、管道(如BC)和显示器(如OC)。(括号内容为译者注。)

!!! 注意
`BlockEntities`并不是万能的解决方案,如果使用错误,它们可能会导致游戏卡顿。
如果可能的话,尽量避免使用。

## 注册

方块实体是动态创建和删除的,因此它们本身不是注册表对象。

为了创建`BlockEntity`,你需要继承`BlockEntity`类。这样,另一个对象被替代性地注册以方便创建和引用动态对象的*类型*。对于`BlockEntity`,这些对象被称为`BlockEntityType`。

`BlockEntityType`可以像任何其他注册表对象一样进行[注册][registration]。若要构造`BlockEntityType`,可以通过`BlockEntityType$Builder#of`使用其Builder形式。这需要两个参数:`BlockEntityType$BlockEntitySupplier`,它接受`BlockPos`和`BlockState`来创建关联`BlockEntity`的新实例,以及该`BlockEntity`可以附加到的`Block`的可变参数。构建该`BlockEntityType`是通过调用`BlockEntityType$Builder#build`来完成的。其接受一个`Type`,表示用于引用某个`DataFixer`中的此注册表对象的类型安全引用。由于`DataFixer`是用于模组的可选系统,因此其也可用`null`代替。

```java
// 对于某个类型为DeferredRegister<BlockEntityType<?>>的REGISTER
public static final RegistryObject<BlockEntityType<MyBE>> MY_BE = REGISTER.register("mybe", () -> BlockEntityType.Builder.of(MyBE::new, validBlocks).build(null));

// 在MyBE(一个BlockEntity的子类)中
public MyBE(BlockPos pos, BlockState state) {
super(MY_BE.get(), pos, state);
}
```

## 创建一个`BlockEntity`

要创建`BlockEntity`并将其附加到`Block`,`EntityBlock`接口必须在你的`Block`子类上实现。方法`EntityBlock#newBlockEntity(BlockPos, BlockState)`必须实现并返回一个你的`BlockEntity`的新实例。

## 将数据存储到你的`BlockEntity`

为了保存数据,请重写以下两个方法:
```java
BlockEntity#saveAdditional(CompoundTag tag)

BlockEntity#load(CompoundTag tag)
```
每当包含`BlockEntity`的`LevelChunk`从标签加载/保存到标签时,都会调用这些方法。
使用它们以读取和写入你的方块实体类的字段。

!!! 注意
每当你的数据发生改变时,你需要调用`BlockEntity#setChanged`;否则,保存存档时可能会跳过包含你的`BlockEntity`的`LevelChunk`。

!!! 重要
调用`super`方法非常重要!

标签名称`id`、`x`、`y`、`z`、`ForgeData`和`ForgeCaps`均由`super`方法保留。

## 计时的`BlockEntity`

如果你需要一个计时的`BlockEntity`,例如为了跟踪冶炼过程中的进度,则必须在`EntityBlock`中实现并重写另一个方法:`EntityBlock#getTicker(Level, BlockState, BlockEntityType)`。这可以根据用户所处的逻辑端实现不同的计时器,或者只实现一个通用计时器。无论哪种情况,都必须返回`BlockEntityTicker`。由于这是一个功能性的接口,因此它可以转而采用一个表示计时器的方法:

```java
// 在某个Block子类内
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
return type == MyBlockEntityTypes.MYBE.get() ? MyBlockEntity::tick : null;
}

// 在MyBlockEntity内
public static void tick(Level level, BlockPos pos, BlockState state, MyBlockEntity blockEntity) {
// 处理一些事情
}
```

!!! 注意
这个方法在每个游戏刻都会调用;因此,你应该避免在这里进行复杂的计算。如果可能的话,你应该每X个游戏刻进行更复杂的计算。(一秒钟内的游戏刻数量可能低于20(二十),但不会更高)

## 向客户端同步数据

有三种方法可以将数据同步到客户端:在区块加载时同步、在方块更新时同步以及使用自定义网络消息同步。

### 在LevelChunk加载时同步

为此你需要重写
```java
BlockEntity#getUpdateTag()

IForgeBlockEntity#handleUpdateTag(CompoundTag tag)
```
同样,这非常简单,第一个方法收集应该发送到客户端的数据,而第二个方法处理这些数据。如果你的`BlockEntity`不包含太多数据,你可以使用[将数据存储到你的`BlockEntity`][storing-data]小节之外的方法。

!!! 重要
为方块实体同步过多/无用的数据可能会导致网络拥塞。你应该通过在客户端需要时仅发送客户端需要的信息来优化网络使用。例如,在更新标签中发送方块实体的物品栏通常是没有必要的,因为这可以通过其[`AbstractContainerMenu`][menu]进行同步。

### 在方块更新时同步

这个方法有点复杂,但同样,你只需要重写两个或三个方法。
下面是它的一个简易的实现示例:
```java
@Override
public CompoundTag getUpdateTag() {
CompoundTag tag = new CompoundTag();
//将你的数据写入标签
return tag;
}

@Override
public Packet<ClientGamePacketListener> getUpdatePacket() {
// 将从#getUpdateTag得到标签
return ClientboundBlockEntityDataPacket.create(this);
}

// 可以重写IForgeBlockEntity#onDataPacket。默认地,其将遵从#load。
```
静态构造器`ClientboundBlockEntityDataPacket#create`接受:

* 该`BlockEntity`。
* 从该`BlockEntity`中获取`CompoundTag`的可选函数。默认情况下,其使用`BlockEntity#getUpdateTag`。

现在,要发送数据包,必须在服务端上发出更新通知。
```java
Level#sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags)
```
`pos`应为你的`BlockEntity`的位置。
对于`oldState`和`newState`,你可以传递那个位置的`BlockState`。
`flags`是一个应含有`2`的位掩码(bitmask),其将向客户端同步数据。有关更多信息以及flags的其余信息,参见`Block`。flag `2`与`Block#UPDATE_CLIENTS`相同。

### 使用自定义网络消息同步

这种同步方式可能是最复杂的,但通常是最优化的,因为你可以确保只有需要同步的数据才是真正同步的。在尝试之前,你应该先查看[`Networking`][networking]部分,尤其是[`SimpleImpl`][simple_impl]。一旦你创建了自定义网络消息,你就可以使用`SimpleChannel#send(PacketDistributor$PacketTarget, MSG)`将其发送给所有加载了该`BlockEntity`的用户。

!!! 警告
进行安全检查很重要,当消息到达玩家时,`BlockEntity`可能已经被销毁/替换!你还应该检查区块是否已加载(`Level#hasChunkAt(BlockPos)`)。

[registration]: ../concepts/registries.md#methods-for-registering
[storing-data]: #storing-data-within-your-blockentity
[menu]: ../gui/menus.md
[networking]: ../networking/index.md
[simple_impl]: ../networking/simpleimpl.md
49 changes: 49 additions & 0 deletions docs/translation/zh_CN/blocks/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
方块
====

显然,方块是Minecraft世界的关键。它们构成了所有的地形、结构和机器。如果你有兴趣制作一个模组,那么你必然可能会想添加一些方块。本页将指导你创建方块,以及你可以使用它们做的一些事情。

创建一个方块
-----------

### 基础方块

对于不需要特殊功能的简单方块(比如圆石、木板等),不必自定义一个类。你可以通过使用`BlockBehaviour$Properties`对象实例化`Block`类来创建一个方块。该`BlockBehaviour$Properties`对象可以调用`BlockBehaviour$Properties#of`创建,并且可以通过调用其方法进行自定义。例如:

- `strength` - 硬度控制着断块所需的时间。它是一个任意值。作为参考,石头的硬度为1.5,泥土的硬度为0.5。如果该方块不能被破坏,则应使用-1.0的硬度,`Blocks#BEDROCK`的定义是一个例子。抗性控制块的防爆性。作为参考,石头的抗性为6.0,泥土的抗性为0.5。
- `sound` - 控制方块在点击、破坏或放置时发出的音效。其需要一个`SoundType`参数,请参阅[音效][sounds]页面了解更多详细信息。
- `lightLevel` - 控制方块的亮度。其接受一个带有`BlockState`参数的函数,该函数返回从0到15的某一个值。
- `friction` - 控制方块的动摩擦系数。作为参考,冰的动摩擦系数为0.98。

所有这些方法都是*可链接*的,这意味着你可以串联地调用它们。有关此方面的示例,请参见`Blocks`类。

!!! 注意
`CreativeModeTab`未针对方块定义setter。如果方块有与之关联的物品(例如`BlockItem`),则由[`BuildCreativeModeTabContentsEvent`][creativetabs]处理。此外,也没有针对翻译键的setter,因为它是通过`Block#getDescriptionId`从注册表名称生成的。

### 进阶方块

当然,上面只允许创建非常基本的方块。如果你想添加一些功能,比如玩家交互,那么需要一个自定义的方块类。然而,`Block`类有很多方法,并且不幸的是,并不是每一个方法都能在这里用文档完全表述。请参阅本节中的其余页面,以了解你可以对方块进行的操作。

注册一个方块
-----------

方块必须经过[注册][registering]后才能发挥作用。

!!! 重要
存档中的方块和物品栏中的“方块”是非常不同的东西。存档中的方块由`BlockState`表示,其行为由一个`Block`类的实例定义。同时,物品栏中的物品是由`Item`控制的`ItemStack`。作为`Block`和`Item`二者之间的桥梁,有一个`BlockItem`类。`BlockItem`是`Item`的一个子类,它有一个字段`block`,其中包含对它所代表的`Block`的引用。`BlockItem`将“方块”的一些行为定义为物品,例如右键单击如何放置方块。存在一个没有其`BlockItem`的`Block`也是可能的。(例如`minecraft:water`是一个方块,但不是一个物品。因此,不可能将其作为一个物品保存在物品栏中。)

当一个方块被注册时,也*仅仅*意味着一个方块被注册了。该方块不会自动具有`BlockItem`。要为块创建基本的`BlockItem`,应该将`BlockItem`的注册表名称设置为其`Block`的注册表名称。`BlockItem`的自定义子类也可以使用。一旦为方块注册了`BlockItem`,就可以使用`Block#asItem`来获取它。如果该方块没有`BlockItem`,`Block#asItem`将返回`Items#AIR`,因此,如果你不确定你正在使用的方块是否有`BlockItem`,请检查其`Block#asItem`是否返回`Items#AIR`。

#### 选择性地注册方块

在过去,有一些模组允许用户在配置文件中禁用方块/物品。但是,你不应该这样做。允许注册的方块数量没有限制,所以请在你的模组中注册所有方块!如果你想通过配置文件禁用一个方块,你应该禁用其配方。如果要禁用创造模式物品栏中的方块,请在[`BuildCreativeModeTabContentsEvent`][creativetabs]中构建内容时使用`FeatureFlag`。

延伸阅读
-------

有关方块属性的信息,例如用于栅栏、墙等原版方块的属性,请参见[方块状态][blockstates]部分。

[sounds]: ../gameeffects/sounds.md
[creativetabs]: ../items/index.md#creative-tabs
[registering]: ../concepts/registries.md#methods-for-registering
[blockstates]: states.md
Loading