User Tools

Site Tools


zh_cn:tutorial:side

This is an old revision of the document!


侧(Side)

Minecraft 使用 客户端/服务器模型(Client-server model),即用户安装游戏客户端(Client)并连接到服务器(Server)以玩游戏。 Fabric 允许 mod 既可以针对 Minecraft 客户端,也可以同时针对 Minecraft 服务器。

客户端/服务器(client/server)的概念在 Minecraft 中是有二义性的并可能指代物理或逻辑侧。术语客户端/服务器有时用于区分的 Minecraft 的不同发行版(Minecraft 客户端和独立的 Minecraft 服务器)被称为“物理”侧(“physical” sides)。然而,Minecraft 客户端也托管(hosts)着一个自己的内置服务器(integrated server)用于单人和本地局域网游戏,这意味着 Minecraft 客户端也包含了服务器的逻辑。因此,客户端/服务器也可以用来区分的游戏逻辑的不同部分被称为“逻辑”侧(“logical” sides)。

这两种不同类型的侧都有一个“客户端”和一个“服务器”。但逻辑客户端并不等于物理客户端,逻辑服务器也并不等于物理服务器。相反的,逻辑客户端是被托管在(hosted by)物理客户端上的,逻辑服务器也是被托管在物理服务器或物理客户端上的。

逻辑侧是这两个 Minecraft 发行版的体系架构中的重要核心。因此理解逻辑侧对任何使用 Fabric 的 mod 开发都至关重要。

物理侧(Physical Sides)

