46. 专用服务器支持

本文档介绍了应该怎样利用客户端引擎的专用服务器功能来构建游戏服务。 目前可通过iFun引擎使用Unreal Engine 4的专用服务器功能。 It also supports Unity Engine.

Note

Unity多人游戏等其他引擎的类似功能 也将在该引擎的稳定化版本上市后支持。 如有其他疑问,请发送邮件至 Funapi support

iFun引擎专用服务器结构图

用于运行专用服务器的物理机或虚拟机被称为专用服务器主机。 通过下面一系列过程,可使已登录iFun引擎的用户访问专用服务器, 并进行游戏。

  1. (服务器)iFun引擎把通过一个专用服务器进入游戏的用户捆绑到一起,与追加信息共同传输。

  2. 选择专用服务器主机,开始专用服务器进程。

  3. 运行专用服务器

    • 开始专用服务器进程

    • 将命令行参数传输到客户端插件中,执行必要的初始化

    • 待专用服务器准备好后,调用特定插件函数,完成准备

  4. iFun引擎服务器将调用表示“已开始”的回调函数,并向客户端传输访问信息。

  5. (客户端)收到插件回调函数后,通过专用服务器访问后进行游戏。

  6. 游戏结束后,专用服务器传输游戏结果。

46.1. 修改服务器设置

MANIFEST.json 中添加以下项目,即可使用专用服务器功能。

"DedicatedServerManager": {
}

46.1.1. 专用服务器管理器

46.2. 安装专用服务器管理器

支持iFun引擎支持的Linux环境,也支持MS Windows环境。

Ubuntu linux环境

$ sudo apt-get install -y funapi1-dedicated-server-host

CentOS环境

$ sudo yum install -y funapi1-dedicated-server-host

目前已在Windows 10 (x64)环境的64bit Python 2.7.12上完成测试。

  1. 首先下载 MS Windows专用python ,然后进行安装。

  2. 假设Python已安装到默认路径 c:\Python27 下,在命令行中通过如下命令安装必要的包文件。

    C:\> C:\Python2.7\Script\pip.exe install flask gevent netifaces ^
        python-gflags requests redis six
    

    Note

    ^ 符号是MS-DOS批处理文件的连行字符。输入一行即可。

  3. 下载专用服务器管理器,解压到任一位置。

46.3. 设置专用服务器管理器

在配置文件中设置如下值。

  • 指定接收游戏客户端连接的网络接口

  • 指定接收iFun引擎游戏服务器命令的网络接口

  • Redis服务器地址。Redis服务器应和iFun引擎共享。

  • 专用服务器执行文件位置

Linux环境中,配置文件位于 /etc/funapi-dedicated-server-host/funapi-dedicated-server-host.flag 中 。MS Windows环境中,可在解压文件的目录下查看。

# Lines that begins with the '#' are ignored.
# You should update binary_path to your dedicated server executable's location.
--binary_path=/var/lib/your/dedicated-server/binary

# Engine type. Possible values are 'ue4' (UnrealEngine4) and 'unity' (Unity).
--engine_type=ue4

# Also, you should update redis_host, redis_port to match the redis address.
--redis_host=127.0.0.1
--redis_port=6379

# If you want to bind the specific NIC for clients, update the following lines.
# And you may choose another NIC for inter-server communication.
# eg) You may use eno1 for games, and eno2 for inter-server communication.
# Depends on your OS, NIC name can be varying - eg) eth0, eno1, ens1, enp2s0.
--game_interface=eth0
--restful_interface=eth1

专用服务器binary是名为 /var/lib/your/dedicated-server/binary 的执行文件,是redis服务器在 127.0.0.1:6379 上运行时 的配置文件。 当游戏客户端通过 eth0 进行通信,并与iFun引擎游戏服务器通过 eth1 进行通信时,按如上所示设置即可。

Important

리눅스 운영체제에서 Unreal Engine 4 로 개발한 데디케이티드 서버를 실행하기 위해서는 데디서버 호스트 매니저를 root 가 아닌 일반 사용자 권한으로 실행해야 합니다. 그렇지 않을 경우, 데디케이티드 서버 실행에 실패합니다.

데디케이티드 서버 매니저 설치로 생성된 서비스 파일을 복사하여 유저 권한의 서비스 목록에 추가합니다.

$ sudo cp /lib/systemd/system/funapi-dedicated-server-host.service \
/usr/lib/systemd/user/funapi-dedicated-server-host.service

Note

\ 문자는 bash 의 줄 이어짐 문자입니다. 한 줄로 입력하시면 됩니다.

그리고 복사된 서비스 파일을 열어 14~15 line 의 User=root, Group=root 를 제거합니다.

# NOTE: It's strongly recommended that one should use uid:gid other than root

