43. 编程Part 3: 程序运行参数

iFun Engine中程序的设置内容通过 MANIFEST.json 进行管理。

因此,传输运行参数的方法大体上有在MANIFEST.json中指定参数的方法,以及添加命令行参数的方法。

43.1. 方法1: 利用MANIFEST.json

43.1.1. 在MANIFEST.json中添加参数

如下所示,在MANIFEST.json中添加名为 arguments 的JSON property,定义其中使用的参数。

 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
{
  "version": 1,

  "components": [
    {
      "name": "MyProjectServer",

      "arguments": {
        "example_arg1": "val1",
        "example_arg2": 100
      },

      "library": "libmy_project.so",

      "dependency": {

        ...

        "SessionService": {
          "tcp_json_port": 8012,
          ...
        },

        ...
      }
    }
  ]
}

43.1.2. 从服务器代码读取参数

已添加到MANIFEST.json中的参数将在相应服务器的Install函数被调用时传输。下面是读取上述MANIFEST.json的情况。

my_project_server.cc:

 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
class MyProjectServer : public Component {
 public:
  static bool Install(const ArgumentMap &arguments) {
    LOG(INFO) << "Built using Engine version: " << FUNAPI_BUILD_IDENTIFIER;

    // Kickstarts the Engine's ORM.
    // Do not touch this, unless you fully understand what you are doing.
    my_project::ObjectModelInit();

    /*
     * Parameters specified in the "arguments" section in your MANIFEST.json
     * will be passed in the variable "arguments".
     * So, you can give configuration data to your game server.
     *
     * Example:
     *
     * We have in MANIFEST.json "example_arg1" and "example_arg2" that
     * have a string value and an integer value, respectively.
     * So, you can access the arguments like below:
     */
    string arg1 = arguments.FindStringArgument("example_arg1");
    LOG(INFO) << "example_arg1: " << arg1;

    int64_t arg2 = arguments.FindIntegerArgument("example_arg2");
    LOG(INFO) << "example_arg2: " << arg2;

     // You can override gflag like this: ./my_project-local --example_arg3=hahaha
    LOG(INFO) << "example_arg3: " << FLAGS_example_arg3;


    /*
     * Registers various handlers.
     * You may be interesed in this function and handlers in it.
     * Please see "event_handlers.cc"
     */
    my_project::RegisterEventHandlers();

    return true;
  }
}

server.cs:

 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
42
43
namespace MyProject
{
  public class Server
  {
    public static void Install(ArgumentMap arguments)
    {
      // Session open, close handlers.
      NetworkHandlerRegistry.RegisterSessionHandler (
        new NetworkHandlerRegistry.SessionOpenedHandler (OnSessionOpened),
        new NetworkHandlerRegistry.SessionClosedHandler (OnSessionClosed));

      // "echo" message handler for JSON type.
      NetworkHandlerRegistry.RegisterMessageHandler ("echo", new NetworkHandlerRegistry.JsonMessageHandler (OnEcho));

      // "echo_pbuf" message handler for Google Protocol Buffers.
      NetworkHandlerRegistry.RegisterMessageHandler ("echo_pbuf", new NetworkHandlerRegistry.ProtobufMessageHandler (OnEchoPbuf));

      // Parameters specified in the "arguments" section in your MANIFEST.json
      // will be passed in the variable "arguments".
      // So, you can give configuration data to your game server.
      //
      // Example:
      //
      // We have in MANIFEST.json "example_arg1" and "example_arg2" that
      // have a string value and an integer value, respectively.
      // So, you can access the arguments like below:
      string arg1 = arguments.FindString ("example_arg1");
      Log.Info ("example_arg1: {0}", arg1);

      Int64 arg2 = arguments.FindInteger ("example_arg2");
      Log.Info ("example_arg2: {0}", arg2);

      // You can override gflag like this: ./mono-local --example_arg3=hahaha
      Log.Info("example_arg3: {0}", Flags.GetString ("example_arg3"));

      // Registers a timer.
      //
      // Below demonstrates a repeating timer. One-shot timer is also available.
      // Please see the Timer class.
      Timer.ExpireRepeatedly(WallClock.FromSec(1), OnTick);
    }
  }
}

43.2. 方法2: 通过Google Flag添加

43.2.1. 添加Google Flag

首先利用 Google Gflag ,在代码中定义要使用的运行参数。

此时使用的函数如下所示。

DEFINE_bool

boolean

DEFINE_int32

32-bit integer

DEFINE_int64

64-bit integer

DEFINE_uint64

unsigned 64-bit integer

DEFINE_double

double

DEFINE_string

C++ string

示例如下所示。

DEFINE_string(my_arg1, "기본값", "my_arg1에 대한 설명");

Note

对于C#,须要通过C++代码在src/{{project_name}}_server.cc中添加,而不是在mono/server.cs中添加。

43.2.2. 从服务器代码读取flag

当需要相应flag时,通过与DEFINE_XYZ()匹配的DECLARE_XYZ()函数 声明 flag,然后在代码中以 FLAGS_XYZ 的名字使用即可。

