目录

使用 steamcmd 搭建游戏服务器

警告
本文最后更新于 12-19,文中内容可能已过时。

和好友联机的时候本地服务器实在是不爽,一个人起飞,其他人都是高PING战士,最开始主要是 L4D2 时各种 RPG 服务器有些不爽,为了纯净的服务器只好自己建了

事先声明,我们所有的操作在 Debian / Ubuntu 下操作,有些操作系统可能会不一样,不过大同小异,我们还是定义一些等等可能用到的变量 (主要是路径和密码之类的

shell

steam=/home/steam
group_id=123456789
l4d2=${steam}/l4d2
l4d2_id=222860
l4d2_server_name="L4D2 Server"
l4d2_port=1024
valheim=${steam}/valheim
valheim_id=896660
valheim_server_name="Valheim Server"
valheim_world="World"
valheim_port=1024
valheim_passwd=valheim_password
dst=${steam}/dst
dst_id=343050

顾名思义,steamcmd 是一个命令行工具,同时支持 linux,是我们搭建服务器的好帮手,然而我不会用,不过这不重要,安装跑起来就好

shell

add-apt-repository multiverse
dpkg --add-architecture i386
apt update && apt upgrade
apt install -y lib32gcc1 steamcmd

我们不仅要安装一个 steamcmd,还要将所有游戏服务器,存放在 ~steam 下,使用 steam 这个用户来运行游戏

shell

adduser --disabled-login --gecos 'Steam' steam
sudo -u steam -H ln -s /usr/games/steamcmd ${steam}/steamcmd

这里说的语法并不是 SteamCMD 的语法,而是 Steam 中所使用的文本标记语法,这些标记标签允许您为您的留言及发帖文字添加格式,类似于 HTML,官方展示在这里

标签 释义 示例
h 标题 [h1]一级标题[/h1]
b 粗体 [b]粗体文本[/b]
u 下划线 [u]下划线文本[/u]
l 斜体 [l]斜体[/l]
strike 删除线 [strike]删除线文本[/strike]
spoiler 隐藏 [spoiler]隐藏文本[/spoiler]
noparse 不解析 [noparse]不解析[b]标签[/b][/noparse]
url 网络链接 [url=blog.ginshio.org]博客[/url]
Youtube / Shop / Workshop Widget https://store.steampowered.com/app/570
list 无序列表 [list] [*] 列表 [*] 列表 [/list]
olist 有序列表 [olist] [*] 列表 [*] 列表 [/olist]
quote 引用 [quote=author]引用文本[/quote]
code 等宽字体 (保留空格) [code]code[/code]

表格语法有点难度,tr 表示一行,th 表示一个单元格

text

[table]
[tr]
[th][/th]
[th]DST Memorandum[/th]
[th]Status Announcements[/th]
[th]Global Positions[/th]
[/tr]
[tr]
[th]DST Memorandum[/th]
[th][/th]
[th]Crash[/th]
[th]Crash[/th]
[/tr]
[tr]
[th]Status Announcements[/th]
[th]Crash[/th]
[th][/th]
[th]OK[/th]
[/tr]
[tr]
[th]Global Positions[/th]
[th]Crash[/th]
[th]OK[/th]
[th][/th]
[/tr]

可以做出一个这样的表格

DST Memorandum Status Announcements Global Positions
DST Memorandum Crash Crash
Status Announcements Crash OK
Global Positions Crash OK

如果遇到服务器无法启动,比如缺少 sdk32/libsteam.sosdk32/steamclient.so 之类的错误,需要完成以下操作

shell

sudo -u steam -H mkdir -p /home/steam/.steam/sdk32
sudo -u steam -H ln -s /home/steam/.steam/steamcmd/linux32/steamclient.so /home/steam/.steam/sdk32/steamclient.so
警告
L4D2 每次搭建都被 DDOS,已经不再维护

在搭建服务器之前,为了你的服务器着想,请先创建一个 Steam 组,将你们一起开黑的人都拉入组中,我们需要将服务器设置为组私有,只有组中的人才能使用

安装并对服务器进行配置,配置文件是 ${l4d2}/left4dead2/cfg/server.cfg

shell

sudo -u steam -H ${steam}/steamcmd +force_install_dir ${l4d2} +login anonymous +app_update ${l4d2_id} validate +quit
sudo -u steam -H cat <<- EOF > ${l4d2}/left4dead2/cfg/server.cfg
hostname "${l4d2_server_name}"       // 服务器名
hostport ${l4d2_port}                // 服务器端口
sv_tags "hidde,GinShio"              // 隐藏服务器
sv_gametypes "versus,survival,coop,realism,teamversus,teamscavenge" // 游戏类型
mp_gamemode "coop"
sv_cheats 0                          // 允许作弊
sv_voiceenable 1                     // 语音服务
sv_pausable 0                        // 暂停
sv_consistency 0                     // 一致性
sv_lan 0                             // 局域网游戏
sv_allow_lobby_connect_only 0        // 大厅连接
sv_region 4                          // 区域:亚洲
sv_visiblemaxplayers 4               // 最多人数上线:4 (4~32)
mp_disable_autokick 0                // 闲置踢出
sv_steamgroup "${group_id}"          // 根据自己的steam组ID绑定服务器
sv_steamgroup_exclusive 1            // 设置组私有化
exec banned_user.cfg
exec banned_ip.cfg
heartbeat
EOF

对于服务器公告,${l4d2}/left4dead2/host.txt 可以修改服务器公告的标题,而 ${l4d2}/left4dead2/motd.txt 修改的是公告的内容,我们可以在公告中使用之前列出的文本标记语法。对于第三方地图,我们只需要将地图存放在 {l4d2}/left4dead2/addons/workshop 中即可,不过记得将地图文件的权限转到 steam

个人喜欢使用 systemctl 来管理服务,这样觉得更安全些,所以我们完成一个 service 管理服务器,当然如果你想用 screen 可以自行搜索它的用法

text

[Unit]
Description=Left 4 Dead 2 Server
Documentation=https://left4dead.fandom.com/wiki/Left_4_Dead_Wiki
After=network.target

[Service]
Type=simple
User=steam
WorkingDirectory=/home/steam/l4d2
ExecStart=/home/steam/l4d2/srcds_run -game left4dead2 -autorestart +ip 0.0.0.0 +exec server.cfg
ExecReload=/bin/kill -HUP
Restart=on-failure
RestartPreventExitStatus=23

[Install]
WantedBy=multi-user.target

到这里,纯净的 l4d2 服务器就搭建好了,我并没有弄插件,也没有弄管理员,所以就到这里!

警告
该章节没有真正部署维护,且没有更新过,酌情参考

首先我们配置服务器,不过和 L4D2 的方式差不多,毕竟都是 SteamCMD,不废话,直接上 Shell 指令。需要注意的是,Valheim 将占用三个端口,即 valheim_portvalheim_port + 2,请在防火墙开启需要的全部三个端口

shell

sudo -u steam -H ${steam}/steamcmd +force_install_dir ${valheim} +login anonymous +app_update ${valheim_id} validate +quit
sudo -u steam -H cp ${valheim}/start_server.sh ${valheim}/start_server.sh.bkp
sudo -u steam -H cat <<- EOF > ${valheim}/start_server.sh
export templdpath=${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH=${valheim}/linux64:${LD_LIBRARY_PATH}
export SteamAppId=892970
echo "Starting server PRESS CTRL-C to exit"
${valheim}/valheim_server.x86_64 -name "${valheim_server_name}" -port ${valheim_port} -world "${valheim_world}" -password "${valheim_passwd}"
export LD_LIBRARY_PATH=$templdpath
EOF

搞定,整一个 service 让 systemd 帮我们管理服务器

text

[Unit]
Description=Valheim Server
After=network.target

[Service]
Type=simple
User=steam
WorkingDirectory=/home/steam/valheim
ExecStart=bash /home/steam/valheim/start_server.sh
ExecReload=/bin/kill -HUP
Restart=on-failure
RestartPreventExitStatus=23

[Install]
WantedBy=multi-user.target

好了,现在问题就是,你的服务器配置,请务必 2C4G5Mbps 及以上配置,要求真tm高,听说开发者只有5个人,,,

现在我们要征服永恒领域了,首先的问题就是搭建一个服务器。我们下载服务器很简单,就是一行用了很多遍的命令

shell

sudo -u steam -H ${steam}/steamcmd +force_install_dir ${dst} +login anonymous +app_update ${dst_id} validate +quit

下载好了当然没有用,我们需要去 Klei 官网 生成一份服务器 token。在 Games 一栏选择 DST Game Server 即可,输入 Cluster Name 添加生成服务器配置,还有 token,请务必保存好。

DST 服务器在运行时,全部数据都会存储在 $HOME/.klei 下,因此我们只需要常备份这个目录即可。饥荒服务器的目录结构如下:

text

├── Cluster1/
│    ├── cluster.ini
│    ├── cluster_token.txt
│    ├── Caves/
│    │    ├── server.ini
│    │    ├── leveldataoverride.lua
│    │    ├── modoverrides.lua
│    ├── Master/
│    │    ├── server.ini
│    │    ├── leveldataoverride.lua
│    │    ├── modoverrides.lua

这是一个完整的位面所需要配置的文件

  • cluster_token.txt 存储的是从 Klei 官网拿到的 token
  • cluster.ini 即这个位面的主配置,主要配置游戏模式、游戏人数、服务器名、密码、 steam 组等等
  • Master/server.iniCaves/server.ini 配置基本相同,主要是世界的端口号和主次世界设置
  • modoverrides.lua 配置开启的 mod 的设置
  • leveldataoverride.lua 配置这个世界的资源、设置

另外在安装目录中有个 mods 的目录,其中可以添加服务器模组,当然仅仅是安装到服务器上。用不用还是需要看世界中 modoverrides.lua 的设置。

如果需要详细设置哪些人为管理员,可以在目录下添加 adminlist.txt 文件,文件中使用 Klei Account ID 区分玩家。如果你不知道 ID 的话可以在启动服务器后生成的 server_log.txtserver_chat_log.txt 中查找。这两个文件在启动对应的世界后在目录下生成。

基本上在 Klei 官网所生成的 cluster.inicluster_token.txt 基本够用了,额外需要注意的是如果需要设置为组服务器

text

[STEAM]
steam_group_admins=false  # 设置组成员是否为管理员,接受 true / false
steam_group_id=123456789  # 设置组 id
steam_group_only=true     # 设置是否仅组成员可用,接受 true / false

至于 server.ini 则分别在世界的目录下,基本无需多修改 (除非多个世界分主次或改端口)

DST 服务器最复杂的是世界设置文件,可以先在自己电脑上配置好你想要的世界设置,还有服务器 mod,然后把它们复制进对应的世界目录就好了。

当然还可以自己手动修改配置文件,比如说 Maxwell 雕像的数量、虫洞类型等等在界面无法修改的东西。

  • 地上世界基础配置文件

    lua

    return {
      desc="The standard Don't Starve experience.",
      hideminimap=false,
      id="SURVIVAL_TOGETHER",
      location="forest",
      max_playlist_position=999,
      min_playlist_position=0,
      name="Survival",
      numrandom_set_pieces=4,  -- 雕像的数量
      override_level_string=false,
      overrides={
        -- 资源设置的可选项分别为:
        ----- "never"    无
        ----- "rare"     较少
        ----- "default"  默认
        ----- "often"    较多
        ----- "always"   大量
    
        -- 全局设置
        specialevent="default",         --- 特殊事件: none (无); default (自动)
        crow_carnival="default",        --- 盛夏鸦年华: default (自动); enabled (启用)
        hallowed_nights="default",      --- 万圣之夜: default (自动); enabled (启用)
        winters_feast="default",        --- 冬季盛宴: default (自动); enabled (启用)
        year_of_the_gobbler="default",  --- 火鸡之年: default (自动); enabled (启用)
        year_of_the_varg="default",     --- 座狼之年: default (自动); enabled (启用)
        year_of_the_pig="default",      --- 猪王之年: default (自动); enabled (启用)
        year_of_the_carrat="default",   --- 胡萝卜鼠之年: default (自动); enabled (启用)
        year_of_the_beefalo="default",  --- 皮弗娄牛之年: default (自动); enabled (启用)
        year_of_the_catcoon="default",  --- 浣猫之年: default (自动); enabled (启用)
        autumn="default",  --- 秋季: noseason (无季节, 0); veryshortseason (非常短, 5); shortseason (较短, 12);
                           ---       default (默认长度, 20); longseason (较长, 30); verylongseason (非常长, 50); random
        winter="default",  --- 冬季: noseason (无季节, 0); veryshortseason (非常短, 5); shortseason (较短, 10);
                           ---       default (默认长度, 15); longseason (较长, 22); verylongseason (非常长, 40); random
        spring="default",  --- 春季: noseason (无季节, 0); veryshortseason (非常短, 5); shortseason (较短, 12);
                           ---       default (默认长度, 20); longseason (较长, 30); verylongseason (非常长, 50); random
        summer="default",  --- 夏季, noseason (无季节, 0); veryshortseason (非常短, 5); shortseason (较短, 10);
                           ---       default (默认长度, 15); longseason (较长, 22); verylongseason (非常长, 40); random
        day="default",     --- 天类型: default (默认);
                           ---         longday (加长白天); longdusk (加长黄昏); longnight (加长黑夜);
                           ---         noday (无白天); nodusk (无黄昏); nonight (无黑夜);
                           ---         onlyday (只有白天); onlydusk (只有黄昏); onlynight (只有黑夜)
        spawnmode="fixed",          --- 出生点: fixed (固定大门); scatter (随机)
        ghostenabled="always",      --- 死亡变为鬼魂: none (关闭); always (启用)
        portalresurection="none",   --- 大门复活: none (关闭); always (启用)
        ghostsanitydrain="always",  --- 队友死亡扣除精神: none (关闭); always (启用)
        resettime="default",        --- 死亡重置时间: none (无); slow (慢); default (正常); fast (快); always (非常快)
        beefaloheat="default",      --- 野牛发情
        krampus="default",          --- 坎普斯
    
        -- 求生者设置
        extrastartingitems="default",       --- 额外起始资源: 0 (总是); 5 (5 天后); default (10 天后); 15 (15 天后); 20 (20 天后); none (从不)
        seasonalstartingitems="default",    --- 季节起始物品: never; default
        spawnprotection="default",          --- 出生保护: never (无); default (自动); always (总是)
        dropeverythingondespawn="default",  --- 退出掉落物品: default (默认); always (所有)
        healthpenalty="always",             --- 生命惩罚: none (关闭); always (启用)
        lessdamagetaken="none",             --- 伤害减免: always (减免); none (无); more (增加)
        temperaturedamage="default",        --- 温度伤害: default (默认); nonlethal (非致命)
        hunger="default",                   --- 饥饿伤害: default (默认); nonlethal (非致命)
        darkness="default",                 --- 黑暗伤害: default (默认); nonlethal (非致命)
        brightmarecreatures="default",      --- 启蒙怪兽数量
        shadowcreatures="default",          --- 理智怪兽数量
    
        -- 世界设置
        petrification="default",  --- 石化: none (无); few (慢); default (默认); many (快); max (极快)
        frograin="default",       --- 蛙雨
        hounds="default",         --- 猎犬来袭频率
        summerhounds="default",   --- 火狗: never (禁止); default (默认)
        winterhounds="default",   --- 冰狗: never (禁止); default (默认)
        alternatehunt="default",  --- 追猎惊喜
        hunt="default",           --- 狩猎
        lightning="default",      --- 闪电
        meteorshowers="default",  --- 流星
        weather="default",        --- 雨
        wildfires="default",      --- 野火
    
        -- 资源再生的可选项分别为:
        ----- "never"     从不
        ----- "veryslow"  非常慢
        ----- "slow"      缓慢
        ----- "default"   默认
        ----- "fast"      快速
        ----- "veryfast"  非常快
    
        -- 资源再生设置
        regrowth="default",                --- 再生速度
        basicresource_regrowth="always",   --- 基础资源再生: none (关闭); always (启用)
        deciduoustree_regrowth="default",  --- 桦栗树再生
        cactus_regrowth="default",         --- 仙人掌再生
        carrots_regrowth="default",        --- 胡萝卜再生
        evergreen_regrowth="default",      --- 常青树再生
        flowers_regrowth="default",        --- 花再生
        moon_tree_regrowth="default",      --- 月树再生
        palmconetree_regrowth="default",   --- 棕榈树再生
        reeds_regrowth="default",          --- 芦苇再生
        saltstack_regrowth="default",      --- 盐矿再生
        twiggytrees_regrowth="default",    --- 多枝树再生
    
        -- 非自然传送门设置
        bananabush_portalrate="default",     --- 香蕉从
        lightcrab_portalrate="default",      --- 光蟹
        monkeytail_portalrate="default",     --- 猴尾草
        palmcone_seed_portalrate="default",  --- 棕榈树种子
        portal_spawnrate="default",          --- 传送频率
        powder_monkey_portalrate="default",  --- 粉猴
    
        -- 生物设置
        bees_setting="default",      --- 蜜蜂
        birds="default",             --- 鸟
        bunnymen_setting="default",  --- 兔人
        butterfly="default",         --- 蝴蝶
        catcoons="default",          --- 浣猫
        gnarwail="default",          --- 一角鲸
        perd="default",              --- 火鸡
        grassgekkos="default",       --- 草蜥蜴
        moles_setting="default",     --- 鼹鼠
        penguins="default",          --- 企鹅
        pigs_setting="default",      --- 猪人
        rabbits_setting="default",   --- 兔子
        fishschools="default",       --- 鱼群
        wobsters="default",          --- 龙虾
    
        -- 敌对生物设置
        bats_setting="default",     --- 蝙蝠
        cookiecutters="default",    --- 饼干切割机
        frogs="default",            --- 青蛙
        mutated_hounds="default",   --- 恐怖猎犬: never; default
        hound_mounds="default",     --- 猎犬
        wasps="default",            --- 杀人蜂
        lureplants="default",       --- 食人花
        walrus_setting="default",   --- 海象
        merms="default",            --- 鱼人
        pirateraids="default",      --- 掠夺者
        penguins_moon="default",    --- 月石企鹅: never; default
        mosquitos="default",        --- 蚊子
        sharks="default",           --- 鲨鱼
        moon_spider="default",      --- 破碎蜘蛛
        squid="default",            --- 乌贼
        spider_warriors="default",  --- 蜘蛛战士: never; default
        spiders_setting="default",  --- 蜘蛛
    
        -- 巨型生物设置
        antliontribute="default",    --- 蚁狮
        bearger="default",           --- 熊獾
        beequeen="default",          --- 蜂后
        crabking="default",          --- 帝王蟹
        deerclops="default",         --- 独眼巨鹿
        dragonfly="default",         --- 龙蝇
        eyeofterror="default",       --- 泰拉瑞亚之眼
        klaus="default",             --- 克劳斯
        fruitfly="default",          --- 果蝇王
        malbatross="default",        --- 邪天翁
        goosemoose="default",        --- 麋鹿鹅
        deciduousmonster="default",  --- 毒桦栗树
        spiderqueen="default",       --- 蜘蛛女王
        liefs="default",             --- 树精守卫
    
    
    
    
    
        -- 世界生成中等级分别为:
        ----- "never"      无
        ----- "uncommon"   很少
        ----- "rare"       较少
        ----- "default"    默认
        ----- "often"      较多
        ----- "mostly"     很多
        ----- "always"     大量
        ----- "insane"     疯狂
    
        -- 全局生成
        --- 起始季节
        ----- "default"                      秋
        ----- "winter"                       冬
        ----- "spring"                       春
        ----- "summer"                       夏
        ----- "autumn|spring"                秋或春
        ----- "winter|summer"                冬或夏
        ----- "autumn|winter|spring|summer"  随机
        season_start="default",
    
        -- 世界生成
        task_set="default",           --- 生物群落: default (联机版); classic (经典)
        start_location="default",     --- 出生区域: plus (额外资源); darkness (黑暗); default (默认)
        world_size="default",         --- 世界大小: small (小); medium (中); default (大); huge (巨大)
        branching="default",          --- 世界分支: never (从不); least (少); default (默认); most (多); random (随机)
        loop="default",               --- 环形世界: never (从不); default (默认); always (总是)
        roads="default",              --- 道路: never (无); default (有)
        touchstone="default",         --- 试金石
        boons="default",              --- 前辈
        prefabswaps_start="default",  --- 初始资源多样化: classic (经典); default (默认); highly random (随机)
        moon_fissure="default",       --- 天体裂隙
        stageplays="default",         --- 舞台: never (无); default (有)
        terrariumchest="default",     --- 泰拉瑞亚: never (无); default (有)
        wormhole_prefab="wormhole",   --- 虫洞多样性: wormhole (虫洞); tentacle_pillar (巨大触手)
    
        -- 资源
        moon_starfish="default",         --- 海星
        moon_bullkelp="default",         --- 公牛海带茎
        berrybush="default",             --- 浆果从
        rock="default",                  --- 岩石
        ocean_bullkelp="default",        --- 公牛海带
        cactus="default",                --- 仙人掌
        carrot="default",                --- 胡萝卜
        flint="default",                 --- 燧石
        flowers="default",               --- 花
        grass="default",                 --- 草
        moon_hotspring="default",        --- 温泉
        moon_rock="default",             --- 月亮石
        moon_sapling="default",          --- 月亮树苗
        moon_tree="default",             --- 月树
        meteorspawner="default",         --- 流星区
        rock_ice="default",              --- 迷你冰川
        mushroom="default",              --- 蘑菇
        palmconetree="default",          --- 棕榈树
        ponds="default",                 --- 池塘
        reeds="default",                 --- 芦苇
        sapling="default",               --- 小树苗
        ocean_seastack="ocean_default",  --- 海矿
        marshbush="default",             --- 荆棘树枝
        moon_berrybush="default",        --- 石果树
        trees="default",                 --- 树 (所有)
        tumbleweed="default",            --- 风滚草
    
        -- 生物及刷新点
        bees="default",               --- 蜂巢
        beefalo="default",            --- 皮弗娄牛
        buzzard="default",            --- 秃鸠
        moon_carrot="default",        --- 胡萝卜鼠
        catcoon="default",            --- 猫桩
        moles="default",              --- 鼹鼠洞
        pigs="default",               --- 猪人房
        rabbits="default",            --- 兔子洞
        moon_fruitdragon="default",   --- 沙拉蝾螈
        ocean_shoal="default",        --- 鱼群
        lightninggoat="default",      --- 伏特羊
        ocean_wobsterden="default",   --- 龙虾窝
    
        -- 敌对生物及刷新点
        chess="default",                   --- 发条装置
        houndmound="default",              --- 猎犬冢
        angrybees="default",               --- 杀人蜂巢
        merm="default",                    --- 漏雨的小屋
        walrus="default",                  --- 海象营地
        ocean_waterplant="ocean_default",  --- 海草
        moon_spiders="default",            --- 破碎蜘蛛洞
        spiders="default",                 --- 蜘蛛巢
        tallbirds="default",               --- 高脚鸟巢
        tentacles="default",               --- 触手
    
    
    
        -- Other
        has_ocean=true,
        keep_disconnected_tiles=true,
        layout_mode="LinkNodesByKeys",
        no_joining_islands=true,
        no_wormholes_to_disconnected_tiles=true
      },
      playstyle="survival",
      random_set_pieces={
        "Sculptures_1",  -- 完整的三棋子
        "Sculptures_2",
        "Sculptures_3",
        "Sculptures_4",
        "Sculptures_5",
        "Chessy_1",      -- 2发条骑士,2齿轮,长矛,棋盘地皮
        "Chessy_2",      -- 2发条主教,棋盘、牛毛地皮,Maxwell 雕像,(2齿轮)
        "Chessy_3",      -- 发条战车,蜂蜜药膏,背包,棋盘、牛毛地皮
        "Chessy_4",      -- 发条战车,2大理石,鹤嘴锄,2大理石柱,1大理石树,棋盘、牛毛地皮,Maxwell 雕像
        "Chessy_5",      -- 1发条骑士,1发条主教,竖琴雕像,棋盘、牛毛地皮
        "Chessy_6",      -- 1发条骑士,1发条主教,棋盘、牛毛地皮
        "Maxwell1",      -- 1发条战车,3发条骑士,棋盘、牛毛地皮,4大理石柱,9大理石树,大量恶魔花
        "Maxwell2",      -- 1发条战车,4发条骑士,棋盘、牛毛地皮,8大理石树,Maxwell 雕像
        "Maxwell3",      -- 5发条骑士,棋盘、牛毛地皮,Maxwell 雕像
        "Maxwell4",      -- 棋盘、牛毛地皮,8大理石树,Maxwell 雕像
        "Maxwell5",      -- 1发条骑士,牛毛地皮,8竖琴雕像,Maxwell 雕像,少量恶魔花
        "Maxwell6",      -- 5大理石树,牛毛地皮
        "Maxwell7",      -- 2发条骑士,棋盘、牛毛地皮,4大理石树,Maxwell 雕像,少量恶魔花
        "Warzone_1",
        "Warzone_2",
        "Warzone_3",
      },
      required_prefabs={ "multiplayer_portal" },
      required_setpieces={ "Sculptures_1" },  -- 必须包含的雕像种类
      settings_desc="The standard Don't Starve experience.",
      settings_id="SURVIVAL_TOGETHER",
      settings_name="Survival",
      substitutes={  },
      version=4,
      worldgen_desc="The standard Don't Starve experience.",
      worldgen_id="SURVIVAL_TOGETHER",
      worldgen_name="Standard Forest"
    }
  • 地下世界基础配置文件

    lua

    return {
      background_node_range={ 0, 1 },
      desc="Delve into the caves... together!",
      hideminimap=false,
      id="DST_CAVE",
      location="cave",
      max_playlist_position=999,
      min_playlist_position=0,
      name="The Caves",
      numrandom_set_pieces=0,
      override_level_string=false,
      overrides={
        -- 资源设置的可选项分别为:
        ----- "never"    无
        ----- "rare"     较少
        ----- "default"  默认
        ----- "often"    较多
        ----- "always"   大量
    
        -- 资源再生的可选项分别为:
        ----- "never"     从不
        ----- "veryslow"  非常慢
        ----- "slow"      缓慢
        ----- "default"   默认
        ----- "fast"      快速
        ----- "veryfast"  非常快
    
        -- 世界设置
        specialevent="default",         --- 特殊事件: none (无); default (自动)
        crow_carnival="default",        --- 盛夏鸦年华: default (自动); enabled (启用)
        hallowed_nights="default",      --- 万圣之夜: default (自动); enabled (启用)
        winters_feast="default",        --- 冬季盛宴: default (自动); enabled (启用)
        year_of_the_gobbler="default",  --- 火鸡之年: default (自动); enabled (启用)
        year_of_the_varg="default",     --- 座狼之年: default (自动); enabled (启用)
        year_of_the_pig="default",      --- 猪王之年: default (自动); enabled (启用)
        year_of_the_carrat="default",   --- 胡萝卜鼠之年: default (自动); enabled (启用)
        year_of_the_beefalo="default",  --- 皮弗娄牛之年: default (自动); enabled (启用)
        year_of_the_catcoon="default",  --- 浣猫之年: default (自动); enabled (启用)
        autumn="default",  --- 秋季: noseason (无季节, 0); veryshortseason (非常短, 5); shortseason (较短, 12);
                           ---       default (默认长度, 20); longseason (较长, 30); verylongseason (非常长, 50); random
        winter="default",  --- 冬季: noseason (无季节, 0); veryshortseason (非常短, 5); shortseason (较短, 10);
                           ---       default (默认长度, 15); longseason (较长, 22); verylongseason (非常长, 40); random
        spring="default",  --- 春季: noseason (无季节, 0); veryshortseason (非常短, 5); shortseason (较短, 12);
                           ---       default (默认长度, 20); longseason (较长, 30); verylongseason (非常长, 50); random
        summer="default",  --- 夏季, noseason (无季节, 0); veryshortseason (非常短, 5); shortseason (较短, 10);
                           ---       default (默认长度, 15); longseason (较长, 22); verylongseason (非常长, 40); random
        day="default",     --- 天类型: default (默认);
                           ---         longday (加长白天); longdusk (加长黄昏); longnight (加长黑夜);
                           ---         noday (无白天); nodusk (无黄昏); nonight (无黑夜);
                           ---         onlyday (只有白天); onlydusk (只有黄昏); onlynight (只有黑夜)
        spawnmode="fixed",          --- 出生点: fixed (固定大门); scatter (随机)
        ghostenabled="always",      --- 死亡变为鬼魂: none (关闭); always (启用)
        portalresurection="none",   --- 大门复活: none (关闭); always (启用)
        ghostsanitydrain="always",  --- 队友死亡扣除精神: none (关闭); always (启用)
        resettime="default",        --- 死亡重置时间: none (无); slow (慢); default (正常); fast (快); always (非常快)
        beefaloheat="default",      --- 野牛发情
        krampus="default",          --- 坎普斯
        atriumgate="default",       --- 中庭大门重置 (不可置为 never)
        wormattacks="default",      --- 深渊蠕虫攻击
        earthquakes="default",      --- 地震
        weather="default",          --- 漏雨
    
        -- 求生者设置
        extrastartingitems="default",       --- 额外起始资源: 0 (总是); 5 (5 天后); default (10 天后); 15 (15 天后); 20 (20 天后); none (从不)
        seasonalstartingitems="default",    --- 季节起始物品: never; default
        spawnprotection="default",          --- 出生保护: never (无); default (自动); always (总是)
        dropeverythingondespawn="default",  --- 退出掉落物品: default (默认); always (所有)
        healthpenalty="always",             --- 生命惩罚: none (关闭); always (启用)
        lessdamagetaken="none",             --- 伤害减免: always (减免); none (无); more (增加)
        temperaturedamage="default",        --- 温度伤害: default (默认); nonlethal (非致命)
        hunger="default",                   --- 饥饿伤害: default (默认); nonlethal (非致命)
        darkness="default",                 --- 黑暗伤害: default (默认); nonlethal (非致命)
        brightmarecreatures="default",      --- 启蒙怪兽数量
        shadowcreatures="default",          --- 理智怪兽数量
    
        -- 资源再生设置
        regrowth="default",                     --- 再生速度
        basicresource_regrowth="always",        --- 基础资源再生: none (关闭); always (启用)
        flower_cave_regrowth="default",         --- 荧光果再生
        lightflier_flower_regrowth="default",   --- 变异荧光果再生
        mushtree_moon_regrowth="default",       --- 变异蘑菇树再生
        mushtree_regrowth="default",            --- 蘑菇树再生
    
        -- 生物设置
        lightfliers="default",        --- 球状光虫
        bunnymen_setting="default",   --- 兔人
        dustmoths="default",          --- 尘蛾
        grassgekkos="default",        --- 草蜥蜴
        moles_setting="default",      --- 鼹鼠
        mushgnome="default",          --- 蘑菇地精
        pigs_setting="default",       --- 猪人
        rocky_setting="default",      --- 石虾
        slurtles_setting="default",   --- 蛞蝓龟
        snurtles="default",           --- 蜗牛龟
        monkey_setting="default",     --- 穴居猴
    
        -- 敌对生物设置
        bats_setting="default",         --- 蝙蝠
        spider_hider="default",         --- 洞穴蜘蛛
        spider_dropper="default",       --- 穴居蜘蛛
        merms="default",                --- 鱼人
        molebats="default",             --- 裸鼹鼠蝙蝠
        nightmarecreatures="default",   --- 暴动暗影生物
        spider_warriors="default",      --- 蜘蛛战士: never; default
        spiders_setting="default",      --- 蜘蛛
        spider_spitter="default",       --- 喷吐蜘蛛
    
        -- 巨型生物设置
        fruitfly="default",      --- 果蝇王
        spiderqueen="default",   --- 蜘蛛女王
        liefs="default",         --- 树精守卫
        toadstool="default",     --- 毒菌蟾蜍
    
    
    
    
    
        -- 世界生成中等级分别为:
        ----- "never"      无
        ----- "uncommon"   很少
        ----- "rare"       较少
        ----- "default"    默认
        ----- "often"      较多
        ----- "mostly"     很多
        ----- "always"     大量
        ----- "insane"     疯狂
    
        -- 全局生成
        --- 起始季节
        ----- "default"                      秋
        ----- "winter"                       冬
        ----- "spring"                       春
        ----- "summer"                       夏
        ----- "autumn|spring"                秋或春
        ----- "winter|summer"                冬或夏
        ----- "autumn|winter|spring|summer"  随机
        season_start="default",
    
        -- 世界生成
        task_set="cave_default",             --- 生物群落, 仅 "cave_default"
        start_location="caves",              --- 出生点, 仅 "caves"
        world_size="default",                --- 世界大小: small (小); medium (中); default (大); huge (巨大)
        branching="default",                 --- 世界分支: never (从不); least (少); default (默认); most (多); random (随机)
        loop="default",                      --- 环形世界: never (从不); default (默认); always (总是)
        roads="never",                       --- 道路: never (无); default (有)
        touchstone="default",                --- 试金石
        boons="default",                     --- 前辈
        cavelight="default",                 --- 洞穴光, 值同资源再生选项
        prefabswaps_start="default",         --- 初始资源多样化: classic (经典); default (默认); highly random (随机)
        wormhole_prefab="tentacle_pillar",   --- 虫洞多样性: wormhole (虫洞); tentacle_pillar (巨大触手)
    
        -- 资源
        banana="default",        --- 洞穴香蕉
        berrybush="default",     --- 浆果从
        rock="default",          --- 岩石
        fern="default",          --- 洞穴苔藓
        flint="default",         --- 燧石
        wormlights="default",    --- 发光浆果
        grass="default",         --- 草
        lichen="default",        --- 蓝色菌藻
        flower_cave="default",   --- 荧光果
        mushtree="default",      --- 蘑菇树
        mushroom="default",      --- 蘑菇
        cave_ponds="default",    --- 池塘
        reeds="default",         --- 芦苇
        sapling="default",       --- 小树苗
        marshbush="default",     --- 荆棘树枝
        trees="default",         --- 树 (所有)
    
        -- 生物及刷新点
        bunnymen="default",   --- 兔人房
        rocky="default",      --- 石虾窝
        slurper="default",    --- 啜食兽
        slurtles="default",   --- 蛞蝓丘
        monkey="default",     --- 穴居猴窟
    
        -- 敌对生物及刷新点
        bats="default",           --- 蝙蝠洞
        worms="default",          --- 深渊蠕虫
        chess="default",          --- 发条装置
        fissure="default",        --- 远古裂隙
        spiders="default",        --- 蜘蛛巢
        cave_spiders="default",   --- 石笋蛛巢
        tentacles="default",      --- 触手
    
    
    
        -- Other
        layout_mode="RestrictNodesByKey"
      },
      required_prefabs={ "multiplayer_portal" },
      settings_desc="Delve into the caves... together!",
      settings_id="DST_CAVE",
      settings_name="The Caves",
      substitutes={  },
      version=4,
      worldgen_desc="Delve into the caves... together!",
      worldgen_id="DST_CAVE",
      worldgen_name="The Caves"
    }

说明一下,测试时发现地下修改为虫洞,而非大触手时,跳虫洞将导致服务器崩溃。使用了服务器虫洞着色插件 wormhole marks,目前不清楚是 mod 问题还是游戏本身问题。

个人十分喜欢利用 systemd 来管理这些服务器的启停,使用 systemd 首先需要知道 DST 服务器的命令行参数。

  • console 指示这个服务器可以使用控制台
  • persistent_storage_root 指定世界位面存储在什么地方,默认存在于 $HOME/.klei,个人不推荐修改默认目录
  • conf_dir 指定使用哪个位面的配置目录。默认目录为 DoNotStarveTogether,简单来说一个配置目录中有多个 ClusterNum 组成,如果想开多个完全不同的服务器,可以使用该参数修改路径
  • shard 指定启动哪个世界,一般为地上、地下世界的启动指示,当然不排除你一个位面中存在多个地上世界

我的个人服务器就用到了这些参数,一般来说够用了。接下来就是期待的 systemd 示例!

text

[Unit]
Description=GinShio's Don't Starve Together Server
Documentation=https://dontstarve.fandom.com/wiki/Don't_Starve_Wiki
After=network.target

[Service]
Type=simple
User=steam
WorkingDirectory=/home/steam/dst/bin64
TimeoutStartSec=infinity
ExecStart=/home/steam/dst/bin64/dontstarve_dedicated_server_nullrenderer_x64 -console -conf_dir %i -shard Master
ExecStartPost=/home/steam/dst/bin64/dontstarve_dedicated_server_nullrenderer_x64 -console -conf_dir %i -shard Caves
ExecReload=/bin/kill -HUP
Restart=on-failure
RestartPreventExitStatus=23

[Install]
WantedBy=multi-user.target

我所使用的是 dst@.service,这样只需要在启动不同位面时,在 @ 之后加上目录名即可。由于 ExecStartPost 是启动地下世界,这是一个 simple 类型的命令,所以需要设置超时时间为无限 (即 TimeoutStartSec=infinity 来保证 systemd 不会杀掉服务器)。同时也是这个原因,在 start 时并不会结束命令,所以我一般重启服务器利用关机重启来重启这个命令。

举个例子,我有一个冬季盛宴位面在 Winter 目录下,一个万圣节位面在 Dracula 目录下。我想关停万圣节位面关停冬季盛宴位面,即可使用以下命令

shell

systemctl disable dst@Winter   # 开机不启动冬季盛宴位面
systemctl disable dst@Dracula  # 开机启动万圣节位面
systemctl reboot               # 关机重启服务器
  • steamcmd ILocalize::AddFile() failed to load file "public/steambootstrapper_english.txt".

    shell

    steamcmd --reset
  • 找不到 libcurl-gnutls

    shell

    ln -s /usr/lib64/libcurl.so.4 /usr/lib64/libcurl-gnutls.so.4

自己写了一个启动 (run) / 停止 (stop) / 更新 (update) / 清除(clean) / 备份 (backup) 的 fish-shell 小脚本,方便对分离式服务器进行操作。相比 systemd 的方式,缺点就是开机自启以及守护进程没有了,需要频繁登录服务器。好处是更灵活了,你可以用 systemd 来管理这个脚本。或者频繁登录服务器来操作该脚本。或许 CI 是个好方法。

fish

set steam     /home/steam
set base_path $steam/dst
set work_path $base_path/bin64
set conf_path $steam/.klei
set dst_id    343050

function get_servers
    ls -l ~steam/.klei/ |grep -Ev "(Agreements)" |grep "drwxr-xr-x" |awk '{print $9}'
end

function mylist
    for s in (get_servers)
        echo -n (set_color magenta)"$s"(set_color normal)
        set get_status (ps aux |grep -P "^(?=.*dontstarve_dedicated)(?=.*$s)"|grep -v "grep")
        if test "" = "$get_status"
            echo -e "\t\t\t" (set_color red)"stop"(set_color normal)
        else
            echo -e "\t\t\t" (set_color green)"run"(set_color normal)
        end
    end
end

function mybackup
    cd $conf_path
    set --local flag
    if test "" = "$argv"
        set flag false
    else
        set flag true
    end
    set --local time_string (date --iso-8601=seconds |sed "s/:/-/g" -)
    for s in (get_servers)
        if $flag; and test "$s" != "$argv"
            continue
        end
        echo "tar -cvf - $s/* |xz -9 --threads=0 --block-size=128MiB --lzma2=dict=768MiB -c > DST_$s""_$time_string.tar.xz" |sudo -u steam fish
    end
end

function myrun
    cd $work_path
    # echo "Passwd" |
    sudo -u steam "$work_path"/dontstarve_dedicated_server_nullrenderer_x64 -console -persistent_storage_root "$conf_path" -conf_dir $argv -shard Master &
    sudo -u steam "$work_path"/dontstarve_dedicated_server_nullrenderer_x64 -console -persistent_storage_root "$conf_path" -conf_dir $argv -shard Caves &
end

function mystop
    # echo "Passwd" |
    sudo -u steam kill -9 (ps aux |grep -P "^(?=.*dontstarve_dedicated)(?=.*$argv)" |awk '{print $2}')
end

function myupdate
    # echo "Passwd" |
    sudo -u steam $steam/steamcmd +force_install_dir $base_path +login anonymous +app_update $dst_id validate +quit
    sudo -u steam cp $conf_path/dedicated_server_mods_setup.lua $base_path/mods/
end

function myclean
    cd $conf_path
    set --local master $conf_path/$argv/Cluster_1/Master
    set --local caves  $conf_path/$argv/Cluster_1/Caves
    # echo "Passwd" |
    sudo -u steam rm -rf $master/backup/ $master/save/ $master/*.txt
    sudo -u steam rm -rf $caves/backup/  $caves/save/  $caves/*.txt
end

function myparse
    argparse 'h/help' 'r/run=!' 's/stop=?' 'u/update' 'l/list' 'b/backup=?' 'C/clean=!' -- $argv
    if set --query _flag_h
        printf "Usage: script [OPTIONS]\n\n"
        printf "Options:\n"
        printf "    -h/--help               Prints help and exits\n"
        printf "    -r/--run=STRING         Run A Server\n"
        printf "    -s/--stop[=STRING]      Stop Servers\n"
        printf "    -u/--update             Stop && Update Servers\n"
        printf "    -l/--list               List All Servers\n"
        printf "    -b/--backup[=STRING]    Backup Server[s]\n"
        printf "    -C/--clean=STRING       Clean A Server\n"
        return 0
    end

    if set --query _flag_list
        mylist
        return 0
    end

    if set --query _flag_backup
        mybackup $_flag_backup
        return 0
    end

    if set --query _flag_run
        myrun $_flag_run
        return 0
    end

    if set --query _flag_stop
        mystop $_flag_stop
        return 0
    end

    if set --query _flag_update
        mystop
        myupdate
        return 0
    end

    if set --query _flag_clean
        myclean $_flag_clean
        return 0
    end
end

myparse $argv