Minecraft 是一款自由度非常高的游戏。但是,其联机(或多人游戏)功能却依赖于局域网。本来,同学到家里玩,利用家里的 WiFi 进行联机是非常正常且愉快的事情,但是如今,大家任务繁重,去朋友家里,或者邀请朋友成为成为非常不现实的事情。

于是,远程联机,成了一代又一代人追求的目标。

有目标,必定有实现。确实,对于手机端的 Minecraft,市面上已经出现了很多的远程联机平台。然而,适用于 PC 端的联机平台却姗姗来迟,并且许多限制使得无法定制多人游戏体验。原因很简单,Java 版 Minecraft 拥有 mod 和许多种很可能互不兼容的游戏版本,其情形比手机版复杂许多。

但是这样的理由并不能打消我们在 PC 端联机的念头。

本文介绍的就是在 PC 端远程联机的方法。

本文所有操作均在 Windows 下的非正版的国际版 Minecraft 上进行。如果你使用的是中国版 Minecraft,请迅速撤离;如果你使用 Linux 或 Mac 等系统,请根据你的常识替换掉教程中的一些 Windows 命令行。学习本教程需要一定的计算机问题排查能力(至少要会重启电脑解决问题吧)。

注意:本文估计的时间为大约值,非准确值。估计的时间假设读者聚精会神地阅读,并且不偷懒。

有效性核查日期:2020年9月30日

需要阅读的部分

如果你好奇怎么进行联机

预计通读时间:16分钟
预计实践时间:59分钟

如果你对联机完全不了解,请阅读并实践整篇文章(最好能叫上好友)。

如果你不想废话

预计通读时间:6分钟
预计实践时间:20分钟

本文标题中的“远程联机”包括“联机”“远程”两部分。

如果你已经知道如何搭建独立服务端(或不想知道)以及如何进行局域网联机,请跳过下面几节,从“局域网限制的来历和新的解决方法”开始。

如果你是房主

预计通读时间:16分钟
预计实践时间:59分钟

请阅读并实践整篇文章,以在其他玩家出现问题时给予帮助。

如果你不是房主

预计通读时间:7分钟(以测量为依据)
预计实践时间:18分钟(以测量为依据)

如果你不是房主,并且房主通过阅读这篇教程搭建了多人联机世界,而你想要加入,那么请看下面。

你需要有这些东西:

  • 房主提供的 ZeroTier One 网络 ID。b6079f73d63c95f3
  • 房主提供的,虚拟局域网下的,自己的 IP 地址。 10.241.179.124
  • 房主提供的,自己的游戏端口。
  • 房主说的,关于自己的服务器是否开启外置登录的信息。

请阅读以下部分:

  • 操作流程(位于文章末尾)
  • 如果房主开启外置登录,阅读 使用一个物理服务端 -> 使用外置登录模块 -> 在客户端配置。
  • 如果你之前没有加入过房主的网络,或者房主改用了另外一个网络,阅读 使用 VLAN 实现远程联机 -> 软件选择 和 使用 VLAN 实现远程联机 -> 准备工作 -> 加入VLAN网络。
  • 如果你不清楚该怎么通过 IP 地址和游戏端口加入服务器,阅读 使用 VLAN 实现远程联机 -> Van 游戏 -> 加入游戏。

局域网联机与“游戏终端”的概念

预计通读时间:2分钟
预计实践时间:9分钟(假设游戏启动耗费的时间为40秒)

如果仅仅需要在局域网内进行联机,我们一般会选择“对局域网开放”。

然后我们会运行 ipconfig(查看本机IP信息),随后把自己的 IP 地址和端口号一起交给基友。

C:\Users\【数据删除】>ipconfig

Windows IP 配置


以太网适配器 以太网:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . :

以太网适配器 nMatrix Virtual Network:

   【数据删除】

无线局域网适配器 本地连接* 3:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . :

无线局域网适配器 本地连接* 12:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . :

以太网适配器 VMware Network Adapter VMnet1:

   【数据删除】

以太网适配器 VMware Network Adapter VMnet8:

   【数据删除】

以太网适配器 ZeroTier One [【数据删除】]:

   【数据删除】

以太网适配器 蓝牙网络连接:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . :

无线局域网适配器 WLAN:

   连接特定的 DNS 后缀 . . . . . . . :
   IPv4 地址 . . . . . . . . . . . . : 192.168.1.124     <-- WiFi IP 地址
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : 192.168.1.1

隧道适配器 Teredo Tunneling Pseudo-Interface:

   【数据删除】

随后,基友根据你的信息,使用“多人游戏”功能对你进行连接。

OK。现在我们尝试探究本质,用图示表示基友的电脑与你电脑的关系。

我们把主持游戏的称作“服务器”,参与游戏的称为“客户端”,用箭头表示客户端对服务器的连接,那么,关系是这样的:

然而,不得不承认的是,此时你也在加入自己的游戏。

所以,事情实际上是这样的。我们玩的 Minecraft 通常被称为“Minecraft 客户端”。为了防止搞晕,我们用一个更加清晰的名字表示这个“客户端”,即物理客户端 (Physical Client)。与其对应的,还有一种软件,叫作“Minecraft 服务端”。我们称之为物理服务端 (Physical Server)

而实际联机时,你自己加入了自己的游戏。因此,如果把主持游戏的组件称作“服务器”,参与游戏的组件称为“客户端”,我们还将物理客户端划分为逻辑服务端 (Logical Server)逻辑客户端 (Logical Client)。对应地,物理服务端仅仅包含一个逻辑服务端,因为它只能用于主持游戏,而不能参与游戏。

所以联机时的关系实际是这样:

而单人游戏时,实质上是你的逻辑客户端在参与逻辑服务端主持的游戏。

至此,为了阐述单人游戏和联机的本质,我们引入了以下的概念:

  • 物理客户端 (Physical Client)
  • 物理服务端 (Physical Server)
  • 逻辑服务端 (Logical Server)
  • 逻辑客户端 (Logical Client)

