用python程序快速搭建饥荒专用服务器(ubuntu)

这几天阿里云通过学生认证给了300免费额度,于是白嫖了几个月的2核2G轻量服务器。

心血来潮又拿来搭了饥荒服务器,然后写了一段python程序,省的每次都得从头再来。

应该已经有类似的快速搭建工具了,但是还是闲着没事自己写了一个。

参考:搭建饥荒服务器(2024.1) - 知乎 (zhihu.com)

修改:2.21-----修复了上传存档时解压报错的问题

目录

前提条件

编写服务器启动程序

服务器搭建主程序

开始搭建

其它


前提条件

1. linux ubuntu服务器,内存不少于2G(勉强可以5个人)。

2. 服务器设置为通过密码登录。

3. 一个本地建立的完整饥荒存档,已经设置好了各类参数和mod。

编写服务器启动程序

以下代码命名为startup.sh

#!/bin/bash

steamcmd_dir="$HOME/steamcmd"
install_dir="$HOME/dontstarvetogether_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"
                            check_for_file "$install_dir/bin"

                            cd "$install_dir/bin" || fail

                            run_shared=(./dontstarve_dedicated_server_nullrenderer)
                            run_shared+=(-console)
                            run_shared+=(-cluster "$cluster_name")
                            run_shared+=(-monitor_parent_process $$)
                            run_shared+=(-shard)

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

服务器搭建主程序

以下代码随便命名,以.py结尾, 导入的库没有的话就自己pip下载吧。

修改开头的user host token password等参数,然后和上一个程序放在同一个目录下。

from fabric import Connection
import shutil
import re
import os
import time
import tkinter as tk
from tkinter import filedialog,messagebox

user = "root" #设置你的登录名,最好是以root方式,否则可能出问题
host = "" #设置服务器IP地址
token="" #设置你的饥荒服务器token,在游戏官网获取,详见参考

password="" #设置服务器密码
swap_p=30 #设置swappiness,内存比较大可以小一点
swap_size=2048 #设置swap大小,以M为单位

global Cluster_name
Cluster_name=""
def check_swap(c):
    # 利用run方法直接执行传入的命令
    print("\n # 当前swap分区:")
    output=c.run('swapon').stdout
    print("\n # 当前swap分区开始使用的内存占用比:")
    output=c.run('cat /proc/sys/vm/swappiness').stdout
    
def change_swappiness(c,swap_p):
    output=c.run('cat /etc/sysctl.conf', hide=True).stdout
    if "vm.swappiness" in output:
        #去除原来的vm.swappiness行
        output=c.run('sed -i "/vm.swappiness/d" /etc/sysctl.conf', hide=True).stdout
    #在文件开头添加新的vm.swappiness行
    output=c.run('sed -i "1i vm.swappiness = '+str(swap_p)+'" /etc/sysctl.conf', hide=True).stdout
    #重新加载sysctl.conf文件
    output=c.run('sysctl -p', hide=True).stdout
        
        
def change_swapsize(c,swap_size):
    output=c.run('sudo swapoff -v /mnt/swap', hide=True).stdout
    output=c.run('sudo dd if=/dev/zero of=/mnt/swap bs=1M count='+str(swap_size)).stdout
    output=c.run('sudo chmod 600 /mnt/swap').stdout
    output=c.run('sudo mkswap /mnt/swap').stdout
    output=c.run('sudo swapon /mnt/swap').stdout   
        
def check_server_f(c):
    # 利用run方法直接执行传入的命令
    output=c.run('ps -ef | grep dontstarve', hide=True).stdout
    if "dontstarve_dedicated_server_nullrenderer" in output:
        print('\n # 服务器已经启动')
        return True
    else:
        print('\n # 服务器未启动')
        return False

def check_server(c):
    # 利用run方法直接执行传入的命令
    output=c.run('ps -ef | grep dontstarve', hide=True).stdout
    if "dontstarve_dedicated_server_nullrenderer" in output:
        return True
    else:
        return False
    
def restart_server(c):
    stop_server(c)
    while check_server(c):
        time.sleep(1)
        pass
    start_server(c)

def start_server(c):
    # 利用run方法直接执行传入的命令
    if check_server(c):
        print('\n # 服务器已经启动,无法再次启动')
        return
    output=c.run('nohup ~/startup.sh>root.log 2>&1 &').stdout
    print('\n # 服务器已启动')
    