User=root   # remove
Group=root  # remove

Type=simple
Restart=on-failure
RestartSec=5s

MS Windows使用 game_iprestful_ip 参数。(不使用 interface 参数。) 只有指定了相应值,才能正常连接。

# Lines that begins with the '#' are ignored.
# You should update binary_path to your dedicated server executable's location.
--binary_path=D:\ShooterGame\ShooterGame.exe

# Also, you should update redis_host, redis_port to match the redis address.
--redis_host=127.0.0.1
--redis_port=6379

# For Microsoft Windows, you must use following flags, instead of
# game_interface or restful_interface.
# IP addresses used by game clients and game servers respectively.
--game_ip=10.0.0.7
--restful_ip=10.10.1.7

Tip

当想要向专用服务器额外传输特定参数时,可以不指定执行文件位置,而是 通过脚本文件(根据OS的不同,可以是.sh或.bat)指定 --binary_path , 然后在相应文件中添加参数。

或者,也可以在开发过程中,利用UE4编辑器设置成在无打包过程的情况下运行。 可参考以下示例。(MS Windows中使用.bat)

REM exmple batch file, which utilizes UE4 editor to launch dedicated server

"C:\Program Files\Epic Games\4.14\Engine\Binaries\Win64\UE4Editor.exe" ^
  "C:\Work\apps-ue4-dedi-server-example\ShooterGame\ShooterGame.uproject" ^
  HighRise -skipcompile -server -log ^
  %*

利用UE4编辑器打开专用服务器,追加传输地图名字 HighRise

当传输每个游戏都须要变更的地图名字、游戏模式等值时, 请参考下一节,使用 DedicatedServerManager::SendUsers() 函数的 server_args 参数。

46.4. 运行专用服务器管理器

在Ubuntu 16.04 / CentOS 7环境中运行

首先通过以下命令语激活服务。

# Unity

$ sudo systemctl daemon-reload
$ sudo systemctl enable funapi-dedicated-server-host

# Unreal Engine 4

$ systemctl --user daemon-reload
$ systemctl --user enable funapi-dedicated-server-host

然后执行服务。

# Unity

$ sudo systemctl start funapi-dedicated-server-host

# Unreal Engine 4

$ systemctl --user start funapi-dedicated-server-host

在Ubuntu 14.04环境中运行

执行如下服务。

$ sudo start funapi-dedicated-server-host

在MS Windows环境中运行

funapi-dedicated-server-host.flag 中的内容进行设置后, 在 funapi_dedicated_server 文件夹所在目录下执行以下命令。

假设已解压到 D:\DedicatedServerHost 目录中。

D:\DedicatedServerHost> C:\Python2.7\python.exe -m funapi_dedicated_server ^
    --flagfile=funapi-dedicated-server-host.flag

Note

^ 符号是MS-DOS批处理文件的连行字符。输入一行即可。

46.4.1. 开始游戏

在游戏服务器中调用如下函数。

#include <funapi/service/dedicated_server_manager.h>

void start_callback(const fun::Uuid &match_id,
                    const std::vector<std::string> &accounts,
                    bool success) {
  // Do anything after dedicated game server started.
  // You may handle the failed spawning of dedicated game server here.
}


// 게임 데이터, 유저목록, 서버 실행 인자 (추가로 필요한 경우만) 를 넘겨서
// 데디케이티드 서버를 실행한다.
DedicatedServerManager::Spawn(
    match_id,
    game_data,
    server_args,
    accounts,
    start_callback);

参数的涵义如下所示。

  • fun::Uuid match_id: 各个专用服务器实例的唯一 ID。游戏后接收结果时也通过该ID接收。

  • fun::Json game_data: 可以从专用服务器中接收并进行使用的 JSON格式的数据。在其中加入用于开始游戏的必要信息。

  • std::vector<std::string> server_args: 如果有需要作为参数向专用服务器 执行文件传输的值,请对该参数进行设置。例如,若须要选择map,可按 map=blahblah?opt1=1&opt2=2 所示进行传输。

  • std::vector<std::string> accounts: 如果将登录 AccountManager 时已传输的 用户账号ID加入到这里进行传输,则将向相关用户的客户端 传输专用服务器访问信息。

  • start_callback: 游戏Start成功/失败后调用的回调函数。

当拥有可运行专用服务器的主机并成功运行时,在调用回调函数 后,将向个别客户端传输访问信息(地址、令牌等)。 然后个别客户端访问专用服务器并进行游戏。

46.4.2. 处理专用服务器

专用服务器把和iFun引擎服务器通信时所需的部分汇集到一起,通过 fun::FunapiDedicatedServer 类的成员函数提供。

46.5. 处理命令行参数

