⬆️ ⬇️

Setting up a dedicated Source server for Linux, part 2



Records



Records (Replays) in Team Fortress 2 is an opportunity, on the server side, to create a record of the player’s last life, and on the client side, to view, edit, save, and publish it. It is an extension of SourceTV.



Entries must be explicitly enabled on the server command line, enabled and configured in the configuration file that is executed before loading the map. In addition, the web server must be pre-configured to deliver records to players.



Web server setup



For clarity, we will add a separate subdomain replay.example.org to the DNS, create the directory /var/www/replay.example.org, and for convenience we will write the logs into separate files and let the user read the game.



From root, we create directories, set the owner (game: game) and rights β€” to the game user for writing, the rest (the web server) for reading. You can also make symbolic links for convenience. This web server will be common to both game servers, but each of them will use separate directories for posting entries.



# mkdir -p /var/www/replay.example.org/{htdocs/server1,htdocs/server2,log} # chown -R game:game /var/www/replay.example.org # chmod -R 755 /var/www/replay.example.org # ln -s /var/www/replay.example.org/log /home/game/log/www-replay 


In our default configuration, all web server logs are owned by nginx: adm and 640 permissions, that is, they are not available to regular users. Adjust this for this case:



  # touch /var/www/replay.example.org/log/{access,error}.log # chmod 644 /var/www/replay.example.org/log/*.log 


Thus, the user of the game, our logs will be available for reading. But only until their first rotation. We fix this too. In the /etc/logrotate.d directory we copy the nginx file to srcds-nginx, in it we set the path to the logs and in the create 640 nginx adm fix the access rights mask from 640 to 644:



srcds-nginx
 #/etc/logrotate.d/srcds-nginx /var/www/stat.example.org/log/*.log /var/www/fastdl.example.org/log/*.log /var/www/replay.example.org/log/*.log { daily missingok rotate 52 compress delaycompress notifempty create 644 nginx adm sharedscripts postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 `cat /var/run/nginx.pid` fi endscript } 


Here we are in the paths for rotation at the same time indicated directories with logs from the statistics server HLstatsX and from the Fast Download server.



As root, create a web server configuration file, /etc/nginx/conf.d/replay.example.org.conf:



replay.example.org.conf
 # /etc/nginx/conf.d/replay.example.org.conf server { server_name replay.example.org; listen 80; root /var/www/replay.example.org/htdocs; disable_symlinks on; autoindex off; access_log /var/www/replay.example.org/log/access.log main; error_log /var/www/replay.example.org/log/error.log warn; } 


This, of course, is a somewhat simplified version. Since in our case the web server is located on the same computer as the game servers and shares one channel with them on the Internet, it makes sense to register additional restrictions on the width of the channel for uploading records. But, unlike the Fast Download settings, there is no need to install additional checks on the referer.



We set the call to replay.example.org.conf in the main /etc/nginx/nginx.conf file if not yet, then test the configuration and restart nginx.



  # nginx -t # systemctl reload nginx 


Further we continue as the user of game.



Configure the game server



By default, when resolving records, the servers will try to execute the configuration file ~ / tf2 / tf / cfg / replay.cfg at startup. Since we include records on both servers, the individual settings of which must be different, as in the previous cases, we prepare individual files for each server.



In the ~ / tf2 / tf / cfg directory there is a file replay_example.cfg, we study it and create our own. For the first server, ~ / cfg / replay1.cfg:



replay1.cfg
 echo "*** ~/cfg/replay1.cfg" replay_name "  " replay_local_fileserver_path /var/www/replay.example.org/htdocs/server1 replay_fileserver_offload_enable 0 replay_fileserver_host replay.example.org replay_fileserver_path /server1 replay_enable 1 


Here:



replay_name

the name of the special bot to record, as it will be visible in the list of spectators.



replay_local_fileserver_path

directory where the finished files with records will be placed. It must be individual for each game server and available for reading by a web server.