物理侧或环境是指 Minecraft 游戏的两个发行版(两个 jar 文件):客户端(使用原版启动器启动的)和服务器(可从 https://minecraft.net 免费下载的)。物理侧是指当前环境中可用的代码。

客户端和服务器环境是同一程序的精简发行版,仅包含必需的部分代码。

在 Fabric 中,你经常可以看到诸如 @Environment(EnvType.CLIENT) 之类的注解。这表明某些代码只会在一种环境中存在;这个例子意味着仅在客户端中存在。

在 Fabric 的 fabric.mod.json 和 mixin 配置中,客户端/服务器指代环境。

每个物理侧都附带其入口点(entry point) net.minecraft.data.Main 使用的类和相关的数据生成器类(data generator classes)。

逻辑侧(Logical Sides)

逻辑侧是负责实际游戏逻辑的。 逻辑客户端进行渲染,将玩家输入发送到服务器,处理资源包并部分模拟游戏世界。服务器处理核心游戏逻辑、数据包(data packs)并维护游戏世界的真实状态。

客户端维护服务器世界的部分副本,其中包含例如以下对象的副本:

net.minecraft.world.World
net.minecraft.entity.Entity
net.minecraft.block.entity.BlockEntity

这些复制的对象使客户端和服务器能执行一些常见的游戏逻辑。客户端能够与这些对象进行交互,而服务器则负责保持它们的同步。通常,可以通过访问对象所在世界的 isClient 字段来区分逻辑客户端和逻辑服务端。这可以用来在服务器上执行需要授权的操作,例如生成实体,也用于在客户端上模拟操作。为了避免两个逻辑侧之间的不同步,这样的技术是必需的。

深入了解这些侧

有了之前对这些侧是什么以及如何区分它们的知识,我们现在可以分别深入了解这些侧的细节。

物理客户端(Physical Client)

物理客户端是指由原版启动器下载的 Minecraft jar 文件。它包含一个逻辑客户端和一个逻辑服务器(内置服务器)。它的入口点(entrypoint)是 net.minecraft.client.main.Main

一个物理客户端能够加载多个不同的世界,分别加载在单独的逻辑服务器内,但一次只能加载一个。

相比物理服务器(独立服务器)上的逻辑服务器,物理客户端上的逻辑服务器(内置服务器)能被物理客户端上的逻辑客户端控制(例如 F3 + T 会重新加载数据包(data packs),关闭客户端并同时关闭内置服务器)。它还可以将世界里捆绑的资源包加载到物理客户端上的逻辑客户端。

所有逻辑客户端相关的内容都是物理客户端独占的,所以你会看到在渲染、声音和其他逻辑客户端代码上有许多环境注解。

一些 mod 只针对物理客户端,例如 Liteloader,Optifine 和 Minecraft PvP 客户端(Badlion,Hyperium)。

物理服务器(Physical Server)

物理服务器是指 java 独立服务器。相比物理客户端,它只有一个逻辑服务器(独立服务器)。它的入口点(entrypoint)是 net.minecraft.server.MinecraftServer,且物理服务器在运行期间只能存在一个世界。要切换到另一个世界,就必须重启服务器。

物理服务器上的逻辑服务器与物理客户端上的略有不同,因为当物理服务器运行时只存在一个逻辑服务器实例。此外,物理服务器上的逻辑服务器能通过 Rcon 被远程控制,拥有名为 server.properties 的配置文件,也可以发送服务器资源包。

尽管存在这些差异,大部分 mod 都同时适用于物理客户端上的和物理服务器上的逻辑服务端,只要它们不使用逻辑客户端的内容。

由于它的单一世界和资源包发送特性,原版模组(数据包(data pack)和资源包的组合)的安装在物理服务器上要比在物理客户端上容易得多,因为物理客户端会在连接到服务器时自动进行设置。

一些 mod 只针对物理服务器。例如 Bukkit 及其衍生物(Spigot、Paper、Cauldron、某某-Bukkit 混合产物)始终在物理服务器上运行。

逻辑客户端(Logical Client)

逻辑客户端是玩家的接口。渲染(LWJGL),资源包,处理玩家输入和声音都在逻辑客户端上进行。它在物理服务器上不存在。

逻辑服务器(Logical Server)

逻辑服务器是执行大多数游戏逻辑的地方。数据包(Data packs),世界更新(world updates),方块实体和实体刻(block entity and entity ticks)的处理,怪物 AI,游戏/世界保存以及世界生成都在逻辑服务器上发生。

物理客户端上的逻辑服务器称为“内置服务器”,而物理服务器上的逻辑服务器称为“独立服务器”(这也是物理服务器本身的名称)。

即使在物理服务器上,逻辑服务器也运行在它自己的主线程中并拥有一些工作线程。逻辑服务器的生存周期取决于托管它的物理侧。在物理服务器上,逻辑服务器的生存周期与进程的生存周期一样长。在物理客户端上可以创建多个逻辑服务器,但一次只能存在一个逻辑服务器。当玩家打开本地世界时将创建一个新的逻辑服务器,并在玩家关闭本地世界时将其关闭。

大多数通用 mod 都针对逻辑服务器,因此它们在单人和多人游戏中都能运行。

通信

在逻辑客户端和逻辑服务器之间唯一正确的数据交换方式是交互数据包(packets)。这些数据包(文档在 https://wiki.vg(英文)上)在逻辑客户端和逻辑服务器而不是物理侧之间发送。mod 可以添加数据包(packets)从而在两个逻辑侧之间传输自定义信息。连接自己的内置服务器的逻辑客户端使用内存来交换数据包(packets),其他情况下则通过网络协议来交换。

逻辑客户端发送 C2S(客户端到服务器,Client-To-Server)数据包(packets)到逻辑服务器。 逻辑服务器发送 S2C(服务器到客户端,Server-To-Client)数据包(packets)到逻辑客户端。 数据包(packets)通过网络线程中的 write 方法发送,通过网络线程中的 read 方法调用接收。

关于如何处理网络的更多详细信息,请参见这篇文章(英文)

关于逻辑服务器的常见误解

大多数情况下,针对物理服务器的 mod 也能在物理客户端上的逻辑服务器上运行。

但是,mod 作者时常会抱有一些并不适用于内置服务器的错误假设,包括但不限于:

  • 假设游戏运行时只存在一个逻辑服务器实例
  • 假设任何世界和实体都应该计算游戏逻辑(也就是假设世界对象的 isClient 字段肯定是 false)
  • 假设远程控制,资源包发送和图标(Favicon)一定是可用的

制作在逻辑服务器上运行的 mod 时必须更正这些假设。

结论

可能的物理侧和逻辑侧组合:

逻辑客户端 逻辑服务器
物理客户端 始终存在一个实例 在本地世界中存在;每次打开本地世界都创建新的实例
物理服务器 不存在 始终存在一个实例

最终,主要的困惑来源于物理客户端上存在着逻辑服务器的事实。

zh_cn/tutorial/side.1627646784.txt.gz · Last modified: 2021/07/30 12:06 by nkid00