def stop_server(c):
    if not check_server(c):
        print('\n # 服务器未运行,无法停止')
        return
    # 利用run方法直接执行传入的命令
    output=c.run('pkill -f dontstarve_dedicated_server_nullrenderer').stdout
    print('\n # 服务器已停止')
    
def update_server(c):
    # 利用run方法直接执行传入的命令
    output=c.run('~/steamcmd/steamcmd.sh +force_install_dir ~/dontstarvetogether_dedicated_server +login anonymous +app_update 343050 validate +quit').stdout
    print('\n # 服务器已更新,开始重启')
    restart_server(c)
    
def backup_cluster(c):
    # 利用run方法直接执行传入的命令
    output=c.run('cd ~/.klei/DoNotStarveTogether && tar -cvzf Cluster_1.tar.gz Cluster_1').stdout
    #本地创建backup文件夹
    if not os.path.exists('backup'):
        os.makedirs('backup')
    #下载Cluster_1.tar.gz文件
    ctime=time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
    #移动Cluster_1.tar.gz文件到~下
    output=c.run('mv ~/.klei/DoNotStarveTogether/Cluster_1.tar.gz ~').stdout
    print('\n # 开始下载存档')
    c.get('Cluster_1.tar.gz', "backup/Cluster_1_"+ctime+".tar.gz")
    print('\n # 存档已下载,正在解压...')
    #本地解压Cluster_1.tar.gz文件
    shutil.unpack_archive("backup/Cluster_1_"+ctime+".tar.gz", "backup/Cluster_1_"+ctime)
    #删除本地的Cluster_1.tar.gz文件
    os.remove("backup/Cluster_1_"+ctime+".tar.gz")
    #删除远程服务器上的Cluster_1.tar.gz文件
    output=c.run('rm -rf ~/Cluster_1.tar.gz').stdout
    print('\n # 存档备份完成')

def update_cluster(c):
    stop_server(c)
    #在本地Cluster_1文件夹中创建一个txt文件,写入token
    with open(Cluster_name+'/cluster_token.txt', 'w') as f:
        f.write(token)
    # 利用run方法直接执行传入的命令
    shutil.make_archive('Cluster_1', 'gztar', Cluster_name)
    #以文本形式打开Cluster_1\Master中的modoverrides.lua
    with open(Cluster_name+'/Master/modoverrides.lua', 'r') as f:
        modoverrides = f.read()
    mods=re.findall(r'"workshop-(.*?)"]', modoverrides)
    output=c.run('mkdir -p ~/.klei/DoNotStarveTogether/Cluster_1').stdout
    output=c.put('Cluster_1.tar.gz', "Cluster_1.tar.gz")
    output=c.run('tar -xvzf Cluster_1.tar.gz -C ~/.klei/DoNotStarveTogether/Cluster_1').stdout
    output=c.run('rm -rf Cluster_1.tar.gz').stdout
    os.remove('Cluster_1.tar.gz')
    os.remove(Cluster_name+'/cluster_token.txt')

    output=c.run('rm -rf Cluster_1.tar.gz').stdout
    #清空重建dedicated_server_mods_setup.lua
    output=c.run('echo "" > ~/dontstarvetogether_dedicated_server/mods/dedicated_server_mods_setup.lua').stdout
    #在dedicated_server_mods_setup.lua文件后添加行
    for mod in mods:
        #添加行
        output=c.run(f'echo "ServerModSetup(\"{mod}\")" >> ~/dontstarvetogether_dedicated_server/mods/dedicated_server_mods_setup.lua').stdout
    while check_server(c):
        time.sleep(1)
        pass
    start_server(c)
    print('\n # 存档已上传/更新')

