36. Server management part 3: Server packaging¶
36.1. Flavors: Identifying servers according to their role¶
In some cases, you may need to set up servers differently depending on their role. You can set server flavors for this purpose in iFun Engine.
36.1.1. What is a flavor?¶
Flavors are server types that share source code but handle different roles. For example, a lobby server type and game server type may differ even if they use the same source code and can be identified as the lobby flavor and game flavor in iFun Engine.
36.1.2. Setting up flavors¶
If you want to differentiate between a lobby type game server and game type game server, set flavors as follows in the top-level CMakeLists.txt.
1 2 3 4 | ...
set(APP_FLAVORS lobby game)
...
include(Funapi)
|
Note
flavor 지정 시, default
는 엔진 내부에서 예약어(reserved keyword)로 사용하기 때문에 default
이외의 다른 이름을 사용해야 합니다.
36.1.3. Automatically created files for each flavor¶
When you set up and build this way, iFun Engine automatically creates the following files.
36.1.3.1. MANIFEST.json¶
Copy src/MANIFEST.json
, included by default, to create src/MANIFEST.lobby.json
and src/MANIFEST.game.json
in the source directory. You can now change the MANIFEST.json for each flavor as necessary.
36.1.3.2. Launcher script¶
A launcher script is created for each flavor in the build directory. In the example above, scripts ending with .lobby-local
, .lobby-launcher
, .game-local
, and game-launcher
are created.
36.1.3.3. Daemon script¶
If set(WANT_SYSTEMD true)
or set(WANT_UPSTART true)
is set in CMakeLists.txt
, script files are also created to run the game server using a daemon. Files included by default are copied to create files for flavor use, just as with MANIFEST.json.
For *set(WANT_SYSTEMD true):
Files are created in the etc/systemd/ directory in the source directory in formats like
.chat.service
and.lobby.service
.
For *set(WANT_UPSTART true):
Files like
.chat
and.lobby
are created in the etc/upstart/default/ directory in the source directory.Files like
.chat.conf
and.lobby.conf
are created in the etc/upstart/init/ directory in the source directory.
Note
Files created in this way are included and installed or distributed during make install
or make package
.
36.1.4. Learning the current flavor from code¶
To handle server actions differently for each flavor, you need to know the current server flavor from the code.
Use a Google flag called app_flavor
for this. The following is an example of use.
1 2 3 4 5 6 7 8 9 10 11 12 | DECLARE_string(app_flavor)
class MyGameServer : public Component {
public:
static bool Install(const ArgumentMap &arguments) {
if (FLAGS_app_flavor == "lobby") {
// Configure as a lobby server.
} else if (FLAGS_app_flavor == "game") {
// Configure as a game server.
}
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class Server
{
public static void Install(ArgumentMap arguments)
{
if (Flags.GetString ("app_flavor") == "lobby")
{
// Configure as a lobby server.
}
else if (Flags.GetString ("app_flavor") == "game")
{
// Configure as a game server.
}
}
}
|
Tip
When you use a flavor, that flavor’s name is automatically included in its server’s RPC tag. Using this, you can easily import a list of servers with the same flavor. For more details, please see Distribution tagging.
36.2. Game server packaging to move to a production server¶
iFun Engine provides an easy packaging feature for developed game servers. You can use this feature to avoid the unstable process of copying all sources to copy the game server to the production server.
36.2.1. Available packaging types¶
You can create package files in the following three forms and set the variables below in the project’s top-level CMakeLists.txt file.
TGZ: tar file bundled with gzip. Created when set as
set(WANT_TGZ_PACKAGE true)
. This is useful when you want the game server installed in a particular user’s home directory rather than in the usual OS path of /usr/bin.DEB: Debian package file. Created when set as
set(WANT_DEB_PACKAGE true)
. This is only available in Ubuntu. An execution file is installed according to Ubuntu conventions and a daemon script is also included.RPM: Redhat package file. Created when set as
set(WANT_RPM_PACKAGE true)
. This is only available in CentOS. An execution file is installed according to CentOs conventions and a daemon script is also included.
36.2.2. Adding version numbers to packages¶
The package file name is created in the format “{{project}}_{{version}}_install.tgz”, and version strings comprise major version strings and code revision IDs extracted from the source repository, as explained below.
36.2.2.1. Major version strings¶
To update a server package version, modify the contents of the VERSION
file specified in source-directory-structure and create a package. The server package version is then automatically upgraded.
36.2.2.2. Minor version strings (code revision IDs)¶
If you want to automatically add the GIT commit ID or SVN revision number as a build number to the version text string in versions other than those that must be updated manually, set the following variables in CMakeLists.txt.
GIT: Set
set(PACKAGE_WITH_BUILD_NUMBER_FROM_GIT true)`
to set the GIT commit ID as a minor version string.Tip
If the source tree is dirty, add the text string
~dirty
after the commit ID. This way, it is recognized as having been built in a source tree with uncommitted data.SVN: Set
set(PACKAGE_WITH_BUILD_NUMBER_FROM_SVN true)`
to set the revision ID extracted fromsvn info
as a minor version string.Warning
If the update command is not run after committing for SVN,
svn info
returns the revision number before commitment. Runsvn update
before creating the package to prevent this problem.
36.2.3. Generating packages¶
36.2.3.1. In a command line¶
Enter make package
in the terminal to create a package file.
36.2.3.2. In CLion¶
Go to the right target
submenu and find the target called package
. Double-click it to create the package file.
36.2.3.3. In Visual Studio¶
Package creation in Visual Studio will be supported later. You need to connect to the Linux server through Putty, etc. to create the package as explained in In a command line above.
36.2.4. Checking package data¶
36.2.4.1. TGZ¶
You can check package data as follows with tar ztvf
.
$ tar ztvf example_0.0.1_install.tar.gz
drwxrwxr-x dkmoon/dkmoon 0 2017-05-18 14:24 etc/
drwxrwxr-x dkmoon/dkmoon 0 2017-05-18 14:24 etc/default/
-rw-r--r-- dkmoon/dkmoon 72 2017-05-18 14:23 etc/default/example
drwxrwxr-x dkmoon/dkmoon 0 2017-05-18 14:24 etc/init/
-rw-r--r-- dkmoon/dkmoon 1304 2017-05-18 14:23 etc/init/example.conf
drwxrwxr-x dkmoon/dkmoon 0 2017-05-18 14:24 usr/
drwxrwxr-x dkmoon/dkmoon 0 2017-05-18 14:24 usr/lib/
drwxrwxr-x dkmoon/dkmoon 0 2017-05-18 14:24 usr/lib/example/
drwxrwxr-x dkmoon/dkmoon 0 2017-05-18 14:24 usr/lib/example/default/
-rw-r--r-- dkmoon/dkmoon 5723064 2017-05-18 14:23 usr/lib/example/default/libexample.so
...
-rwxr-xr-x dkmoon/dkmoon 3288 2017-05-18 14:23 usr/bin/example-launcher
36.2.4.2. DEB¶
You can check package data as follows with the dpkg-deb --contents
command.
$ dpkg-deb --contents example_0.0.1_install.deb
drwxrwxr-x root/root 0 2017-05-18 14:24 ./etc/
drwxrwxr-x root/root 0 2017-05-18 14:24 ./etc/default/
-rw-r--r-- root/root 72 2017-05-18 14:23 ./etc/default/example
drwxrwxr-x root/root 0 2017-05-18 14:24 ./etc/init/
-rw-r--r-- root/root 1304 2017-05-18 14:23 ./etc/init/example.conf
drwxrwxr-x root/root 0 2017-05-18 14:24 ./usr/
drwxrwxr-x root/root 0 2017-05-18 14:24 ./usr/bin/
-rwxr-xr-x root/root 3288 2017-05-18 14:23 ./usr/bin/example-launcher
drwxrwxr-x root/root 0 2017-05-18 14:24 ./usr/lib/
drwxrwxr-x root/root 0 2017-05-18 14:24 ./usr/lib/example/
drwxrwxr-x root/root 0 2017-05-18 14:24 ./usr/lib/example/default/
-rw-r--r-- root/root 5723064 2017-05-18 14:23 ./usr/lib/example/default/libexample.so
drwxrwxr-x root/root 0 2017-05-18 14:24 ./usr/share/
...
36.2.4.3. RPM¶
You can check package data as follows with the rpm --qpl
command.
$ rpm -qpl example_0.0.1_install.rpm
/lib/systemd/system/example.service
/usr/bin/example-launcher
/usr/lib/example/default/libexample.so
/usr/share/example/default/DEBIAN
/usr/share/example/default/LICENSE
/usr/share/example/default/README
/usr/share/example/default/VERSION
/usr/share/example/default/manifests/MANIFEST.json
/usr/share/example/default/resources/.stamp
/usr/share/example/default/resources/client_data/.stamp
/usr/share/example/default/resources/client_data/README
/usr/share/example/default/resources/game_data/.stamp
/usr/share/example/default/resources/game_data/README
/usr/share/example/default/resources/json_protocols/.stamp
/usr/share/example/default/resources/json_protocols/README
/usr/share/example/default/symbols/libexample.so/62BD5D7D261EC43AFCBABB208919AD480/libexample.so.sym
36.2.5. Including the iFun Engine license file in a package¶
As explained in Using a license file, when installing account.ilf
, it is better to also include it in packages.
When you save account.ilf
as etc/ifunfactory/account.ilf
in the source directory to create the package file as a DEB or RPM file, account.ilf
is also installed.
36.2.6. Including game resource files in a package¶
As with Content support part 4: Game design data, you may have resource files to reference in order to implement server-side logic.
All resource files must be accessible by the game server during development and live service. Resource files are often copied to a set location and used for this purpose, but this creates problems such as requiring the same user ID or requiring separate resource updates when the game server is updated.
iFun Engine allows game developers to specify particular directories as resource directories to solve these problems. These specified directories are included in game server packages and can be accessed consistently by the game server.
36.2.6.1. Specifying a resource directory¶
Resource directories are listed in a variable called RESOURCE_DIRS
in CMakeLists.txt
of the top-level directory.
1 2 3 4 5 | ...
set(RESOURCE_DIRS game_data)
...
include(Funapi)
|
36.2.6.2. Accessing resource files in code¶
Resource files are located in the current source directory during server development and are installed in particular locations depending on the package during service.
For this reason, GetResRoot()
results must be used as a prefix in source code to access resource files. This feature guarantees access to the same resource files during both development and live service.
For example, in the previous example in which a directory called game_data
was set as a resource, it was used as follows to access the file called game_data/my_file1
.
1 | string path = GetResRoot() + "/game_data/my_file1";
|
36.3. Distributing on the production server¶
Please read Server management part 4: Deployment for package distribution and deployment.