我们将这些概念统称为游戏终端 (Sides)

使用一个物理服务端

预计通读时间:6分钟
预计实践时间:32分钟(“外置登录”部分计算在内)

在开始之前,我建议先学会使用物理服务端

物理服务端中包含的逻辑服务端相较于物理客户端中包含的逻辑服务端(即,对局域网开放)有以下的好处:

  • 能够在房主不在线时仍然保持开启。
    实际上,在物理服务端中没有房主的概念。
  • 允许房主或管理员在发现有人捣乱时,封禁或踢出用户。
  • 允许添加外置的“正版登录”模块(如 LittleSkin)。使用这个模块,可以大大提高多人游戏安全性,同时规避绝大多数技术问题。
  • 允许房主和管理员随时任命或撤销管理员。
    房主和管理员没有本质区别。唯一区别在于,服务端开在房主的电脑上或房主掌握的公网服务器上。
  • 允许自定义人数限制,但是必须根据电脑配置量力而行。
  • 可以拥有固定端口(即,服务器地址可以是一个固定的值)。

为什么这些重要?举个例子,远程联机时,如果你发现朋友在搞破坏,而又不想打断游戏的进行,那么使用封禁或踢出是很好的选择(因为你不能武力解决)。

注:已经验证,1.16.1 版本搭建带 mod 服务端的过程与 1.12.2 相同。