def init_server(c):
# 利用run方法直接执行传入的命令
#检查是否存在startup.sh文件
    output=c.run('ls', hide=True).stdout
    if "startup.sh" in output:
        return
    
    output=c.run('sudo apt -y update').stdout
    output=c.run('sudo apt-get install software-properties-common -y').stdout
    output=c.run('sudo add-apt-repository multiverse').stdout
    output=c.run('sudo dpkg --add-architecture i386').stdout
    
    output=c.run('sudo apt install libstdc++6 libgcc1 libcurl4-gnutls-dev:i386 lib32z1 -y').stdout
    output=c.run('sudo apt install libstdc++6 -y').stdout
    output=c.run('sudo apt install lib32stdc++6 -y').stdout
    output=c.run('mkdir ~/steamcmd').stdout

    output=c.run('wget https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz').stdout 
    output=c.run('tar -xvzf steamcmd_linux.tar.gz -C ~/steamcmd').stdout
    output=c.run('rm -rf steamcmd_linux.tar.gz').stdout
    output=c.run('~/steamcmd/steamcmd.sh +force_install_dir ~/dontstarvetogether_dedicated_server +login anonymous +app_update 343050 validate +quit').stdout
    
    output=c.run('dd if=/dev/zero of=/mnt/swap bs=1M count='+str(swap_size)).stdout
    output=c.run('sudo chmod 600 /mnt/swap').stdout
    output=c.run('mkswap /mnt/swap').stdout
    output=c.run('swapon /mnt/swap').stdout
    output=c.run('echo "/swapfile swap swap defaults 0 0" >> /etc/fstab').stdout
    output=c.run('echo "vm.swappiness = '+str(swap_p)+'" >> /etc/sysctl.conf').stdout
    output=c.run('sysctl -p', hide=True).stdout
    
    output=c.run('sudo apt-get install dos2unix -y').stdout
    output=c.put('startup.sh', "startup.sh")
    output=c.run('dos2unix startup.sh').stdout
    output=c.run('sudo chmod u+x startup.sh').stdout
    
def check_cluster(c):
    #检查文件是否存在
    try:
        output=c.run('ls ~/.klei/DoNotStarveTogether/Cluster_1', hide=True).stdout
        if "cluster.ini" not in output:
            return
    except:
        return
    # 读取~/.klei/DoNotStarveTogether/Cluster_1/cluster.ini文件内容
    output=c.run('cat ~/.klei/DoNotStarveTogether/Cluster_1/cluster.ini | iconv -c -f UTF-8 -t GBK', hide=True).stdout
    # 匹配cluster.ini文件中的[]=[]内容,返回一个字典,key为[],value为[]
    cluster_ini = re.findall(r'(.*?) = (.*?)\n', output)
    # 将cluster_ini转为字典
    cluster_ini = dict(cluster_ini)
    
    return cluster_ini
def update_cluster_ini(c,cluster_ini):
    #修改cluster.ini文件
    output=c.run('sed -i "s/cluster_name = .*/cluster_name = '+cluster_ini['cluster_name']+'/" ~/.klei/DoNotStarveTogether/Cluster_1/cluster.ini', hide=True).stdout
    output=c.run('sed -i "s/cluster_password = .*/cluster_password = '+cluster_ini['cluster_password']+'/" ~/.klei/DoNotStarveTogether/Cluster_1/cluster.ini', hide=True).stdout
    output=c.run('sed -i "s/cluster_description = .*/cluster_description = '+cluster_ini['cluster_description']+'/" ~/.klei/DoNotStarveTogether/Cluster_1/cluster.ini', hide=True).stdout
    output=c.run('sed -i "s/max_players = .*/max_players = '+cluster_ini['max_players']+'/" ~/.klei/DoNotStarveTogether/Cluster_1/cluster.ini', hide=True).stdout
    output=c.run('sed -i "s/game_mode = .*/game_mode = '+cluster_ini['game_mode']+'/" ~/.klei/DoNotStarveTogether/Cluster_1/cluster.ini', hide=True).stdout
    
def check_cluster_f(c):
    cluster_ini=check_cluster(c)
    print('\n # 当前存档信息-----------------')
    print('   名称:',cluster_ini['cluster_name'])
    print('   密码:',cluster_ini['cluster_password'])
    print('   描述:',cluster_ini['cluster_description'])
    print('   最大玩家数:',cluster_ini['max_players'])
    print('   模式:',cluster_ini['game_mode'])
    
def update_cluster_ini_f(newindow,c,cluster_ini,option,new_value):
    #修改时名称、模式、最大玩家不能为空字符
    if option=="cluster_name" and new_value=="":
        #弹窗提示输入不合法
        messagebox.showinfo('提示','输入不合法')
        return
    elif option=="game_mode" and new_value=="":
        #弹窗提示输入不合法
        messagebox.showinfo('提示','输入不合法')
        return
    elif option=="max_players" and new_value=="":
        #弹窗提示输入不合法
        messagebox.showinfo('提示','输入不合法')
        return
    elif option=="max_players" and new_value!="":
        if new_value.isdigit():
            new_value=int(new_value)
            if new_value<0:
                #弹窗提示输入不合法
                messagebox.showinfo('提示','输入不合法')
                return
            new_value=str(new_value)
        else:
            #弹窗提示输入不合法
            messagebox.showinfo('提示','输入不合法')
            return
    cluster_ini[option]=new_value
    update_cluster_ini(c,cluster_ini)
    print('\n # 存档信息已更新,重启后生效。')
    #关闭窗口
    newindow.destroy()