调用如下所示代码,读取命令行参数。 只有调用了以下代码,才能读取游戏服务器发送的数据或将游戏结果 发送给游戏服务器。相应函数如下所示。

bool ParseConsoleCommand(const TCHAR* cmd,
                         const FString &match_id_field,
                         const FString &manager_server_field);

如未能获取所有必要参数,将返回 false 。 如果按如下所示执行,将自动解析必要参数。

fun::FunapiDedicatedServer::ParseConsoleCommand(FCommandLine::Get());

如不想把专用服务器的命令行参数值不作为初始值,而是用作其他值, 按如下所示调用即可。

fun::FunapiDedicatedServer::ParseConsoleCommand(
    FCommandLine::Get(),
    "FunapiMatchID",        // match id 에 해당하는 인자 이름입니다.
    "FunapiManagerServer",  // 데디케이티드 서버를 관리하는 서버 주소입니다.
  );

46.6. 导入必要数据

游戏服务器端向专用服务器发送的数据可调用 如下函数导入即可。 导入相应数据后,在回调函数内进行必要的初始化即可。

void GetGameInfo(
    const TFunction<void(FHttpResponsePtr response)> &completion_handler);

例如,按如下所示指定回调函数,并进行调用。

// 데이터를 받은 후 호출할 콜백 함수.
void OnDataReceived(FHttpResponsePtr response) {
  // response 안에 JSON 형식으로 데이터가 들어있습니다.
  // 게임 서버에서 보낸 데이터는 JSON data의 "data" attribute 밑의
  // 내용에 해당합니다.
}

// 실제로 데이터를 가져옵니다.
fun::FunapiDedicatedServer::GetGameInfo(OnDataReceived);

46.7. 专用服务器完成准备后进行通知

专用服务器初始化结束后,为了使客户端可以访问,将调用 以下函数,通知专用服务器管理器。

fun::FunapiDedicatedServer::PostReady();

46.8. 已访问用户的认证处理

该函数仅在已调用 GetGameInfo() 后才有效。

在UE4的 PreLogin 阶段提供用于确认用户是否为有效用户的函数。 即,客户端访问后,为进行认证处理,将调用以下函数。 用户ID和认证令牌字段名使用 FunapiUIDFunapiToken 。 如须使用其他值,请使用第二个函数。

// 유저 인증 처리; 반환 값: 인증 성공 여부
bool AuthUser(const FString& options,  // PreLogin 단계에서 넘어오는 인자
              FString &error_message);  // 오류가 발생한 경우 오류 메시지

// 유저 아이디 / 토큰 필드명을 변경한 경우 이 함수를 씁니다.
bool AuthUser(const FString& options,  // PreLogin 단계에서 넘어오는 인자
              const FString& uid_field,  // uid 필드명
              const FString& token_field,  // 인증 토큰 필드명
              FString &error_message);  // 오류가 발생한 경우 오류 메시지

例如,按如下所示调用即可。

// 기본 필드 이름을 쓰는 경우
if (!fun::FunapiDedicatedServer::AuthUser(Options, ErrorMessage)) {
  // 인증 실패한 경우 처리
}


// 기본 필드 이름을 쓰지 않는 경우
if (!fun::FunapiDedicatedServer::AuthUser(Options,
                                          "FunapiUID",
                                          "FunapiToken",
                                          ErrorMessage)) {
  // 인증 실패한 경우 처리
}

46.9. 报告游戏结果

游戏结束后,将以JSON形式创建将向游戏服务器发送的数据,并进行传输。 使用以下函数。

void PostResult(const FString &json_string, const bool use_exit);

use_exittrue 时,报告结果后关闭专用服务器。

例如,调用如下所示函数,报告游戏结果。

fun::FunapiDedicatedServer::PostResult(
    FString("{ \"foo\":\"bar\"}"), false);

这里传输的游戏结果在 处理游戏结果 一节中所介绍的 服务器代码中进行处理。

46.9.1. 处理游戏结果

对于前面所介绍的 报告游戏结果 中向游戏服务器发送的结果 ,若事先已注册好回调函数,则可在相应函数中进行处理。

#include <funapi/service/dedicated_server_manager.h>


// 게임 결과를 처리하는 콜백 함수입니다.
void result_callback(const fun::Uuid &match_id,
                     const fun::Json &match_data,
                     bool success) {
    // 게임 결과 처리를 수행합니다.
}

// 콜백을 등록합니다.
DedicatedServerManager::RegisterMatchResultCallback(result_callback);

若在游戏服务器的 Start() 函数或其他函数中已事先注册回调函数,则可在游戏结束后 接收结果,并进行处理。专用服务器已传输的 JSON数据将传输给 match_data 。建议运用该值和matchID等 将游戏结果保存在数据库中。