replay_fileserver_offload_enable

if 1, then the records are uploaded via ftp to another server, which already distributes them themselves via http. Not our case.



if 0, then the distribution is handled by a web server on our machine.



replay_fileserver_host

web server name or ip



replay_fileserver_path

the url part is the path to the entries as displayed by the web server.



replay_enable

actually includes records on the server.



Thus, from the replay_local_fileserver_path, replay_fileserver_host, replay_fileserver_path and replay_fileserver_protocol not mentioned here replay_file_fileserver (= "http") and replay_fileserver_port (= "80") variables, the url of the type " http://replay.example.org:80/serverpage ", is formed; for downloading records. And the replay_local_fileserver_path variable sets the actual directory location in the file system and is equal to root from the nginx + replay_fileserver_path configuration file.



Copy this file to replay2.cfg, fix server1 paths -> server2



replay2.cfg
 echo "*** ~/cfg/replay2.cfg" replay_name "My replay bot" replay_local_fileserver_path /var/www/replay.example.org/htdocs/server2 replay_fileserver_offload_enable 0 replay_fileserver_host replay.example.org replay_fileserver_path /server2 replay_enable 1 


Make links in ~ / tf2 / tf / cfg:



  $ ln -s -v ~/cfg/replay{1,2}.cfg ~/tf2/tf/cfg/ 


It should be borne in mind that these configuration files are executed only during the initial launch of the server, after autoexec.cfg. When changing cards, they are not involved.



From more or less useful console variables:



replay_dopublishtest

performs a server (gaming and web) readiness test for records β€” checks the availability of paths in the file system, the name of the web server, and so on.



replay_data_lifespan

sets the number of days (by default, 1 day), after which the records on the server will be marked as "stale", which will allow manual or automatic cleaning to delete them.



replay_docleanup

removes "stale" entries. With the parameter 'force' removes all entries altogether.



replay_fileserver_autocleanup

the default is 0 - off, starts the automatic cleaning of "stale" records between rounds.



replay_dofileserver_cleanup_on_start

the default is 1 - on, when the server starts, it starts automatic cleaning of "stale" entries, both in ~ / tf2 / tf / replay / server {1,2} and in the web server directory /var/www/replay.example. org / htdocs / server {1,2}.



replay_record_voice

default 1 - on, record voice chat of players.



The list of actual, in this version of the Steam engine, variables can be viewed by typing in the server console find replay_ .



Turning on



In the startup scripts of servers start {1,2} .sh, we add to the command line:



For the first server:



start1.sh
 CMDLINE="... -replay reply1.cfg -replayserverdir server1 \ ... 


For the second:



start2.sh
 CMDLINE="... -replay reply2.cfg -replayserverdir server2 \ ... 


Here the "-replay" command includes the recording functions and executes the specified configuration file when the server starts. The second command, "-replayserverdir" as a parameter takes the name of the directory (from the path ~ / tf2 / tf / replay /), in which each server will accumulate records.



Everything, you can run the server and try. In the game client, in the server browser, near the name of our server, a characteristic Records icon will appear next to the VAC shield.



When recordings are turned on, a bot appears in the server in observer mode, which actually keeps records and at the same time occupies one game slot. Therefore, the maximum number of players set at the server startup "+ maxplayers 24" is increased by one, that is, in our case it becomes equal to twenty-five (and when you turn on SteamTV - twenty-six).



In the old tutorials on setting up records, the server command line parameter "-replay_port" is usually specified, but we don’t mention it because it was canceled back in 2011 - store.steampowered.com/news/6282/



When using plug-ins that facilitate mass actions on players (including those bundled with SourceMod), you should be careful about the bot records. In any case, do not accidentally kick it from the server :)


Service