既然重要,我们就要学习搭建服务端了。你需要准备以下内容(以 Minecraft 1.12.2,带 mod 为例):

  • Minecraft 1.12.2 物理客户端
  • Minecraft 1.12.2 纯净服务端(通常叫做 minecraft_server.1.12.2.jar
  • Forge EXE 安装程序(用于加载 MOD),在这里可以找到。(英语完全看不懂的劝退)

按照常规,你的朋友也需要有 1.12.2 的 物理客户端

我们仍然假设在局域网下联机,因为 物理服务端 本身也仅支持局域网联机。

系统需求

游戏刻:游戏逻辑以循环的方式运行,一个循环被称为一个游戏刻

服务端延迟(TPS延迟):按程序逻辑,每秒应该执行 20 个游戏刻,也就是,处理每个游戏刻至多使用 50ms 的时间。但是,如果搭载服务端的计算机处理能力不足,使得处理某个游戏刻的时间超过了 50ms,就会使某一秒的刻数低于 20,这种情况被称为服务端延迟。出现这种情况时,由于逻辑客户端仍然正常运作(且不卡顿),玩家将会看到周围的其他生物、玩家静止不动,且挖掘方块后不掉落物品等现象,但自己仍然可以移动。如果某一刻处理时间极长(例如 41s),玩家就会在延迟结束后被传送回原来位置,并且挖掘的方块都恢复原状,因为延迟之大使得服务端已经没有能力跟踪客户端的行为。若出现一刻处理时长超过“刻时长限制”(默认 60s),服务端将崩溃。

服务端对内存与处理器的要求较高。在单人游戏或自己主持的局域网游戏中,由于逻辑服务端和逻辑客户端均在物理客户端中,她们可以利用特殊的机制进行协调,使得玩家难以感受到服务端延迟。然而,使用物理服务端时,逻辑服务端与逻辑客户端分离,延迟问题也就原形毕露了。

按 2020 年的习惯,中配机才能使服务器“可玩”,而高配机才能将延迟降到可以忽略的程度。如果要完全消除延迟,则需使用固态硬盘(也可以使用 PrimoCache 等软件加速机械硬盘,但是这种做法内存与 CPU 开销较大,且需要另一个固态硬盘或缓存盘作为缓存)。

供参考的测试结果(仅供参考):

警告:实验没有采用科学探究方法,测量也可能不准确。请不要将其作为选购电脑的指导文件。

项目 机器0 机器1 机器2 机器2.5 机器3 机器3.5
基本信息
形态 台式 笔记本 笔记本 笔记本 笔记本 笔记本
制造年份 很久以前 2014 2017 2017 2020 2020
配置
处理器 不明古董 i7-4920HQ i5-7200U i5-7200U i7-1065G7 i7-1065G7
核心数 2 4 2 2 4 4
基准速度/GHz 不明 2.59 2.50 2.50 1.80 1.80
机带内存/GB 4 8 8 12 16 16
分配内存/MB 512 1536 1904 2560 3072 3072
硬盘类型 古董 机械 机械 机械 机械 NVMe 固态
硬盘容量/TB 0.25 1 0.5 1 1 0.5
服务端
版本 1.8.8 1.12.2 1.15.2 1.15.2 1.16.1 1.16.1
类型 V Forge Forge Forge Forge Forge
模组程度/KT[1] 0 73 0.03 0.03 0.02 0.02
外置登录
运行环境 Oracle Oracle OpenJ9 OpenJ9 OpenJ9 OpenJ9
服务端配置
刻时长限制 90 90 90 90 90 90
渲染距离 10 10 10 10 12 12
大致性能
启动时间/s[2] 24 142 68 56 46 41
初次加入后延迟/s >90 5 49 41 2 0
TNT测试存活/s[3] - 215 108 127
理论核载(合作小组型) 0 14 5 5 50 65
理论核载(分头行动型) 0 11 3 3 30 38

注1 模组程度:用模组(不包括原版)所含的模型数与材质数之和大致反映安装模组的多少。单位 KT(KiloTexture)表示 1000 个材质或模型。

注2 启动时间:启动时间没有参考意义,因为 Forge 不同版本的启动时间差异悬殊。

注3 TNT测试存活:将种子为 North Carolina 的普通世界中的 (0,0) 区块填满 TNT 并立刻从顶部点燃,然后测量服务器崩溃前存活的时间。

提示:如果电脑不能满足在运行服务端的同时游玩,则可以将服务端安装在另一台电脑上,并对其进行连接。管理另一台电脑可以采用远程桌面的方式(这要求拥有 Windows 10 专业版)。

内存分配

考虑内存分配时,应按照“最大内存量”计算内存的占用。

内存分配的一般要求如下:

  • 分配内存大小应当为 4MB 的倍数。
  • 对服务端分配的内存量应当至少为 2048M。如果需要搭载较多玩家或玩家经常分头行动,则需要 3072M。
    • 服务端分配内存太小将导致严重卡顿(刻速率可降至 3tick/s),严重者则导致崩溃。
  • 条件允许者应当保留 2GB 空闲内存,防止系统进行内存交换(这对CPU和硬盘的占用很大)。
  • 对于原版客户端,分配 1024MB~1536MB。带模组或高清材质的则需要 1536MB~4096MB 不等。
    • 必须使得在游戏内重新加载资源包时不发生死机或崩溃。
    • 必须使得游戏一段时间后游戏占用分配内存的比率不大于 85%。
  • 除去刻意保留的 2GB 外,若条件允许,预留至少 1.5GB 的空闲内存,以备不时之需。

示例如下:

16GB

12GB

8GB

4GB

下载资料

下载上述的资料。

物理客户端 一般你已经有了(建议使用 HMCL)。

纯净服务器 可以直接在网上搜索 “minecraft_server.1.12.2.jar download”。在 1.14.4 版本之后,Forge 安装程序会自动选择正确的服务端并安装。如果需要手动下载,请参阅 中文 Minecraft Wiki: 1.12.2。你可以通过该站点中的链接找到其他版本。

Forge 在你进入网站后,在左侧选择游戏版本,然后根据你客户端上用的 Forge 版本选择下载(下载时应当选择 Installer 或 Windows Installer)。

Forge 版本需和客户端一致。

另外,如果你需要外置登录,你可以了解 LittleSkin 提供的登录接口。稍后将会介绍这个内容。

开始搭建

1 为服务端专门建立文件夹。将 Forge 安装程序 和 minecraft_server.1.12.2.jar 放到这里(如果是 1.14.4 或更新版本,可以不用将服务端 jar 文件放在此处)。

2 运行安装程序。选择“Install server”,然后再选中刚才建立的文件夹。

3 点击“确定”。根据实际情况不同,中途可能会失败。如果失败频繁而稳定地发生,说明你需要使用珂学上网。

(MC1.13 版本之后,安装器界面略有不同)

4 在文件夹下新建 Launch.bat。如果不知道应该怎样新建批处理文件,劝退(学习“Windows 显示文件扩展名”)。粘贴以下内容。

(批处理仅适用于 Windows。Linux 或 Mac 系统的用户应当使用自己的方式编写一份启动程序)

@echo off
title Server : ready
echo 当前时间:%time%
echo ==================我的世界服务器===================
echo             注意:结束时输入stop存档
echo             否则可能会丢失存档内容
echo             PS:地图备份了吗?
echo ==================================================
echo 就绪
pause
cls
title Server : running
echo 当前时间:%time%
echo =================服务器即将启动=================
java -Xmx{最大内存量}M -jar {forge-...}.jar nogui
echo =================服务器运行结束=================
title Server : stopped
pause

按照你的个人情况修改文件。

  • {最大内存量}:同游戏中的“最大内存量”“分配内存”。个人替换为 3584
  • {forge-...}:形如 forge-xxx.jar 的文件的文件名。根据此处的示例,替换为 forge-1.12.2-14.23.5.2847-universal

需要注意的是,Windows 系统通常默认 GBK 编码。保存时,编码要选择 GBK 或 ANSI,否则会乱码(例外:Windows 10 中若开启了实验性 Unicode 支持,则此时必须使用 UTF-8 编码保存)。

5 运行 Launch.bat。预期:服务器启动失败。

当前时间: 6:06:21.98
=================服务器即将启动=================
[authlib-injector.launch] [INFO] Version: 1.1.26-41a7a47
[authlib-injector.config] [INFO] API root: https://mcskin.littleservice.cn/api/yggdrasil/
[06:06:32] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLServerTweaker
[06:06:32] [main/INFO] [LaunchWrapper]: Using primary tweak class name net.minecraftforge.fml.common.launcher.FMLServerTweaker
[06:06:32] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLServerTweaker
[06:06:32] [main/INFO] [FML]: Forge Mod Loader version 14.23.5.2847 for Minecraft 1.12.2 loading
[06:06:32] [main/INFO] [FML]: Java is Java HotSpot(TM) 64-Bit Server VM, version 1.8.0_221, running on Windows 10:amd64:10.0, installed at C:\Program Files\Java\jre1.8.0_221
[06:06:32] [main/WARN] [FML]: The coremod FMLCorePlugin (net.minecraftforge.fml.relauncher.FMLCorePlugin) is not signed!
[06:06:32] [main/WARN] [FML]: The coremod FMLForgePlugin (net.minecraftforge.classloading.FMLForgePlugin) is not signed!
[06:06:32] [main/INFO] [FML]: Searching D:\Minecraft Profile\servers\1.12.2 Demo-Server\.\mods for mods
[06:06:32] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker
[06:06:32] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLDeobfTweaker
[06:06:32] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker
[06:06:32] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker
[06:06:32] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.relauncher.CoreModManager$FMLPluginWrapper
[06:06:35] [main/ERROR] [FML]: FML appears to be missing any signature data. This is not a good thing
[06:06:36] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.relauncher.CoreModManager$FMLPluginWrapper
[06:06:36] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLDeobfTweaker
[06:06:36] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.TerminalTweaker
[06:06:36] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.TerminalTweaker
[06:06:37] [main/INFO] [LaunchWrapper]: Launching wrapped minecraft {net.minecraft.server.MinecraftServer}
[06:06:37] [main/WARN] [minecraft/ServerEula]: Failed to load eula.txt
[06:06:37] [main/INFO] [minecraft/MinecraftServer]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.
=================服务器运行结束=================
请按任意键继续. . .

请不要试图核对错误信息。错误信息通常大异小同。

6 文件夹下会出现 eula.txt。这是许可协议。要表示同意许可协议,要在下面修改 eula=true

#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).
#Wed Nov 27 06:06:37 CST 2019
eula=true

7 将需要的 mod 放到 mods 文件夹中(尽量去掉所有仅在逻辑客户端上有效的 mod)

正规 mod 发布网站上的作者/搬运者一般对于仅在逻辑客户端上有效的 mod 会注明“仅客户端 / Client side only”“服务端无效 / Will not work on servers”“服务端上会崩溃 / Will crash on servers” 或 side client。因此建议前往正规的发布网站(CurseForge 或 mcmod.cn)下载 mod。

需保证客户端和服务端的 mod 相同(客户端工具类除外)。

8 根据需要编辑 server.properties。下面是细节(不确定就别改):

对于 true/false 变量,true 相当于 yes,false 相当于 no。

#Minecraft server properties
#Fri Nov 29 05:57:17 CST 2019

# 地图生成器设置(用于超平坦、自定义、自选等世界类型)
generator-settings=
# 管理员默认权限级别。如果是远程联机(不能武力解决冲突时)建议设置为 2。
op-permission-level=4
# 地图的相对路径。
# 建议将地图存于 world 文件夹下,而不是直接用 world 存储地图。如果地图不存在会生成一个。
level-name=world/test-world
# 允许玩家使用作弊插件在生存、冒险模式下飞行,或利用“方块跳跃”漏洞到达高处。(某些模组下使用该选项可能造成问题)
allow-flight=true
# 防止玩家通过代理(专指 Minecraft 代理)连接服务器
prevent-proxy-connections=false
# 游戏端口。玩家连接的地址 'xxx.xxx.xxx.xxx:xxxxx' 的冒号后面部分。
# 可以自定义
# 原则上建议使用大于等于 2048 的端口。建议使用 25565 或 23333 以及它们后面的几个。
server-port=23334
# 地图类型(DEFAULT、AMPLIFIED ...)
level-type=DEFAULT
# 地图种子(如果你是将一个原有的地图移到服务器上,请勿设置)
level-seed=
# 强制设置游戏模式
force-gamemode=false
# 服务器监听IP。
# 仅仅利用服务器进行单人游戏时,设置 ::1(即 127.0.0.1),否则设置 ::(即 0.0.0.0)
server-ip=::
# 数据压缩限度。如果数据包长度超过此值将进行压缩。过大的值将增加流量使用并导致网络延迟;过小的值会影响性能。不懂别乱改。
network-compression-threshold=256
# 建造高度限制(最大 256)
max-build-height=256
# 是否生成村民
spawn-npcs=true
# 是否使用白名单模式(仅允许白名单内用户加入)
# 未考证过用法。
white-list=false
# 是否自然生成被动性生物(不含村民)
spawn-animals=true
# 不知道啥玩意
snooper-enabled=true
# 服务器资源包(服务器可以为客户端提供材质包)
# 此处填材质包的 sha1 值(可不填)
resource-pack-sha1=
# 验证玩家是否登录?
# 这是安全性的重要保障。
# 如果要求玩家通过 Mojang 账号登录,或者你使用了 authlib-injector,开启。否则关闭。
online-mode=true
# 服务器资源包的相对位置(如 resource-packs/R3D-Minecraft-512x.zip)
resource-pack=
# 允许玩家和玩家互撕
pvp=true
# 默认难度(实际难度以地图设置为准。0-4 分别为和平到困难)
difficulty=2
# 允许使用命令方块
enable-command-block=true
# 默认游戏模式(实际模式以玩家数据为准)
gamemode=0
# 如果玩家不操作且不移动的时间超过该设定值,则踢出玩家。
# 此项目为毫秒数,即,秒数 × 1000
# 设置为 0 禁用此功能
player-idle-timeout=0
# 最大玩家数
# 一般来说需要通过某些方法估测理论核载,并填入
max-players=38
# 最大能见度(渲染距离),客户端受其限制
# 一般设置为10。如果你对搭载服务器的电脑性能有信心,可以设为12以上的数值,但是不建议超过16。
view-distance=13
# 默认是否生成建筑?(实际情况以地图为准)
generate-structures=true
# 服务器描述
# 注意,填入非ASCII字符需要先转换为Unicode。
motd=A Minecraft Server
# 是否对区块使用同步写入
# MC1.16 新增选项,可以杜绝服务端意外关闭(但不能是电脑断电)时损坏存档的现象。
# 服务器负载较大且使用机械硬盘时,可能造成性能上的损失。
sync-chunk-writes=true

注意,如果需要填入中文数值必须转换为 Unicode,否则无法正确解码。

9 启动服务器,根据实际情况需要 14 秒到 5 分钟不等。如果 mod 存在特殊的兼容问题,可能无法正常启动服务器。此时需要自行排查问题。

当前时间: 6:13:25.01
=================服务器即将启动=================
# 加载开始
[authlib-injector.launch] [INFO] Version: 1.1.26-41a7a47
[authlib-injector.config] [INFO] API root: https://mcskin.littleservice.cn/api/yggdrasil/
[06:13:36] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLServerTweaker
[06:13:36] [main/INFO] [LaunchWrapper]: Using primary tweak class name net.minecraftforge.fml.common.launcher.FMLServerTweaker
[06:13:36] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLServerTweaker
[06:13:37] [main/INFO] [FML]: Forge Mod Loader version 14.23.5.2847 for Minecraft 1.12.2 loading
[06:13:37] [main/INFO] [FML]: Java is Java HotSpot(TM) 64-Bit Server VM, version 1.8.0_221, running on Windows 10:amd64:10.0, installed at C:\Program Files\Java\jre1.8.0_221
[06:13:38] [main/WARN] [FML]: The coremod FMLCorePlugin (net.minecraftforge.fml.relauncher.FMLCorePlugin) is not signed!
[06:13:38] [main/WARN] [FML]: The coremod FMLForgePlugin (net.minecraftforge.classloading.FMLForgePlugin) is not signed!
[06:13:38] [main/INFO] [FML]: Searching D:\Minecraft Profile\servers\1.12.2 Demo-Server\.\mods for mods
[06:13:38] [main/INFO] [FML]: Searching D:\Minecraft Profile\servers\1.12.2 Demo-Server\.\mods\1.12.2 for mods
...
# 服务器主程序启动
[06:13:51] [main/INFO] [LaunchWrapper]: Launching wrapped minecraft {net.minecraft.server.MinecraftServer}
[authlib-injector.httpd] [INFO] Httpd is running on port 58998
[authlib-injector.transform] [INFO] Transformed [com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService] with [Constant URL Transformer]
[authlib-injector.transform] [INFO] Transformed [com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService] with [Texture Whitelist Transformer]
[authlib-injector.transform] [INFO] Transformed [com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService] with [Yggdrasil Public Key Transformer]
[authlib-injector.transform] [INFO] Transformed [com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository] with [Constant URL Transformer]
...
# 服务器初始化完成
[06:14:41] [Server thread/INFO] [minecraft/DedicatedServer]: Loading properties
[06:14:41] [Server thread/INFO] [minecraft/DedicatedServer]: Default game type: SURVIVAL
[06:14:41] [Server thread/INFO] [minecraft/DedicatedServer]: Generating keypair
[06:14:41] [Server thread/INFO] [minecraft/DedicatedServer]: Starting Minecraft server on :::23334
[06:14:41] [Server thread/INFO] [minecraft/NetworkSystem]: Using default channel type
[06:14:44] [Server thread/INFO] [MoarSigns]: Starting sign integrations
[06:14:44] [Server thread/INFO] [MoarSigns]: Finished 1 sign integrations with 12 signs registered
[06:14:44] [Server thread/WARN] [FML]: Potentially Dangerous alternative prefix `minecraft` for name `sign`, expected `moarsigns`. This could be a intended override, but in most cases indicates a broken mod.
[06:14:44] [Server thread/INFO] [FML]: Applying holder lookups
[06:14:44] [Server thread/INFO] [FML]: Holder lookups applied
[06:14:45] [Server thread/INFO] [MCEF]: Now initializing MCEF v1.11...
[06:14:45] [Server thread/INFO] [MCEF]: MCEF is running on server. Nothing to do.
[06:14:46] [Server thread/INFO] [FML]: Injecting itemstacks
[06:14:46] [Server thread/INFO] [FML]: Itemstack injection complete
[06:14:47] [Server thread/INFO] [worldedit]: WorldEdit for Forge (version 6.1.10-SNAPSHOT) is loaded
[06:14:48] [Server thread/INFO] [FML]: Forge Mod Loader has successfully loaded 25 mods
...
# 生成地图
[06:15:15] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing start region for level 0
[06:15:24] [Server thread/INFO] [net.minecraft]: [streams] River at tp -233 64 -408
[06:15:25] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 0%
[06:15:26] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 3%
[06:15:27] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 4%
[06:15:28] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 4%
[06:15:29] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 10%
[06:15:30] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 13%
[06:15:31] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 19%
[06:15:32] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 25%
[06:15:33] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 33%
[06:15:34] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 44%
[06:15:35] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 49%
[06:15:36] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 55%
[06:15:37] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 56%
[06:15:38] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 65%
[06:15:39] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 72%
[06:15:40] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 78%
[06:15:41] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 87%
[06:15:42] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 91%
[06:15:43] [Server thread/INFO] [minecraft/MinecraftServer]: Preparing spawn area: 96%
# 加载完成
[06:15:43] [Server thread/INFO] [minecraft/DedicatedServer]: Done (55.422s)! For help, type "help" or "?"
[06:15:44] [Server thread/INFO] [journeymap]: global (FirstLoaded) Setting config file to version "5.5.0rc1": journeymap.server.global.config
[06:15:44] [Server thread/INFO] [journeymap]: global (Valid) Creating config file: .\journeymap\server\5.5\journeymap.server.global.config
[06:15:44] [Server thread/INFO] [journeymap]: dim0 (Initialized) Setting config file to version "5.5.0rc1": journeymap.server.dim0.config
[06:15:44] [Server thread/INFO] [journeymap]: dim0 (Valid) Creating config file: .\journeymap\server\5.5\journeymap.server.dim0.config
[06:15:44] [Server thread/INFO] [journeymap]: dim-1 (Initialized) Setting config file to version "5.5.0rc1": journeymap.server.dim-1.config
[06:15:44] [Server thread/INFO] [journeymap]: dim-1 (Valid) Creating config file: .\journeymap\server\5.5\journeymap.server.dim-1.config
[06:15:44] [Server thread/INFO] [journeymap]: dim1 (Initialized) Setting config file to version "5.5.0rc1": journeymap.server.dim1.config
[06:15:44] [Server thread/INFO] [journeymap]: dim1 (Valid) Creating config file: .\journeymap\server\5.5\journeymap.server.dim1.config
[06:15:44] [Server thread/INFO] [journeymap]: dim3 (Initialized) Setting config file to version "5.5.0rc1": journeymap.server.dim3.config
[06:15:44] [Server thread/INFO] [journeymap]: dim3 (Valid) Creating config file: .\journeymap\server\5.5\journeymap.server.dim3.config
[06:15:45] [Server thread/INFO] [journeymap]: dim7 (Initialized) Setting config file to version "5.5.0rc1": journeymap.server.dim7.config
[06:15:45] [Server thread/INFO] [journeymap]: dim7 (Valid) Creating config file: .\journeymap\server\5.5\journeymap.server.dim7.config
[06:15:45] [Server thread/INFO] [STDOUT]: [thut.api.terrain.TerrainSegment:refresh:438]: subBiome refresh took 0.01915091
[06:15:47] [Server thread/INFO] [FML]: Unloading dimension -1
[06:15:47] [Server thread/INFO] [FML]: Unloading dimension 1
[06:15:47] [Server thread/INFO] [FML]: Unloading dimension 3
[06:15:47] [Server thread/INFO] [FML]: Unloading dimension 7

将服务器程序放着,不要关闭。

10 查看你的 IP 地址,并告诉局域网内的朋友(使用 ipconfig 命令,见上文)。IP 地址使用 IPv4 和 IPv6 皆可。

无线局域网适配器 WLAN:

   连接特定的 DNS 后缀 . . . . . . . :
   IPv6 地址 . . . . . . . . . . . . : 2409:8a28:8c2:a0a0:4575:3acc:f2f3:ffd9
   临时 IPv6 地址. . . . . . . . . . : 2409:8a28:8c2:a0a0:587f:e28:2606:537a
   临时 IPv6 地址. . . . . . . . . . : 2409:8a28:8c2:a0a0:d003:c76a:b3b9:4a27
   临时 IPv6 地址. . . . . . . . . . : 2409:8a28:8c2:a0a0:e007:eb29:ca9:aa4e
   本地链接 IPv6 地址. . . . . . . . : fe80::4575:3acc:f2f3:ffd9%15
   IPv4 地址 . . . . . . . . . . . . : 192.168.1.9
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : fe80::1%15
                                       192.168.1.1

11 启动自己的 Minecraft 游戏。(如果使用 authlib-injector 实现外置登录,建议使用 HMCL 启动器,并使用外置登录功能)

12 选择 “多人游戏” -> “直接连接”,输入 [::1]:{端口号},比如 [::1]:23334。如果正常进入了游戏,说明服务器配置没有出现问题。

13 打开服务器控制台,输入 op {你的名字},给自己授予服务器管理员权限。

注意,如果服务器开启 online-mode,那么你需要在玩家在线时才能使用这个命令。

你也可以通过这种方式授权同学使用指令。不过,需要注意的是,所有管理员权限相同,其他管理员甚至可以封禁你。但是,你随时可以操作服务器控制台,来撤销这些更改。

正常的联机下,如果同学搞破坏,一般仅需使用 /kick {玩家名} {原因},将其踢出服务器。要了解更多服务器管理命令,请参阅 中文 Minecraft Wiki: 命令

14 授权管理员后即可为所欲为。

15 将你的 IP 和端口号告诉同学。同学需要使用 “多人游戏” -> “直接连接”。如果你们使用 IPv4 地址,那么填写 {地址}:{端口号}。如果是 IPv6,填写 [{地址}]:{端口号}(这种填写方法用于避免零位压缩造成的歧义)。

加入成功后,就可以愉快地玩(bào)耍(zhèng)了。

16 注意,关闭服务器时,必须在游戏(仅限管理员)或服务器控制台中输入 /stop,千万不要直接关闭,否则会导致地图不保存,严重者会损坏地图。

17 如果想要了解高级的服务器插件,可以使用 PaperMC(但是这个不支持 mod),也可以在刚才搭建的服务端上安装 SpongeForge。

如果电脑配置有中等水平,建议用 SpongeForge。它可以支持许多 SpongeAPI 插件,能够修复一些服务端上的玄学问题,还能提供一个允许你高度个(mēng)性(bī)化的配置文件。

使用外置登录模块

  • 这个模块需要启动器支持。目前大多主流双用启动器支持该特性(建议使用 HMCL 或 BakaXL)。
  • 外置登录可以有效防止玩家将名字改为房主名字而为所欲为,也可以防止恶意的“假人”进入服务器占满人数限制。
    • 注意,这不能避免玩家实现一个拥有账号的“假人”并利用其进行作弊。
  • 外置登录为游戏本身模拟了“正版登录”的环境,因此可以彻底避免离线登录造成的技术问题,但这并不意味着你拥有正版,也不意味着你可以进入国际服务器游玩。

外置登录并不是正版 Minecraft 登录。有很多第三方机构都提供了外置登录服务。此处,我们以使用最广泛的 LittleSkin 为例。

打开 LittleSkin 主站,注册账号,设置角色名和皮肤。在用户手册中往下翻,我们找到了 Yggdrasil 部分(这是外置登录模块)。

在客户端配置

预计通读时间:0.6分钟
预计实践时间:5分钟

(只讲 HMCL。如果要玩的服务器需要外置登录请使用 HMCL)

1 点击“账户”栏,点击页面右下角的加号。

2 登陆方式选择外置登录。点击“认证服务器”右侧的加号。

3 输入 LittleSkin 认证服务地址。

https://mcskin.littleservice.cn/api/yggdrasil

等待操作成功后,点击“完成”。

4 输入 LittleSkin 用户名和密码,进行登录。

5 如果登陆成功,会创建一个登陆身份。以后启动游戏使用这个身份即可。

游戏中的昵称即为你在 LittleSkin 设置的角色名(可以在 LittleSkin 上修改)。

在设置 LittleSkin 外置登录后,无需其他 mod 就可以显示皮肤。

服务端配置

预计通读时间:1分钟
预计实践时间:6分钟

1 去下载 authlib-injector,然后放在你开设服务端的文件夹下。

2 修改 server.properties 中的 online-mode 属性为 true

3 修改 Launch.bat

修改前:
java -Xmx{最大内存} -jar {forge-xxx.jar} nogui
Example
java -Xmx3584M -jar forge-1.12.2-14.23.5.2847-universal.jar nogui

修改后:
java -Xmx{最大内存} -javaagent:{authlib-injector-xxx.jar}={登录服务地址} -jar {forge-xxx.jar}.jar nogui
Example
java -Xmx3584M -javaagent:authlib-injector-1.1.26-41a7a47.jar=https://mcskin.littleservice.cn/api/yggdrasil -jar forge-1.12.2-14.23.5.2847-universal.jar nogui

4 按原来方式启动服务端即可。此时服务端仅仅接受通过 LittleSkin 登录的玩家。其他玩家无法加入服务器。这样有效防止了其他玩家通过修改昵称冒充你的管理员用户,也大大加大了被封禁账户改名重新加入的成本。

局域网限制的来历和新的解决方法

预计通读时间:3分钟
预计考证时间:40分钟(如果你需要用探究证明这个问题)

理论部分,看不懂无需追究。

一般的家庭在将局域网设备接入外界互联网时,都经过了 NAT。NAT 是一个技术,可以使多个设备共用一个公网(局域网外的) IP 地址。这种结构看起来大概是这样的:

在同一个局域网内,每台机器都有不同的 IP 地址,因此,同学输入你的 IP,就可以精准地进入你的游戏。

而在局域网外,玩家只有可能通过你的公网 IP 访问你。于是,一个带着 19.26.8.17:23334 目的的数据包被发到了你家的 NAT。然而,NAT 并不知道该数据包应该前往局域网中的哪个机器。此时,NAT 就会拒绝连接。

于是,一个叫“端口转发”的机制产生了。(也可以叫做 “端口映射”)

你可以在 NAT 上对数据包去向进行设置。比如说当公网用户访问 19.26.8.17:23334 时,将其导向到 192.168.1.114:23334,而不是其他地方。你甚至可以设置 19.26.8.17:23334 转发到 192.168.1.114:25566

这就是某些过时教程介绍的联机方法,然而并不可行。这究竟是为什么呢

原来,中国对互联网的的管控十分严格。想要让他人能对你的公网 IP 进行连接,你需要进行备案(这需要申请者提供身份证件等资料),并且还要向运营商申请(可能造成手续费用)。对于某些人来说,这显然是完全超出能力范围的。

那么究竟该怎么办呢?

请不要惊慌。其实,端口转发并不是唯一的解决方案。我们要介绍的,是另一个更加可行,却毫不逊色于端口转发的方法。

那么,就是时候请出主角 —— VPN (Virtual Private Network) 了。

诶等等,VPN 不是拿来爬 Great Wall 的吗?

没错,是的。小时候妈妈告诉你,VPN 就是拿来爬 Great Wall 的。但是,VPN 设计出来的本意可不是让你干这种龌龊的事情。今天,我们要还 VPN 一个清白。

我们再用一个缩写来形容 VPN 的正确用途 —— VLAN (Virtual Local Area Network),就是虚拟局域网

这么一说,事情就变得非常好理解了。通过合适的 VPN 软件,你可以和朋友通过互联网组建一个虚拟的、允许用户互相访问的局域网,从而使用局域网联机的方法来实现远程联机。

使用 VLAN 实现远程联机

预计通读时间:5分钟
预计实践时间:18分钟

软件选择

那么问题来了。原理我们清楚了,但是我们需要一个 VLAN 软件。

中国免费VLAN软件哪家强?tan(90°)。(我只知道有个蒲公英 VPN,但是很可能并不能满足正常的联机需要,因为在免费版下,所有加入网络的成员都对网络有管理权限(这不符合安全要求),而且限制 3 人)

于是我们去国外看看,发现了好东西:

ZeroTier One

这个软件具有这些好处:

  • 对于一个已注册用户,其主持的所有虚拟局域网中用户数加和限制为 100(于是可以愉快地打一些 MC 小游戏)。
  • 有 API,方便开发者用自己的方式使用,或者针对其开发软件。(有版权限制。如果你使用免费版,并且要在自己的软件中使用 ZeroTier,你的软件必须是开源的)
  • 如果一个用户仅仅需要加入一个 VLAN,而不需要主持,那么她无需注册账户,只需下载软件即可。
  • 支持创建私有 VLAN,加入者需要通过验证。
  • 允许选择 VLAN 中的 IP 格式。对于 IPv4,可以使用静态 IP(即,同一个用户在同一个网络中的 IP 地址不会改变)。一个用户的可以同时连接多个 VLAN,只要 IP 不冲突。
  • 允许自定义连接规则(靠编写代码实现)。
  • 使用 P2P 传输数据,速度达到游戏联机水平(实测)。
  • 全球通用,无需实名验证。
  • 加入 VLAN 后,即使不打开软件,也可以在 VLAN 中正常通信。

可以说这是非常良心的软件了。除了界面略有点不好看,别的都非常好。

Windows 版下载

其他平台

准备工作

开设 VLAN 网络

只有联机时的房主需要开设网络,其他玩家只需要加入。

1ZeroTier Central 创建账户,并完成套餐选择。

2 点击顶栏上的 “Networks”,然后选择 “+ Create Network”。

3 点击进入新创建的网络。修改网络名称和描述。

如果希望任何人都能加入,选择“PUBLIC”。如果希望加入者需要授权,选择“PRIVATE”。

4 在 IPv4 Auto Assign 处选择喜欢的 IPv4 地址格式。

5 安装 ZeroTier One 软件。安装后,右键托盘图标,选择“Join Network”。

6 将网络管理页面上的 Network ID 复制到输入框中。底下的选项不用管。

7 如果系统在加入后提示“是否允许被其他设备发现”,选择“是”。如果系统询问网络类型,选择“专用网络”。

8 刷新网络管理页面。翻到 Members 处,授权自己加入。

9 可以在管理页为自己的电脑填写名字、描述。还可以看到,你的电脑获得了一个固定 IP。

10 右键 ZeroTier One 软件的托盘图标,查看是否加入成功。

(如果网络 ID 和名称能同时正确显示,并且前面打勾,说明成功)

你可以通过点击已加入的网络来断开连接。点击断开的网络将重新加入。若要将一个网络从列表中移除,选择“Show Networks”,然后使用“Delete”按钮即可移除。

11 使用 ipconfig 命令查看自己在 VLAN 中的 IP 地址(具体见上文)。

以太网适配器 ZeroTier One [1c33c1ced0267728]:

   连接特定的 DNS 后缀 . . . . . . . :
   本地链接 IPv6 地址. . . . . . . . : fe80::4584:a844:fa95:ab58%16
   IPv4 地址 . . . . . . . . . . . . : 10.147.17.172
   子网掩码  . . . . . . . . . . . . : 255.255.0.0
   默认网关. . . . . . . . . . . . . : 25.255.255.254

IPv4 地址:10.147.17.172

关于重启:VLAN 的参与者重启计算机后,只要IP地址没有变更,就可以在不打开 ZeroTier One 的情况下仍然使用该 VLAN。

加入 VLAN 网络

预计通读时间:1.5分钟
预计实践时间:8分钟

预计本小节完成时间:2分钟

这个操作由房主的好友完成。

4 让房主把自己的 Network ID 发给好友。

5 安装 ZeroTier One 软件。安装后,右键托盘图标,选择“Join Network”。

6 将房主告诉自己的 Network ID 复制到输入框中。底下的选项不用管。

7 如果系统在加入后提示“是否允许被其他设备发现”,选择“是”。如果系统询问网络类型,选择“专用网络”。

8 让管理员授权自己加入。

10 右键 ZeroTier One 软件的托盘图标,查看是否加入成功。

(如果网络 ID 和名称能同时正确显示,并且前面打勾,说明成功)

你可以通过点击已加入的网络来断开连接。点击断开的网络将重新加入。若要将一个网络从列表中移除,选择“Show Networks”,然后使用“Delete”按钮即可移除。

关于重启:VLAN 的参与者重启计算机后,只要IP地址没有变更,就可以在不打开 ZeroTier One 的情况下仍然使用该 VLAN。

Van 游戏

主持游戏

房主应该按照局域网内联机时的方法开启局域网世界或者物理服务端,随后将自己在 VLAN 中的 IPv4 地址和游戏端口号告诉好友。

加入游戏

好友应启动对应版本、Mod 相同的游戏,选择 “多人游戏” -> “直接连接”,然后按照“{IPv4}:{端口号}”的格式(如 10.147.17.172:23334)输入并连接。

然后就可以愉快地被暴政了。

拓展应用

VLAN 的用途远远不止打游戏。VLAN 打破了内网与地域的限制,使得设备能够轻松在异地互相连接。有能力的同学可以自行探究下面的应用方式。

传输文件

如果建立连接后延迟小于 100ms,那么 VLAN 将会是一个理想的文件远程传输工具(只需要一次上传或下载,而无需上传并下载),其速度可能高于 QQ 等常见的文件传输软件。

一种可行的方式是在其中一台机器上安装 web 服务器。这样,文件传输就变成了高速下载的过程,且不需要先上传后下载,效率极高。

在 web 服务器上添加一个可用于上传文件的接口,即可实现反向传输。如果要进一步提高效率,可以考虑 KodExplorer可道云 等轻量级网盘应用。

一个管理较好的文件传输 web 服务器可以成为团队合作的工具。事实上,许多企业均让在家办公的员工连接公司 VPN 以访问公司内部的服务。

即时通信

一个属于个人的 VLAN 通常不会承载大量用户。因此,可以在 web 服务器上添加一个利用 AJAX 每 3 秒刷新一次来进行即时通信的软件。

VLAN 相当于真正的局域网,参与者可以充分利用网络协议。通过使用基于局域网的即时通信协议或工具,就可以实现真正意义上的即时通信(而不是每 3 秒刷新一次)。

这种通信手段的好处在于通信系统完全受参与者控制(ZeroTier 网络上传输的数据都被事先加密,且不会经过 ZeroTier 的服务器)。因此,某些学生可以自行搭建用于 PY 交易的通信系统,而非使用 QQ 群。这样,即使 PY 交易被发现,参与者也可以共同快速销毁证据,不留下一片云彩(大雾

远程控制

如果一台电脑使用 Windows 10 专业版、企业版等高级版本,那么该电脑可以开启“远程桌面”功能。开启后,同一局域网(包括 VLAN)中的设备输入密码后就可以直接远程控制该电脑,这为远程办公或处理紧急事件提供了便利。

你也可以编写一些专项远程控制程序,例如实时监测当前电脑上进行的操作,或是远程锁定电脑,或是打开摄像头拍照(用于抓获盗用电脑还忘记遮蔽摄像头的粗鄙之人)。但是,千万记住要对远程控制接口进行密码保护,并且不要公开发布这些东西(否则可能比 Kali 用户更早坐牢)。

操作流程

房主与玩家约定进行联机时,可以按下面的流程“启封”(做好第一次准备)。

如果通读教程后,房主与玩家没有完整的思路,则可以在实践时参照该过程。

本例中,测试页面是这样的:

这是测试页面的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>VLAN 连接测试</title>
</head>
<body>
    <h2>VLAN 连接测试</h2>
    <p>您在当前网络中的IP地址是:<?php echo $_SERVER['REMOTE_ADDR'] ?></p>
    <p>请核对地址是否与管理员为你分配的相同。</p>
    <ul>
        <li>如果相同,那么恭喜你,你配置成功了。</li>
        <li>如果不同,请向管理员求助。</li>
        <li>如果你不知道管理员分配的IP地址,请向管理员索取。</li>
    </ul>
</body>
</html>

结语

“山重水复疑无路,柳暗花明又一村”。在阅读了许多篇老旧的、互相转载的 Minecraft 远程联机假教程时,我们曾经怀疑过这是不可能的。但是,凭借探究和创新的精神,我们一定会发现新的办法的。

关于转载的特别说明

盗教程的死个马,骨灰飞扬千万家。

任何人在未经特别允许(由作者允许)的情况下,不得:

  • 复制文章内容,发布在其他地方。
  • 在自己博客文章不含任何有意义内容的情况下,直接贴出本文链接。

任何人可以:

  • 通过私信、群发、群聊等形式分享指向此文章的链接。
  • 在有意义的博客文章、朋友圈等地方添加指向此文章的链接。

undefined