可使用的DECLARE_XYZ()函数如下所示。

DECLARE_bool

boolean

DECLARE_int32

32-bit integer

DECLARE_int64

64-bit integer

DECLARE_uint64

unsigned 64-bit integer

DECLARE_double

double

DECLARE_string

C++ string

my_project_server.cc:

 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
42
43
// You can differentiate game server flavors.
DECLARE_string(example_arg3);

class MyProjectServer : public Component {
 public:
  static bool Install(const ArgumentMap &arguments) {
    LOG(INFO) << "Built using Engine version: " << FUNAPI_BUILD_IDENTIFIER;

    // Kickstarts the Engine's ORM.
    // Do not touch this, unless you fully understand what you are doing.
    my_project::ObjectModelInit();

    /*
     * Parameters specified in the "arguments" section in your MANIFEST.json
     * will be passed in the variable "arguments".
     * So, you can give configuration data to your game server.
     *
     * Example:
     *
     * We have in MANIFEST.json "example_arg1" and "example_arg2" that
     * have a string value and an integer value, respectively.
     * So, you can access the arguments like below:
     */
    string arg1 = arguments.FindStringArgument("example_arg1");
    LOG(INFO) << "example_arg1: " << arg1;

    int64_t arg2 = arguments.FindIntegerArgument("example_arg2");
    LOG(INFO) << "example_arg2: " << arg2;

     // You can override gflag like this: ./my_project-local --example_arg3=hahaha
    LOG(INFO) << "example_arg3: " << FLAGS_example_arg3;


    /*
     * Registers various handlers.
     * You may be interesed in this function and handlers in it.
     * Please see "event_handlers.cc"
     */
    my_project::RegisterEventHandlers();

    return true;
  }
}

需要相应flag时,可以以**Flags.GetString(“XYZ”)**的形式读取值。

此时,各类型可Get的函数如下。

GetBool

boolean

GetInt32

32-bit integer

GetInt64

64-bit integer

GetUInt64

unsigned 64-bit integer

GetDouble

double

GetString

C# string

server.cs:

 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
42
43
namespace MyProject
{
  public class Server
  {
    public static void Install(ArgumentMap arguments)
    {
      // Session open, close handlers.
      NetworkHandlerRegistry.RegisterSessionHandler (
        new NetworkHandlerRegistry.SessionOpenedHandler (OnSessionOpened),
        new NetworkHandlerRegistry.SessionClosedHandler (OnSessionClosed));

      // "echo" message handler for JSON type.
      NetworkHandlerRegistry.RegisterMessageHandler ("echo", new NetworkHandlerRegistry.JsonMessageHandler (OnEcho));

      // "echo_pbuf" message handler for Google Protocol Buffers.
      NetworkHandlerRegistry.RegisterMessageHandler ("echo_pbuf", new NetworkHandlerRegistry.ProtobufMessageHandler (OnEchoPbuf));

      // Parameters specified in the "arguments" section in your MANIFEST.json
      // will be passed in the variable "arguments".
      // So, you can give configuration data to your game server.
      //
      // Example:
      //
      // We have in MANIFEST.json "example_arg1" and "example_arg2" that
      // have a string value and an integer value, respectively.
      // So, you can access the arguments like below:
      string arg1 = arguments.FindString ("example_arg1");
      Log.Info ("example_arg1: {0}", arg1);

      Int64 arg2 = arguments.FindInteger ("example_arg2");
      Log.Info ("example_arg2: {0}", arg2);

      // You can override gflag like this: ./mono-local --example_arg3=hahaha
      Log.Info("example_arg3: {0}", Flags.GetString ("example_arg3"));

      // Registers a timer.
      //
      // Below demonstrates a repeating timer. One-shot timer is also available.
      // Please see the Timer class.
      Timer.ExpireRepeatedly(WallClock.FromSec(1), OnTick);
    }
  }
}

43.2.3. 运行命令行时传输参数

现在游戏服务器将识别到名为 --example_arg3 的运行参数。即,将通过 --example_arg3=my_value 的形式予以使用。

$ ./my_game_server-local --example_arg3=my_value

也可以在EXTRA_ARGS环境变量中列出将要添加的参数。

$ EXTRA_ARGS="--my_arg1=my_value" ./my_game_server-local

$ export EXTRA_ARGS="--my_arg1=my_value"
$ ./my_game_server-local

43.2.4. 作为Service运行时传输参数

当游戏服务器打包后作为Service运行时,和前面提到的一样,无法传输运行参数。 此时,可在 设置服务 中提到的文件中定义运行参数后传输。

Upstart:

etc/upstart/default/{{project-name}} 文件中以 export EXTRA_ARGS="--example_arg3=my_value --example_arg4=another" 的形式输入。

Important

必须带有 exportEXTRA_ARGS 后面的 = 前后不能有空格。

Systemd:

在*etc/systemd/{{project-name}}*文件中以 EXTRA_ARGS="--example_arg3=my_value --example_arg4=another" 的形式输入。

Important

编写时不能有 export