def change_swapsize_f(newindow,c,swap_size):
    #检查是否为整数
    if swap_size.isdigit():
        swap_size=int(swap_size)
        if swap_size<0:
            #弹窗提示输入不合法
            messagebox.showinfo('提示','输入不合法')
            return
    else:
        #弹窗提示输入不合法
        messagebox.showinfo('提示','输入不合法')
        return
    change_swapsize(c,swap_size)
    #关闭窗口
    newindow.destroy()
    
def change_swappiness_f(newindow,c,swap_p):
    #检查是否为整数
    if swap_p.isdigit():
        swap_p=int(swap_p)
        if swap_p<0 or swap_p>100:
            #弹窗提示输入不合法
            messagebox.showinfo('提示','输入不合法')
            return
    else:
        #弹窗提示输入不合法
        messagebox.showinfo('提示','输入不合法')
        return
    change_swappiness(c,swap_p)
    #关闭窗口
    newindow.destroy()
    
def select_cluster_f(newindow):
    #弹出选择文件夹对话框
    global Cluster_name
    Cluster_name = filedialog.askdirectory()
    #更新label显示的内容
    newindow.children['!label']['text']=Cluster_name
    
def update_cluster_f(c,newindow):
    #检查是否选择了存档文件夹
    if Cluster_name=="":
        #弹窗提示输入不合法
        messagebox.showinfo('提示','请选择存档文件夹')
        return
    #检查选择的存档文件夹是否存在cluster.ini文件
    if not os.path.exists(Cluster_name+'/Master/modoverrides.lua'):
        #弹窗提示输入不合法
        messagebox.showinfo('提示','存档文件夹不合法')
        return
    
    update_cluster(c)
    #关闭窗口
    newindow.destroy()
    
    
