饥荒(Don't Starve Together)独立服务器搭建

云服务器配置如下:

  • CPU:2核
  • 内存:4GB
  • 带宽:6Mbps
  • 操作系统:Ubuntu 22.04.5 LTS

1 服务器环境配置

参考以下步骤进行服务器的初始化配置,按需配置即可

1.1 准备一个非root的特权用户

如果已有则可跳过该步骤,没有则可参考下面的步骤配置:

  1. 使用root用户新建用户并添加到sudo用户组
    1
    2
    3
    4
    5
    # 新增用户 根据提示设置密码等用户信息
    adduser guozhuang

    # 将用户添加到sudo用户组
    adduser guozhuang sudo
  2. 使用刚才新建的用户重新登录
    1
    su - guozhuang

后续步骤都应使用非root用户执行

1.2 更新软件

1
2
sudo apt update
sudo apt upgrade -y

1.3 配置防火墙

该步骤一般在云服务器平台的控制台中配置,放行10998和10999端口,协议选择UDP

2 安装SteamCMD

SteamCMD是Steam官方提供的命令行版本,和桌面端的Steam不同的是,SteamCMD的软件库中只有游戏服务器,
其中就包括饥荒独立服务器(Don’t Starve Together Dedicated Server),
因此我们需要使用SteamCMD下载和更新饥荒独立服务器

SteamCMD的安装步骤参考[1]

  1. 新建一个文件夹用于放SteamCMD
    1
    mkdir ~/steamcmd && cd ~/steamcmd
  2. 如果你的服务器是64位的,则需要安装下面的依赖
    1
    sudo apt install lib32gcc-s1
    执行uname -m,如果输出x86_64则表示你的服务器是64位的
  3. 下载并解压SteamCMD到当前文件夹下
    1
    curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxvf -

3 安装饥荒独立服务器(Don’t Starve Together Dedicated Server)

这一步才是真正安装饥荒独立服务器,它的作用是把我们的游戏存档运行起来,
并把房间注册到游戏大厅里,也就是说它才是本次的主角

饥荒独立服务器的安装步骤参考[2]

  1. 运行SteamCMD
    1
    2
    cd ~/steamcmd && ./steamcmd.sh
    # 等待加载完成
  2. 指定饥荒独立服务器的安装目录
    1
    2
    # 后面的路径可自行修改
    force_install_dir ~/steamcmd/steamapps/dst_dedicated_server/
  3. 匿名登录SteamCMD
    1
    login anonymous
  4. 下载饥荒独立服务器
    1
    2
    app_update 343050 validate
    # 后续它更新也是这个命令
    其中343050是饥荒独立服务器的AppID[3]
  5. 下载完成后退出SteamCMD
    1
    quit

4 准备存档及修改配置

准备一个打算放在云服务器上运行的存档,可以新建一个新存档,也可以使用之前已有的旧存档

准备好之后把存档放到云服务器上的指定位置,然后启动上一步安装的饥荒独立服务器即可运行存档

具体可参考下面的步骤:

4.1 新建存档

进入游戏,创建一个新存档,按需配置后进入到选择人物的界面时退出存档,进入到游戏主界面。

点击左下角的“数据”,打开存档所在目录,Cluster_x即存档文件夹,其中x是数字编号,从1开始,
刚才新建的就是x值最大的那个存档

4.2 使用已有存档

在上一步的存档目录中,所有以Cluster_开头的文件夹都是存档,
所以这里可以选择之前的存档作为本次放到云服务器上运行的存档

4.3 修改配置

为了方便操作,我这里建议在把存档上传到Linux服务器上之前,先把配置文件修改好

在修改配置之前,你可以选择是否先备份存档

4.3.1 修改cluster.ini文件

该文件的内容大致如下,按需修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[GAMEPLAY]
game_mode = endless
max_players = 4
pvp = false
pause_when_empty = true

[NETWORK]
lan_only_cluster = false
cluster_password =
cluster_description = 这是一条神奇的描述...
cluster_name = GZOnline
offline_cluster = false
cluster_language = zh

[MISC]
console_enabled = true

[SHARD]
shard_enabled = true
bind_ip = 127.0.0.1
master_ip = 127.0.0.1
master_port = 10888
cluster_key = defaultPass

配置参数简要介绍[4]

  • game_mode: 游戏模式。取值范围: {survival(默认), endless ,wilderness},分别表示生存、无尽和荒野
  • max_players: 最大同时在线人数。取值范围: 1~16之间的整数,包含1和16,默认值16
  • pvp: 是否开启PVP。取值范围: {true, false(默认)}
  • pause_when_empty: 无人在线时是否暂停世界时间
  • lan_only_cluster: 是否仅局域网。如果设置成true 则表示只有局域网内的玩家能加入房间
  • cluster_password: 房间密码 不设置则表示无密码
  • cluster_description: 房间描述 显示在游戏大厅的房间详情中
  • cluster_name: 房间名称
  • offline_cluster: 是否是离线存档 如果设置成true 则房间不会在游戏大厅展示 只有本地网络上的玩家才能加入 且所有跟Steam有关的功能都不能用 比如:拆礼物
  • console_enabled: 是否启用控制台 如果设置成false 那么你将无法在终端中执行命令 但仍可在游戏中按下~按键并执行命令(如果你具有管理员权限的话)
  • shard_enabled: 是否启用多层世界 如果启用了洞穴则必须设置为true
  • bind_ip : 主服务侦听的IP地址 如果你的存档分布在多台服务器上 则需要设置成0.0.0.0 否则设置成127.0.0.1即可
  • master_ip: 主服务器的IP地址 如果你的存档分布在多台服务器上 则需要设置成主世界所在服务器的IP地址 否则设置成127.0.0.1即可
  • master_port: 主从服务器建立连接时的UDP端口号 保持默认10888即可
  • cluster_key: 主从服务器建立连接时的验证密码 如果你的存档都在同一台服务器上 则该字段可以不用管 但如果分布在多台服务器上 则每台服务器的该文件中的该字段应保持一致

更多参数详情可查看Klei官方技术论坛

4.3.2 修改Master文件夹下的server.ini文件

该文件的内容大致如下,按需修改:

1
2
3
4
5
6
7
8
9
10
[NETWORK]
server_port = 10999

[SHARD]
is_master = true
id = 1
name = GZOnlineMaster

[ACCOUNT]
encode_user_path = true

配置参数简要介绍:

  • server_port: 当前世界服务的端口号。建议取值介于1099811018之间,且不同世界的端口号不能重复
  • is_master: 是否是主世界。默认情况下,地面作为主世界,并且只能有一个主世界,其他世界的该字段都要设置成false
  • id: 当前世界的ID。可以使用默认的,也可以自行编号,但注意每个世界的ID都是不能重复
  • name: 当前世界的名称。用于在日志中显示,可自行修改或保持默认
  • encode_user_path: 暂未找到相关介绍,保持默认即可

更多参数详情可查看Klei官方技术论坛

4.3.3 修改Caves文件夹下的server.ini文件

该文件内容大致如下,按需修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[NETWORK]
server_port = 10998

[SHARD]
is_master = false
name = GZOnlineCaves
id = 2

[ACCOUNT]
encode_user_path = true

[STEAM]
master_server_port = 27017
authentication_port = 8767

配置参数简要介绍:

  • server_port: 同Master配置
  • is_master: 同Master配置
  • id: 同Master配置
  • name: 同Master配置
  • encode_user_path: 同Master配置
  • master_server_port: Steam内部端口(默认27016)。确保同一台电脑上的该端口不重复,比如上面Master中未配置该参数,也就是使用的默认值,因此当前世界要配置一个不同的端口号
  • authentication_port: Steam内部端口(默认8766)。同上

4.3.4 新建cluster_token.txt文件

想要启动饥荒独立服务器并注册到游戏大厅,还需要一个token,相当于存档注册到大厅的“入场券”。
这个“入场券”的获取方式大致如下:

  1. 访问Klei Accounts网站并登录您的帐户
  2. 点击顶部导航栏中的“游戏”
  3. 点击“《饥荒:联机版》的游戏服务器”
  4. 在“服务器名称”后随便输入一段内容,为了方便记忆和区分,可以输入存档房间的名称
  5. 点击“配置服务器”,复制“服务器票据”后的一串内容,这个就是“入场券”

最后在cluster.ini文件旁边(同级目录)新建一个cluster_token.txt文件,把“入场券”的内容粘贴到该文件中,然后保存即可

4.3.5 新建adminlist.txt文件

首先说明:这一步可跳过。

这个文件是用来添加管理员的,管理员的作用是使用控制台,比如回档、踢人、执行命令等。
而生成“入场券”的那个人默认是管理员,所以即使这个文件不创建也不影响你使用控制台。
但如果你想把你的小伙伴也设置成管理员,则必须要创建这个文件并在里面添加你的小伙伴的Klei用户ID。

Klei用户ID的查看方法如下:

  1. 让你的小伙伴访问Klei Accounts网站并登录他的帐户
  2. 点击顶部导航栏中的“用户信息”,其中“Klei用户ID”下面的以KU_开头的一串字符就是我们需要的东西

搞到这个东西之后,还是在cluster.ini文件旁边(同级目录),新建一个adminlist.txt文件,
然后把这串字符粘贴到该文件中保存即可

如果你的小伙伴不止一个,只需要另起一行粘贴就行,每个ID占一行,不需要任何其他标点符号

4.4 把存档上传到云服务器

首先在云服务上创建一个目录,用来存放要运行的存档。

实际上饥荒独立服务器会默认读取~/.klei/DoNotStarveTogether/Cluster_1/目录下的存档[5]
因此你可以选择创建这个目录,然后把存档放到这个目录下。

当然,也可以指定一个自己喜欢的目录,后面在配置文件中配置即可。
不过如果你是新手或者想尽快完成这项工作,那我建议你使用默认的存档位置,这样后续能省下一部分时间。

我这里使用默认目录,例如存档名称为Cluster_1,则目录结构应大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.klei
└── DoNotStarveTogether
└── Cluster_1
├── Caves
│ ├── leveldataoverride.lua
│ ├── modoverrides.lua
│ ├── save
│ └── server.ini
├── Master
│ ├── leveldataoverride.lua
│ ├── modoverrides.lua
│ ├── save
│ └── server.ini
├── adminlist.txt
├── cluster.ini
└── cluster_token.txt

5 启动独立服务器

  • 推荐使用脚本启动,脚本内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash

steamcmd_dir="$HOME/steamcmd"
install_dir="$steamcmd_dir/steamapps/dst_dedicated_server"
cluster_name="Cluster_1"
dontstarve_dir="$HOME/.klei/DoNotStarveTogether"

function fail()
{
echo Error: "$@" >&2
exit 1
}

function check_for_file()
{
if [ ! -e "$1" ]; then
fail "Missing file: $1"
fi
}

cd "$steamcmd_dir" || fail "Missing $steamcmd_dir directory!"

check_for_file "steamcmd.sh"
check_for_file "$dontstarve_dir/$cluster_name/cluster.ini"
check_for_file "$dontstarve_dir/$cluster_name/cluster_token.txt"
check_for_file "$dontstarve_dir/$cluster_name/Master/server.ini"
check_for_file "$dontstarve_dir/$cluster_name/Caves/server.ini"

./steamcmd.sh +force_install_dir "$install_dir" +login anonymous +app_update 343050 validate +quit

check_for_file "$install_dir/bin64"

cd "$install_dir/bin64" || fail

run_shared=(./dontstarve_dedicated_server_nullrenderer_x64)
# run_shared+=(-console) # 该参数已弃用
run_shared+=(-cluster "$cluster_name")
run_shared+=(-monitor_parent_process $$)

"${run_shared[@]}" -shard Caves | sed 's/^/Caves: /' &
"${run_shared[@]}" -shard Master | sed 's/^/Master: /'

脚本内容简要说明:

  • steamcmd_dir: steamcmd的安装目录,参考安装steamcmd,具体以你实际的安装位置为准
  • install_dir: 饥荒独立服务器的安装目录,参考安装饥荒独立服务器中的第2步,具体以你实际的安装位置为准
  • cluster_name: 准备运行的存档的文件夹名称,注意不是房间名称,参考把存档上传到服务器,具体以你实际的存档名称为准
  • dontstarve_dir: 准备运行的存档的所在目录,保持默认即可。如果你的存档放到了自定义路径下,请参考进阶玩法
  • ./steamcmd.sh +force_install_dir "$install_dir" +login anonymous +app_update 343050 validate +quit: 下载或更新饥荒独立服务器

将上面的内容保存到start_dst.sh文件中,并放到任意目录。比如就放到用户的根目录下。

  • 给脚本赋予执行权限
1
sudo chmod u+x ~/start_dst.sh
  • 启动独立服务器
1
2
cd ~
./start_dst.sh

首次启动时间会比较长 大约15~30分钟,出现以下字样表示启动成功

1
2
3
4
5
Master: [00:00:47]: Server registered via geo DNS in ap-southeast-1
Master: [00:00:47]: Sim paused
...... #省略若干行
Caves: [00:00:51]: [Shard] secondary shard LUA is now ready!
Caves: [00:00:51]: Sim paused
  • 停止服务器

在服务器运行界面按Ctrl+C键即可保存游戏并停止服务器。

6 添加模组

TODO

可参考陈默的博客[6]
其中有一篇《饥荒联机版专用服务器和多层世界配置指南》,
文中介绍了专用服务器和模组的配置

7 进阶玩法

7.1 后台运行

以上步骤虽然能正常启动独立服务器,但是有个很大的缺点:

你必须要保持终端开启,而且一旦和云服务器之间的SSH连接断开,
那将无法再次回到独立服务器运行的界面,这时只能杀死后台并重新启动

所以为了避免这种情况的发生,我们可以让独立服务器在后台运行,这样在运行服务器期间我们仍可操作计算机,并且可以安心断开云服务器的SSH连接

让独立服务器在后台运行的方式很多,这里使用screen工具实现,具体步骤如下:

  1. 安装screen工具: sudo apt install -y screen
  2. 新建窗口,用来运行独立服务器: screen -S dst
    其中dst是给窗口起的名称,可以自定义,但是要记住,后面进入这个窗口时需要指定名称
  3. 运行独立服务器: 正常执行启动脚本即可
  4. 按下Ctrl+A键并松开,然后按下D键分离该窗口

此时独立服务器就放在后台运行了,如果想回到运行界面,执行screen -r dst即可

7.2 定时重启更新

有时候会发现房间搜不到了,服务器运行的好好的,并没有停止,这时候大概率是因为饥荒更新了。

解决方法也很简单:把独立服务器停止,然后再重新启动即可(启动过程中会自动检查并更新)

但是每次都手动重启多多少少有点麻烦,所以可以使用cron配合脚本实现定时重启更新:

  1. 执行crontab -e编辑定时任务
  2. 按下i键以插入内容
  3. 在最后一行添加30 5 * * * ~/update_dst_schedule.sh,表示每天早上5:30执行~/update_dst_schedule.sh脚本
  4. 按下Esc键,输入:wq,然后回车,表示保存文件并退出

其中~/update_dst_schedule.sh脚本内容大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

# 独立服务器所在的窗口名称
SCREEN_SESSION="dst"
# 保持默认0即可
SCREEN_WINDOW="0"
# 服务器启动脚本路径
SCRIPT_NAME="~/dst_server_start.sh"

# 在独立服务器运行的终端中执行命令:c_announce("世界将于30秒后重启..."),表示在世界中宣告服务器即将重启的消息,以提醒当前在线用户(如果还有人在线的话)
screen -S $SCREEN_SESSION -p $SCREEN_WINDOW -X stuff "c_announce(\"世界将于30秒后重启...\")$(printf \\r)"
# 等待30秒
sleep 30
# 在独立服务器运行的终端中执行`CTRL+C`命令 此命令会让独立服务器保存数据并停止运行
screen -S $SCREEN_SESSION -p $SCREEN_WINDOW -X stuff $'\003'
# 关闭需要时间 这里等待20秒
sleep 20

### 在此处可以执行一些额外操作 比如备份数据等

# 再次启动服务
screen -S $SCREEN_SESSION -p $SCREEN_WINDOW -X stuff "$SCRIPT_NAME$(printf \\r)"

7.3 自定义存档路径

上文中我们提到默认的存档路径是~/.klei/DoNotStarveTogether/Cluster_1/,那这个结论的依据是什么?下面我们来详细讨论下

如果仔细看上文中独立服务器的脚本,就会发现真正的独立服务器程序实际上就是dontstarve_dedicated_server_nullrenderer_x64
并且在执行这个程序时指定了-cluster参数,表示要启动哪个存档,但是并没有指定存档的路径,因此可以推断它有个默认路径,如果不指定,
那独立服务器就会到默认路径下找存档。而实际上的确是如此。

这个程序使用以下几个参数来确定存档位置[5:1]

  • -persistent_storage_root: 默认值取决于平台
    1
    2
    3
    Windows: <Your documents folder>/Klei
    Mac OSX: <Your home folder>/Documents/Klei
    Linux: ~/.klei
  • -conf_dir: 默认值为"DoNotStarveTogether"
  • -cluster: 默认值为"Cluster_1"

存档的完整路径为<persistent_storage_root>/<conf_dir>/<cluster>

随意如果想自定义存档路径,只需要在启动脚本里面指定以上参数,并赋予对应的值即可。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ......省略前面部分

./steamcmd.sh +force_install_dir "$install_dir" +login anonymous +app_update 343050 validate +quit

check_for_file "$install_dir/bin64"

cd "$install_dir/bin64" || fail

run_shared=(./dontstarve_dedicated_server_nullrenderer_x64)
# run_shared+=(-console) # 该参数已弃用
run_shared+=(-persistent_storage_root "~")
run_shared+=(-conf_dir "dst_archives")
run_shared+=(-cluster "MyWorld")
run_shared+=(-monitor_parent_process $$)

"${run_shared[@]}" -shard Caves | sed 's/^/Caves: /' &
"${run_shared[@]}" -shard Master | sed 's/^/Master: /'

上述脚本示意的存档路径为:~/dst_archives/MyWorld

更多可用参数可参考Klei官方论坛

7.4 游戏内整点报时

上文在实现定时重启更新时可以发现,我们可以向screen后台运行的窗口中发送命令,那我现在就可以实现一个有意思的功能:

游戏内整点报时

实现方式很简单,首先把要实现的功能放到shell脚本里:

1
2
3
4
#!/bin/bash

# 其中dst是饥荒独立服务器所在的窗口名
screen -S dst -p 0 -X stuff "c_announce(\"北京时间:$(date +%H)点整\")$(printf \\r)"

例如文件名叫hourly_time.sh,且全路径为/home/guozhuang/hourly_time.sh

再次执行crontab -e命令,在文件结尾中添加一行内容:

1
0 * * * * /home/guozhuang/hourly_time.sh

然后保存即可

其中c_announce("xxx")是饥荒联机版原生支持的指令,表示向世界内宣告消息

更多控制台指令可参考饥荒wiki

8 常见问题

  • 启动失败
  • 重启后无模组
  • 大厅不展示
  • 几天后搜不到

  1. Steam控制台客户端 ↩︎

  2. Dedicated Server Quick Setup Guide - Linux ↩︎

  3. 专用服务器列表 ↩︎

  4. Dedicated Server Settings Guide ↩︎

  5. Dedicated Server Command Line Options Guide ↩︎ ↩︎

  6. 陈默的博客 ↩︎