Record files, although small in size, still occupy disk space, both in the replay directory and in / var / www /. And it happens that, despite the established date of aging in one day (replay_data_lifespan 1) and the included auto-cleaning of these directories (replay_dofileserver_cleanup_on_start 1), old files are not automatically deleted. Even when manually starting replay_docleanup. Therefore, for security, we will add a forced cleaning of old records by running crontab -e and adding it to the end:



crontab
 0 3 * * * /usr/bin/find ~/tf2/tf/replay/server{1,2}/* -type f -mtime +10 -delete 0 3 * * * /usr/bin/find /var/www/replay.example.org/htdocs/server{1,2}/* -type f -mtime +10 -delete 


Beforehand, it would be nice to make sure that cron uses a shell that supports the extension of brackets - "{1,2}"



Reading access.log shows that sometimes players, or rather their gaming clients, when they connect to our server, try to say the recordings of the games they played three weeks ago.



Another point is to keep in mind that the Records are eating processor time. An example download is given at the end of the "Bots" section.



SourceTV



Now set up SourceTV. This is useful for online broadcasts of world championships, when we will host them.



SourceTV allows viewers, through their Team Fortress 2 clients, to watch the game progress on the server. When using chains of proxy servers, the size of the audience is practically unlimited, but in this case, when the game will be broadcast only by our game server, it makes sense to limit the number of viewers, since each of them consumes both processor resources and a channel to the Internet.



Since during the initial setup of the launch of the game servers we have already indicated in the command line "+ tv_port" with our port number for each server, we can immediately go to the configuration files.



Just as for setting up records, SourceTV must be activated before loading the map, that is, the "tv_enable 1" command must be executed either on the server launch command line or in the autoexec.cfg file. In addition, it was experimentally established that the "tv_name" command has a similar requirement.



Since the SourceTV settings of our servers are fixed and we don’t plan to change with every change of card, we’ll include all of the common in autoexec.cfg, the individual ones in autoexec {1,2} .cfg.



In ~ / cfg / autoexec.cfg we add general settings:



autoexec.cfg
 //... // SourceTV //      tv_title "  !" //    // tv_password "" //    tv_maxclients 5 //      tv_maxrate 0 //   (1)   POV  (0) tv_transmitall 1 //    tv_delay 20 //  - tv_allow_camera_man 0 //     //tv_record <filename> //   //tv_stoprecord //   tv_autorecord 1 


Here:



tv_title

the title in the window of the viewer when viewing the broadcast.



tv_password

password to connect to the broadcast.



tv_maxclients

The maximum number of viewers, from 0 to 255, is 128 by default. If you do not need an online broadcast, but only a recording of the game (tv_record, tv_autorecord), then you can set it to zero.



tv_maxrate

the maximum channel width for each player, by default - 8000 bps, when set to 0 - without restrictions. The parameter is closely linked with the previous parameter, especially if the server is planned to be fully filled with viewers.



tv_transmitall

by default ("0"), only that which is shown by the SourceTV operator (AI or specially trained person) is transmitted to the audience. When set to "1", viewers are given all the information about the game, and they can switch between POVs from different players, or even hover above / below the map. When the parameter is turned on, the required channel width for each viewer increases by two to three times.



tv_delay

broadcast delay to viewers in seconds, default is 30. Used to reduce cheating when the viewer can give hints to the player.



tv_delaymapchange

delay ("1") or not ("0" is the default) to change the card until the broadcast ends (due to the tv_delay delay).



tv_delaymapchange_protect

protects ("1" - by default) or not ("0") from manually changing the card until the round ends.



tv_allow_camera_man

allow ("1" - the default) or not ("0"), observer players become SourceTV operators. If "0" - then only automatic camera control.



tv_autorecord

when turned on ("1"), all games automatically begin to be recorded in files with names like auto-<YYYYMMDD>-<hhmm>-< >.dem to the ~ / tf2 / tf directory, for example, "auto-20160630-2208-koth_sawmill .dem ".



When setting a password ("tv_password <password>"), viewers will not be able to connect from the server browser - they will constantly be refused with the message: "Disconnect: Bad spectator password", and in the server console it will be written "Dropped <player> from server (Bad spectator password) ". To connect, viewers will need to enter the password <> in the console ( ~ ) of the game, close the console, and then try to connect. Or immediately enter connect 192.0.2.0:27020; password <> in the console connect 192.0.2.0:27020; password <> connect 192.0.2.0:27020; password <> .

In ~ / cfg / autoexec1.cfg we append to the end:



autoexec1.cfg
 //... //  SourceTV tv_enable 1 //     tv_name "SourceTV at Public Server No 1" 


Here:



tv_name

the name of the SourceTV server, as it will be displayed in the server browser, in the "Watch" tab.



tv_enable

includes ("1") or not ("0", the default) SourceTV on the server.



Similarly, we adjust ~ / cfg / autoexec2.cfg



autoexec2.cfg
 //... tv_enable 1 tv_name "SoutceTV at Private Server No 2" tv_autorecord 0 


But for the second server, we have disabled automatic recording in autoexec2.cfg. There is a problem when you turn on automatic recording ("tv_autorecord 1") on cards connected from Steam Workshop, whose name looks like "workshop /", or "workshop / .ugc" - that is, in any case contains a slash "/", which leads to a clumsy formation of the file name for tv_autorecord in the auto-<YYYYMMDD>-<hhmm>-< >.dem scheme and swearing in the logs of the form:

  Failed to write file /home/game/tf2/tf/replay/server2/sessions/20160702-074150-workshop/cp_orange_x3.ugc454299390.dmx Failed to write file /home/game/tf2/tf/replay/server2/blocks/20160702-074150-workshop/cp_orange_x3.ugc454299390_part_0.dmx ******************************************************************************** * * Replay recording shutting down due to publishing error! Recording will begin * at the beginning of the next round, but may fail again. * ******************************************************************************** ERROR: Publish timed out after 60 seconds. 


and, as a result, disabling records. Alternatively, you can think of a scheme using "tv_record", which allows you to manually specify the file name to write.



When SourceTV is turned on, a bot appears in the server in observer mode, which is engaged in broadcasting the game and at the same time occupies one game slot. Therefore, the maximum number of players set at the server startup "+ maxplayers 24" is increased by one, that is, in our case it becomes equal to twenty-five (and when you turn on Replay - twenty-six).



So, the commands are spelled out, restart the server and see what happens. Since we also have recordings that also occupy their gaming slot, we see:



  *** ~/cfg/autoexec.cfg (global) -------------------------------------------------------- sv_pure set to 2. -------------------------------------------------------- maxplayers set to 25 *** ~/cfg/autoexec1.cfg Server logging enabled. Server logging data to file /home/game/log/server1/L1008000.log maxplayers set to 26 (extra slot was added for SourceTV) ... Cannot verify load for invalid steam ID [A:1:0:1] Cannot verify load for invalid steam ID [A:1:1:1] Recording SourceTV demo to auto-20161008-1155-cp_granary.dem... Connection to game coordinator established. *** ~/cfg/server1.cfg ... SourceTV broadcast active. Connection to Steam servers successful. Public IP is 192.0.2.0. 


So, at the beginning, the maximum number of players on the server was increased from 24 to 25 - this worked out the command-line parameter "-replay", the recordings started. Then another extra slot was added for SourceTV - it worked "tv_enable 1" from autoexec1.cfg. We do not pay attention to the abuse about invalid steam ID [A: 1: 0: 1] - these are our recording and broadcasting bots, for which the server has added game slots. Then the demo was started writing to the file ~ / tf2 / tf / auto-20161008-1155-cp_granary.dem - the "tv_autorecord 1" parameter from autoexec.cfg worked. Finally, we were told that SourceTV broadcast active.



It worked. You can populate any card with bots, connect with the viewer and see how the broadcast looks in different modes tv_transmitall, tv_allow_camera_man.



It may happen that the slots are added, but about "SourceTV broadcast active." not a word, and when you enter the tv_status command in the server console, it swears "SourceTV not active.", although tv_enable entered right there says that everything is ok - "tv_enable = 1 (def. 0)". In this case, you should try to change the map - changelevel < > . If everything worked after the change, it means that SourceTV didn’t initially activate until the first map was loaded - you need to look at the settings.



Commands that may come in handy:



tv_record < >

starts recording saved to file <file name>. All events are recorded, regardless of what the operator sees.



tv_stoprecord

stops recording.



tv_clients

shows information about connected viewers.



tv_msg

send a message to all viewers (will appear in the middle of the screen).



tv_status

displays a brief information about the status of the server - online time, FPS, number of viewers, channel band used, and the like.



The list of actual, in this version of the game server, variables can be viewed by typing in the server console find tv_ .



Accelerating Content Download (Fast Download)



If we use maps, models, sounds that are not included in the standard delivery of Team Fortress 2 and are missing from the Steam Workshop on our servers, then when a new player is connected, he will need to download our gaming materials to his gaming computer (if he has not). By default, they will be downloaded from our game server - this mode is called Slow Download. But since the game server is still not a specialized web server, then with frequent installation of new user maps and high load, it would be reasonable to assign the functions on the return of cards (as well as sounds, models, etc.) to a specially trained web server. Which, by a happy coincidence, we already have. This functionality is called Fast Download.



Web server setup



To use Fast Download, you must specify the web server to use a directory with the structure of subdirectories



  dir/maps dir/materials dir/sound ... 


where "dir" is the root directory for fast download. We cannot create it in / home / game - we have a home directory with rwx rights ------, which does not allow the web server to see these files. Therefore, we will create these directories somewhere outside the user's home directory game.



To simplify the configuration, we will register a separate subdomain of fastdl.example.org in our DNS, create the directory /var/www/fastdl.example.org, and for convenience we will write the logs into separate files and let the game user read them.



From root, we create directories, set the owner (game: game) and rights β€” to the game user for writing, the rest (the web server) for reading. You can also make symbolic links for convenience. Catalog Fast Download will be common to both game servers.



  # mkdir -p /var/www/fastdl.example.org/htdocs/{maps,materials,sound} # mkdir /var/www/fastdl.example.org/log # chown -R game:game /var/www/fastdl.example.org # chmod -R 755 /var/www/fastdl.example.org # ln -s /var/www/fastdl.example.org/htdocs /home/game/fastdl # ln -s /var/www/fastdl.example.org/log /home/game/log/www-fastdl 


In our default configuration, all web server logs are owned by nginx: adm and 640 permissions, that is, they are not available to regular users. Adjust this for this case:



  # touch /var/www/fastdl.example.org/log/{access,error}.log # chmod 644 /var/www/fastdl.example.org/log/*.log 


Thus, the user game, our logs will be available for reading. But only until their first rotation. We fix this too. In the /etc/logrotate.d directory we copy the nginx file to srcds-nginx, in it we set the path to the logs and in the create 640 nginx adm fix the access rights mask from 640 to 644:



srcds-nginx
 #/etc/logrotate.d/srcds-nginx /var/www/stat.example.org/log/*.log /var/www/fastdl.example.org/log/*.log /var/www/replay.example.org/log/*.log { daily missingok rotate 52 compress delaycompress notifempty create 644 nginx adm sharedscripts postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 `cat /var/run/nginx.pid` fi endscript } 


Here we are in the paths for rotation at the same time indicated directories with logs from the statistics server HLstatsX and from the server with records.



There is another fun moment to consider. For most servers, it is unlikely to become relevant, but still. Nothing prevents the owner of any game server with user cards like ours, not from malice, but to save your traffic, in your Fast Download settings, specify the address of our web server (it is easy to find it - just enter sv_downloadurl in the game console client by connecting to the server).



You can detect such parasites by referer, with whom maps are downloaded from us. So, when downloading the map by the game client, at the filing of our game server, a record of the following type appears in the web server log



  198.51.100.0 http://fastdl.example.org - [16/Jun/2016:20:08:28 +0600] "GET /maps/cp_orange_x5.bsp.bz2 HTTP/1.1" 200 2685506 "hl2://192.0.2.0:27015" "Half-Life 2" 0.453 "-" 


Pay attention to the referer. We take this into account when setting up.



So, we are going to set up a web server. First, we make a determination whether referer downloads our map with the correct one. /etc/nginx/nginx.conf, http {}, fastdl.example.org, :



nginx.conf
 # /etc/nginx/nginx.conf http { # <...> map $http_referer $bad_client { default 1; "hl2://192.0.2.0:27015" 0; "hl2://192.0.2.0:27016" 0; } include /etc/nginx/conf.d/fastdl.example.org.conf; } 


It's simple. $http_referer , $bad_client ( 1) 0.



/etc/nginx/conf.d/fastdl.example.org.conf.



fastdl.example.org.conf
 #/etc/nginx/conf.d/fastdl.example.org.conf server { server_name fastdl.example.org; listen 80; root /var/www/fastdl.example.org/htdocs; disable_symlinks on; default_type application/octet-stream; if ($bad_client) { #      https://habrahabr.ru/post/272261/,     return 403; } access_log /var/www/fastdl.example.org/log/access.log main; error_log /var/www/fastdl.example.org/log/error.log warn; } 


β€” $bad_client, .



, nginx valid_referers, $http_referer, , . map .



fastdl.example.org.conf nginx.conf , nginx.



  # nginx -t # systemctl reload nginx 


game.





, ( bzip2), (.bsp) . , - cp_orange_x5 ( β€” , Steam Workshop), :



  $ mv cp_orange_x5.bsp ~/fastdl/maps $ ln -s ~/fastdl/maps/cp_orange_x5.bsp ~/tf2/tf/maps $ bzip2 --compress --keep --verbose --best ~/fastdl/maps/cp_orange_x5.bsp 


~/fastdl/maps, . , , , . < >.cfg ~/tf2/tf/cfg ( ~/cfg, ).



~/cfg/autoexec.cfg:



autoexec.cfg
 //... // Fast Download //  -,       //   Fast Download  sv_downloadurl "" sv_downloadurl "http://fastdl.example.org" //       (, ). . sv_allowupload 0 //       //    Slow Download.     . sv_allowdownload 1 


. , . , , autoexec.cfg Fast Download.



- β€” exec <configfile> . Fast Download , autoexec.cfg, "" , server.cfg. , . , autoexec.cfg :-)

SteamApps\common\Team Fortress 2\tf\download\maps\ cp_orange_x5.bsp, β€” ( ).



, , , Fast Download ( "Downloading maps/cp_orange_x5.bsp.bz2" β€” .bz2 ):



Fast Download working



( _x3, ).



, , " " (cl_downloadfilter mapsonly), "Map is missing".



Allow maps downloading



http://fastdl.example.org/maps/cp_orange_x5.bsp.bz2 , "403 Forbidden" β€” , referer hl2://192.0.2.0 , .



:



Fast Download ( sv_downloadurl), -, , < >.bsp.bz2, 404 , .bz2 β€” < >.bsp. , ~/tf2/tf/maps Slow Download, , .



Map missing





Team Fortress 2 β€” . , ( sv_cheats 0), . β€” "", (sv_cheats 1).



TF wiki , King of the Hill ( koth_* ), Payload ( pl_* ), Dustbowl Gorge, Capture the Flag ( ctf_* ) Mann Manor ( cp_manor_event ). , . . , . .





koth_sawmill, by design. 24 . , 24 , . , 24, . β€” . β€” . , . , ~/cfg/koth_sawmill.cfg:



koth_sawmill.cfg
 echo "*** ~/cfg/koth_sawmill.cfg" //    tf_bot_difficulty 3 //      tf_bot_join_after_player 0 //   tf_bot_keep_class_after_death 0 //      tf_bot_quota_mode fill //      tf_bot_quota 24 


:



tf_bot_difficulty 3

. 0=easy, 1=normal, 2=hard, 3=expert.



tf_bot_join_after_player 0

(0), (1), .



tf_bot_keep_class_after_death 0

, (, , ...), (1) (0), .



tf_bot_quota 24

, . , tf_bot_quota_mode "fill" "match", , +maxplayers .



tf_bot_quota_mode fill

:



"normal" β€” / (tf_bot_add / tf_bot_kick)



"fill" β€” ( + ) , tf_bot_quota



"match" β€” 1:N, N tf_bot_quota.



tf_bot_add [] [] [] [] []

, (, , maxplayers)



[] β€” Demoman, Engineer, HeavyWeapons, Medic, Pyro, Scout, Soldier, Sniper, Spy



[] β€” red blue



[] β€” tf_bot_difficulty, . 0=easy, 1=normal, 2=hard, 3=expert.



, ~/cfg, ~/tf2/tf/cfg:



  $ ln -s ~/cfg/koth_sawmill.cfg ~/tf2/tf/cfg 


, , : changelevel koth_sawmill . , expert-lvl tf_bot_difficulty 1 :-)





. cp_orange_x3.



koth_sawmill.cfg cp_orange_x3.cfg, Steam Workshop:



  $ mkdir ~/tf2/tf/cfg/workshop $ cp ~/cfg/koth_sawmill.cfg ~/tf2/tf/cfg/workshop/cp_orange_x3.ugc454299390.cfg 


cp_orange_x3.ugc454299390.cfg echo , .



. changelevel workshop/cp_orange_x3.ugc454299390 . β€” , :





. , : sv_cheats 1 β€” - nav_generate β€” ( < >.nav), . ...



  Generating Navigation Mesh... Sampling walkable space... Sampling walkable space... Sampling walkable space... Creating navigation areas from sampled data... Connecting navigation areas... Merging navigation areas... Created new fencetop area 1781(fc537be) between 3(1f542dcf) and 49(274fa843) Finding hiding spots...DONE Finding encounter spots...DONE Finding sniper spots...DONE Computing mesh visibility... Computing mesh visibility... 0% Computing mesh visibility... 1% Computing mesh visibility... 5% Computing mesh visibility... 17% Can't compute incursion distances from the Red spawn room(s). <...> Can't compute incursion distances from the Blue spawn room(s). <...> Computing mesh visibility... 84% Optimizing mesh visibility... NavMesh Visibility List Lengths: min = 12, avg = 104, max = 280 Computing mesh visibility...DONE Finding earliest occupy times...DONE Start custom... Post custom... Custom game-specific analysis...DONE Generation complete! 77.8 seconds elapsed. Navigation map '/home/game/tf2/tf\maps\workshop/cp_orange_x3.ugc454299390.nav' saved. [TF Workshop] Preparing map ID 454299390 [TF Workshop] Successfully prepared client map from workshop [ workshop/cp_orange_x3.ugc454299390 ] ---- Host_Changelevel ----   . 


. "sv_cheats 0" server2.cfg. , , sv_cheats 0, β€” , .



β€” , . , , . .



- , . Navigation Mesh Commands , Steam Users Forum .



"" (Puppet bots). , , . . TF Wiki, . https://youtu.be/Dn9970dxQ2g



, , , . , top Atom N2800:





24 ( , ), 12, . , . , , 7%. tf_bot_join_after_player 1 .



, , β€” ( ), (koth_sawmill.cfg cp_orange_x3.ugc454299390.cfg ) , , . , β€” , - " ", , .nav . , , tf_bot_quota 0 server{1,2}.cfg β€” , .





')

Source: https://habr.com/ru/post/312928/



All Articles