def on_update_cluster(c):
    #弹窗要求用户选择存档文件夹
    newindow = tk.Toplevel(root)
    #newindow.attributes('-topmost', 1)
    newindow.title("上传/更新存档")
    newindow.grab_set()
    tk.Button(newindow, text='选择存档文件夹', command=lambda: select_cluster_f(newindow)).grid(row=0, column=0,padx=10,pady=10)
    #显示选择的存档文件夹,文本右对齐,加边框
    tk.Label(newindow, text=Cluster_name,width=30,anchor='e',relief='groove').grid(row=0, column=1,padx=10,pady=10)
    #显示确认提醒,告知用户上传/更新存档会停止服务器并覆盖原存档
    tk.Label(newindow, text="请注意上传/更新存档会停止服务器并覆盖原存档!",fg='red').grid(row=1, column=0,padx=10,pady=10,columnspan=2)
    #确认按钮
    tk.Button(newindow, text="确定", command=lambda: update_cluster_f(c,newindow)).grid(row=2, column=0,padx=10,pady=10)
    #取消按钮
    tk.Button(newindow, text="取消", command=newindow.destroy).grid(row=2, column=1,padx=10,pady=10)
    # 更新窗口,以确保它已经被渲染,这样我们才能获取它的大小
    newindow.update_idletasks()
    # 计算新窗口的位置,使其位于主窗口的中心
    width = newindow.winfo_width()
    height = newindow.winfo_height()
    x = root.winfo_x() + (root.winfo_width() // 2) - (width // 2)
    y = root.winfo_y() + (root.winfo_height() // 2) - (height // 2)
    # 设置新窗口的位置
    newindow.geometry(f"+{x}+{y}")
    newindow.mainloop()


def on_change_cluster_info(c):
    ini = check_cluster(c)
    # 弹窗一个新的窗口,要求用户在下拉框中选择更改项并输入更改值,不使用simpledialog.askstring是因为它只能输入字符串
    newindow = tk.Toplevel(root)
    #newindow.attributes('-topmost', 1)
    newindow.title("更改存档信息")
    newindow.grab_set()
    tk.Label(newindow, text="选择更改项:").grid(row=0, column=0,padx=10,pady=10)
    option = tk.StringVar(newindow)
    option.set("cluster_name")
    tk.OptionMenu(newindow, option, "cluster_name", "cluster_password", "cluster_description", "max_players", "game_mode").grid(row=0, column=1,padx=10,pady=10)
    tk.Label(newindow, text="输入新的值:").grid(row=1, column=0,padx=10,pady=10)
    new_value = tk.Entry(newindow)
    new_value.grid(row=1, column=1,padx=10,pady=10)
    tk.Button(newindow, text="确定", command=lambda: update_cluster_ini_f(newindow,c, ini, option.get(), new_value.get())).grid(row=2, column=0,padx=10,pady=10)
    tk.Button(newindow, text="取消", command=newindow.destroy).grid(row=2, column=1,padx=10,pady=10)
    # 更新窗口,以确保它已经被渲染,这样我们才能获取它的大小
    newindow.update_idletasks()
    # 计算新窗口的位置,使其位于主窗口的中心
    width = newindow.winfo_width()
    height = newindow.winfo_height()
    x = root.winfo_x() + (root.winfo_width() // 2) - (width // 2)
    y = root.winfo_y() + (root.winfo_height() // 2) - (height // 2)
    # 设置新窗口的位置
    newindow.geometry(f"+{x}+{y}")
    newindow.mainloop()
def on_change_swapsize(c):
    newindow = tk.Toplevel(root)
    #newindow.attributes('-topmost', 1)
    newindow.title("更改swap分区大小")
    newindow.grab_set()
    tk.Label(newindow, text="输入新的swap分区大小(M):").grid(row=0, column=0,padx=10,pady=10)
    swap_size = tk.Entry(newindow)
    swap_size.grid(row=0, column=1,padx=10,pady=10)
    tk.Button(newindow, text="确定", command=lambda: change_swapsize_f(newindow,c, swap_size.get())).grid(row=1, column=0,padx=10,pady=10)
    tk.Button(newindow, text="取消", command=newindow.destroy).grid(row=1, column=1,padx=10,pady=10)
    # 更新窗口,以确保它已经被渲染,这样我们才能获取它的大小
    newindow.update_idletasks()
    # 计算新窗口的位置,使其位于主窗口的中心
    width = newindow.winfo_width()
    height = newindow.winfo_height()
    x = root.winfo_x() + (root.winfo_width() // 2) - (width // 2)
    y = root.winfo_y() + (root.winfo_height() // 2) - (height // 2)
    # 设置新窗口的位置
    newindow.geometry(f"+{x}+{y}")
    newindow.mainloop()
def on_change_swappiness(c):
    newindow = tk.Toplevel(root)
    #newindow.attributes('-topmost', 1)
    newindow.title("更改swappiness")
    
    
    tk.Label(newindow, text="输入新的swappiness(0-100):").grid(row=0, column=0,padx=10,pady=10)
    swap_p = tk.Entry(newindow)
    swap_p.grid(row=0, column=1,padx=10,pady=10)
    tk.Button(newindow, text="确定", command=lambda: change_swappiness_f(newindow,c, swap_p.get())).grid(row=1, column=0,padx=10,pady=10)
    tk.Button(newindow, text="取消", command=newindow.destroy).grid(row=1, column=1,padx=10,pady=10)
    # 更新窗口,以确保它已经被渲染,这样我们才能获取它的大小
    newindow.update_idletasks()
    # 计算新窗口的位置,使其位于主窗口的中心
    width = newindow.winfo_width()
    height = newindow.winfo_height()
    x = root.winfo_x() + (root.winfo_width() // 2) - (width // 2)
    y = root.winfo_y() + (root.winfo_height() // 2) - (height // 2)
    # 设置新窗口的位置
    newindow.geometry(f"+{x}+{y}")

    newindow.grab_set()
    
    newindow.mainloop()
    
# 对前文提供的create_app函数进行扩展以包含所有操作
def create_app(root):
    root.title('服务器管理工具')
    
    tk.Button(root, text='查看当前存档信息', command=lambda: check_cluster_f(c),width=15).grid(row=0, column=0,padx=10,pady=10)
    tk.Button(root, text='备份当前存档', command=lambda: backup_cluster(c),width=15).grid(row=0, column=1,padx=10,pady=10)
    tk.Button(root, text='更新/上传存档', command=lambda: on_update_cluster(c),width=15).grid(row=0, column=2,padx=10,pady=10)
    tk.Button(root, text='更改存档信息', command=lambda: on_change_cluster_info(c),width=15).grid(row=1, column=0,padx=10,pady=10)
    tk.Button(root, text='查看服务器状态', command=lambda: check_server_f(c),width=15).grid(row=1, column=1,padx=10,pady=10)
    tk.Button(root, text='更新服务器并重启', command=lambda: update_server(c),width=15).grid(row=1, column=2,padx=10,pady=10)
    tk.Button(root, text='启动服务器', command=lambda: start_server(c),width=15).grid(row=2, column=0,padx=10,pady=10)
    tk.Button(root, text='停止服务器', command=lambda: stop_server(c),width=15).grid(row=2, column=1,padx=10,pady=10)
    tk.Button(root, text='重启服务器', command=lambda: restart_server(c),width=15).grid(row=2, column=2,padx=10,pady=10)
    tk.Button(root, text='查看swap分区', command=lambda: check_swap(c),width=15).grid(row=3, column=0,padx=10,pady=10)
    tk.Button(root, text='更改swap分区大小', command=lambda: on_change_swapsize(c),width=15).grid(row=3, column=1,padx=10,pady=10)  # 示例参数,实际操作需要用户输入
    tk.Button(root, text='更改swappiness', command=lambda: on_change_swappiness(c),width=15).grid(row=3, column=2,padx=10,pady=10)  # 示例参数,实际操作需要用户输入

if __name__ == '__main__':
    c = Connection(host=host, user=user, connect_kwargs={"password": password}, connect_timeout=60)
    print(' # 连接成功,开始初始化服务器')
    init_server(c)
    print(' # 服务器初始化完成')
    root = tk.Tk()
    #设置root大小不可变
    root.resizable(0,0)
    create_app(root)
    root.mainloop()
    #output=c.run('tail -f root.log').stdout

开始搭建

1. 确认IP、密码等信息无误后运行.py主程序,会自动初始化,第一次运行可能需要较长时间。

2. 初始化结束后会弹出tkinter交互框,第一次运行请首先上传存档,选择存档文件夹并确定。

3. 存档上传完成后服务器会自动启动,没有报错的话稍等片刻刷新游戏里的服务器列表,搜索你的服务器名称,直到出现你的专用服务器。

4. 饥荒!启动!

其它

1. 程序还有备份到本地的功能。

2. 每次更新/上传存档都会覆盖原始存档,所以有必要的话请注意备份。

3. 内存较小可能会oom,可以适当增大swap分区大小和swappiness大小。

4. 程序写的比较乱,很多部分是GPT写的,主打一个能用就行。

5. 一个打包好的exe文件,在Windows系统下可以直接运行,不需要python环境,需要首先修改config.ini里的参数(见文章开头)。

4. 其它内容就不说了,如果要临时更改mod,还是先备份到本地、替换里边的mod文件再上传吧,懒得加这个功能了,出现问题请留言。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
饥荒联机版游戏中,最大玩家数默认只能为6人。但是,根据引用的描述,可以通过修改游戏服务器设置来提高人数上限。具体操作步骤如下: 1. 打开饥荒联机版游戏,并进入主菜单界面。 2. 在主菜单界面中,找到"设置"选项。 3. 在"设置"选项中,选择"服务器设置"或类似的选项。 4. 在服务器设置界面中,可以看到"最大玩家数"或类似的选项。 5. 点击或选择"最大玩家数"选项,并修改人数上限为你想要的数量。 6. 保存设置并退出服务器设置界面。 7. 现在你的服务器人数上限已经成功修改。 需要注意的是,修改服务器人数上限可能会对游戏的性能和稳定性产生影响。如果你的电脑或服务器配置较低,增加太多的玩家数量可能会导致游戏运行缓慢或出现延迟。因此,建议根据你的设备和网络情况来合理调整人数上限,以保证游戏的流畅性和稳定性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [《饥荒联机版》房间人数上限修改图文教程](https://blog.csdn.net/weixin_36087083/article/details/119288937)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [饥荒联机版房间人数上限修改图文教程_饥荒联机版房间人数上限怎么修改_牛游戏网](https://blog.csdn.net/weixin_39845113/article/details/119288939)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值