nothing@nowhere - 2021-07-02

TF2 GameServer Setup

In this tutorial we're going to look at how to install a tf2 server on a ubuntu 16.04 host.

Initial Setup

I'm setting it up on an Ubuntu LXC container on proxmox:


[ 10.66.66.2/32 ] [ /dev/pts/10 ] [Github/blog/HTB]
→ ssh root@10.0.0.180 -i ~/.ssh/mainpc





root@tf2:~# dpkg --add-architecture i386
root@tf2:~# apt update -y ; apt upgrade -y
root@tf2:~# apt-get install -y software-properties-common

root@tf2:~# apt-get install -y --no-install-recommends --no-install-suggests lib32gcc1 lib32z1 libncurses5:i386  libbz2-1.0:i386  lib32gcc1  lib32stdc++6 libtinfo5:i386 libcurl3-gnutls:i386 wget unzip gettext-base libbsd0 curl tmux screen vim -y
root@tf2:~# rm -rf /var/lib/apt/lists/*

root@tf2local:~# curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxvf -
steamcmd.sh
linux32/steamcmd
linux32/steamerrorreporter
linux32/libstdc++.so.6
linux32/crashhandler.so



root@tf2local:~# ./steamcmd.sh
Redirecting stderr to '/home/steam/Steam/logs/stderr.txt'
ILocalize::AddFile() failed to load file "public/steambootstrapper_english.txt".
[  0%] Checking for available update...
[----] Downloading update (0 of 53901 KB)...
[  0%] Downloading update (738 of 53901 KB)...
[  1%] Downloading update (2417 of 53901 KB)...
[  4%] Downloading update (3721 of 53901 KB)...
[  6%] Downloading update (5180 of 53901 KB)...
[  9%] Downloading update (6593 of 53901 KB)...
	
[...]

WARNING: setlocale('en_US.UTF-8') failed, using locale: 'C'. International characters may not work.
Redirecting stderr to '/home/steam/Steam/logs/stderr.txt'
[  0%] Checking for available updates...
[----] Verifying installation...
Steam Console Client (c) Valve Corporation
-- type 'quit' to exit --
Loading Steam API...OK.

Steam>login anonymous

Connecting anonymously to Steam Public...Logged in OK
Waiting for user info...OK

Steam>force_install_dir ./tf2/

Steam>app_update 232250 validate
 Update state (0x3) reconfiguring, progress: 0.00 (0 / 0)
 Update state (0x3) reconfiguring, progress: 0.00 (0 / 0)
 Update state (0x3) reconfiguring, progress: 0.00 (0 / 0)
 Update state (0x3) reconfiguring, progress: 0.00 (0 / 0)

[...] (after like 20 minutes)

 Update state (0x101) committing, progress: 92.11 (7808672823 / 8477794661)
 Update state (0x101) committing, progress: 94.61 (8020772689 / 8477794661)
 Update state (0x101) committing, progress: 95.87 (8127457161 / 8477794661)
 Update state (0x101) committing, progress: 97.11 (8233117403 / 8477794661)
 Update state (0x101) committing, progress: 98.41 (8343138174 / 8477794661)
Success! App '232250' fully installed.

Steam>exit

root@tf2local:~$ ls
Steam  linux32  linux64  package  public  siteserverui  steamcmd.sh  tf2

root@tf2local:~$ cd tf2/

root@tf2local:~/tf2$ ls
bin  hl2  platform  srcds_linux  srcds_run  steamapps  tf  thirdpartylegalnotices.txt

root@tf2local:~/tf2$ cd tf/

root@tf2local:~/tf2/tf$ ls
bin                         maps       tf2_misc_000.vpk  tf2_misc_006.vpk  tf2_misc_012.vpk  tf2_misc_018.vpk  tf2_misc_024.vpk                      tf2_textures_dir.vpk
cfg                         materials  tf2_misc_001.vpk  tf2_misc_007.vpk  tf2_misc_013.vpk  tf2_misc_019.vpk  tf2_misc_dir.vpk                      workshop
custom                      media      tf2_misc_002.vpk  tf2_misc_008.vpk  tf2_misc_014.vpk  tf2_misc_020.vpk  tf2_sound_misc.vpk.sound.cache
download                    resource   tf2_misc_003.vpk  tf2_misc_009.vpk  tf2_misc_015.vpk  tf2_misc_021.vpk  tf2_sound_misc_dir.vpk
gameinfo.txt                scripts    tf2_misc_004.vpk  tf2_misc_010.vpk  tf2_misc_016.vpk  tf2_misc_022.vpk  tf2_sound_vo_english.vpk.sound.cache
item_whitelist_example.txt  steam.inf  tf2_misc_005.vpk  tf2_misc_011.vpk  tf2_misc_017.vpk  tf2_misc_023.vpk  tf2_sound_vo_english_dir.vpk


Now that srcds is installed, we can start configuring our server, Basically first i want the server to run a few game commands as it boots up, to do that i can either pass those commands as arguements to the srcds_run binary like so:


./srcds_run -game tf +map ctf_2fort +maxplayers 24
	

If you have that steamclient.so error do the following:


root@tf2local:~# ls
Steam  linux32  linux64  package  public  siteserverui  steamcmd.sh  tf2
root@tf2local:~# cd tf2/
root@tf2local:~/tf2# ls
bin  hl2  platform  srcds_linux  srcds_run  steamapps  tf  thirdpartylegalnotices.txt
root@tf2local:~/tf2# ./srcds_run

[...]

ProtoDefs post data loaded.
ProtoDefs post data loaded.
dlopen failed trying to load:
/root/.steam/sdk32/steamclient.so
with error:
/root/.steam/sdk32/steamclient.so: cannot open shared object file: No such file or directory
Looking up breakpad interfaces from steamclient
Calling BreakpadMiniDumpSystemInit
Unknown command "r_decal_cullsize"
Unknown command "startupmenu"
Network: IP 10.0.0.180, mode MP, dedicated Yes, ports 27015 SV / 27005 CL
Fri Jul  2 22:17:18 UTC 2021: Server Quit

root@tf2local:~/tf2# mkdir -p ~/.steam/sdk32
root@tf2local:~/tf2# updatedb
root@tf2local:~/tf2# locate steamclient.so
/root/linux32/steamclient.so
/root/linux64/steamclient.so
/root/tf2/bin/steamclient.so


root@tf2local:~/tf2# ln -s $HOME/linux32/steamclient.so ~/.steam/sdk32/

root@tf2local:~/tf2# ./srcds_run

That's how i fixed the steamclient.so error. Now instead of running the srcds binary ourselves, we can can just specify those commands in the tf/cfg/server.cfg file, if you don't know what to put in here you can just use cfg.tf:


root@tf2local:~/tf2/tf/cfg$ vim server.cfg

root@tf2local:~/tf2/tf/cfg$ cat server.cfg

hostname "void.yt"
sv_password ""
sv_lan 1
sv_cheats 1

rcon_password "changeme"
sv_rcon_banpenalty 15
sv_rcon_minfailures 15
sv_rcon_maxfailures 15
log off
sv_logfile 0
sv_logecho 0
sv_logbans 0
sm_maxhealth 100000
tf_bot_add 1 soldier expert
tf_bot_force_class soldier

sv_pure -1
sv_pure_kick_clients 0
sv_alltalk 1
mp_allowspectators 0
mp_autoteambalance 0
mp_teams_unbalance_limit 30
mp_disable_respawn_times 1
tf_bot_force_class soldier

mp_forcecamera 0
sv_allow_wait_command 0
sv_cheats 0
sv_pausable 0
mp_stalemate_enable 0
mp_stalemate_timelimit 240
mp_winlimit 0
mp_timelimit 0
tf_weapon_criticals 0
tf_use_fixed_weaponspreads 0

sv_maxrate 50000
sv_minrate 7500
sv_maxupdaterate 66
sv_minupdaterate 20
sv_maxcmdrate 66
sv_mincmdrate 0
sv_allow_point_servercommand always
	

since this server will run only one map i specified it in server.cfg


[terminal 1]
[ 10.66.66.2/32 ] [ /dev/pts/16 ] [Github/blog/HTB]
→ cd /mnt/vault/steam/steamapps/common/Team\ Fortress\ 2/tf/maps


[ 10.66.66.2/32 ] [ /dev/pts/14 ] [~/Downloads]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...

	
[terminal 2]
root@tf2local:~/tf2/tf/cfg$ cd ..
root@tf2local:~/tf2/tf$ cd maps/
root@tf2local:~/tf2/tf/maps# wget http://10.0.0.10:9090/airborne2.bsp
--2021-07-02 22:49:26--  http://10.0.0.10:9090/airborne2.bsp ; chmod 755 airborne2.bsp
Connecting to 10.0.0.10:9090... connected.
HTTP request sent, awaiting response... 200 OK
Length: 157192 (154K) [model/vnd.valve.source.compiled-map]
Saving to: 'airborne2.bsp'

airborne2.bsp                                100%[==============================================================================================>] 153.51K  --.-KB/s    in 0.01s

2021-07-02 22:49:26 (11.5 MB/s) - 'airborne2.bsp' saved [157192/157192]

root@tf2local:~/tf2/tf/maps# cd ../cfg
root@tf2local:~/tf2/tf/cfg# cat mapcycle.txt
airborne2

We can run the srcds binary to check that it's working:


root@tf2local:~/tf2# ./srcds_run -game tf +map airborne2


************** WARNING ***************
Running the dedicated server as root
is highly discouraged. It is generally
unnecessary to use root privileges to
execute the dedicated server.
**************************************


Auto detecting CPUntinue to launch in 1 secondss
Using default binary: ./srcds_linux
Server will auto-restart if there is a crash.
Using Breakpad minidump system. Version: 6623512 AppID: 232250
Setting breakpad minidump AppID = 232250
Using breakpad crash handler
Loaded 10223 VPK file hashes from /root/tf2/tf/tf2_textures.vpk for pure server operation.
Loaded 10223 VPK file hashes from /root/tf2/tf/tf2_textures.vpk for pure server operation.
Loaded 476 VPK file hashes from /root/tf2/tf/tf2_sound_vo_english.vpk for pure server operation.
Loaded 476 VPK file hashes from /root/tf2/tf/tf2_sound_vo_english.vpk for pure server operation.
Loaded 1343 VPK file hashes from /root/tf2/tf/tf2_sound_misc.vpk for pure server operation.
Loaded 1343 VPK file hashes from /root/tf2/tf/tf2_sound_misc.vpk for pure server operation.
Loaded 2634 VPK file hashes from /root/tf2/tf/tf2_misc.vpk for pure server operation.
Loaded 2634 VPK file hashes from /root/tf2/tf/tf2_misc.vpk for pure server operation.
Loaded 2634 VPK file hashes from /root/tf2/tf/tf2_misc.vpk for pure server operation.
Loaded 1217 VPK file hashes from /root/tf2/hl2/hl2_textures.vpk for pure server operation.
Loaded 574 VPK file hashes from /root/tf2/hl2/hl2_sound_vo_english.vpk for pure server operation.
Loaded 383 VPK file hashes from /root/tf2/hl2/hl2_sound_misc.vpk for pure server operation.
Loaded 451 VPK file hashes from /root/tf2/hl2/hl2_misc.vpk for pure server operation.
Loaded 451 VPK file hashes from /root/tf2/hl2/hl2_misc.vpk for pure server operation.
Loaded 5 VPK file hashes from /root/tf2/platform/platform_misc.vpk for pure server operation.
Loaded 5 VPK file hashes from /root/tf2/platform/platform_misc.vpk for pure server operation.
server_srv.so loaded for "Team Fortress"
For FCVAR_REPLICATED, ConVar must be defined in client and game .dlls (sv_use_steam_voice)
ProtoDefs post data loaded.
ProtoDefs loaded. 16.46 MB used
ProtoDefs post data loaded.
ProtoDefs loaded. 16.46 MB used
maxplayers set to 24
No '-replayserverdir' parameter found - using default replay folder.
Replay: Creating thread pool...succeeded.
Replay: Starting thread pool with 4 threads...succeeded.
Cleaning files from temp dir, "/root/tf2/tf/replay/server/tmp/" ...no files removed.
ProtoDefs post data loaded.
ProtoDefs post data loaded.
Looking up breakpad interfaces from steamclient
Calling BreakpadMiniDumpSystemInit
Unknown command "r_decal_cullsize"
ConVarRef dev_loadtime_map_start doesn't point to an existing ConVar
Unknown command "startupmenu"
Network: IP 10.0.0.180, mode MP, dedicated Yes, ports 27015 SV / 27005 CL
Initializing Steam libraries for secure Internet server
[S_API] SteamAPI_Init(): Loaded local 'steamclient.so' OK.
CAppInfoCacheReadFromDiskThread took 46 milliseconds to initialize
CApplicationManagerPopulateThread took 0 milliseconds to initialize (will have waited on CAppInfoCacheReadFromDiskThread)
RecordSteamInterfaceCreation (PID 453): SteamGameServer013 /
RecordSteamInterfaceCreation (PID 453): SteamUtils010 /
Setting breakpad minidump AppID = 440
Looking up breakpad interfaces from steamclient
Calling BreakpadMiniDumpSystemInit
RecordSteamInterfaceCreation (PID 453): SteamGameServer013 /
RecordSteamInterfaceCreation (PID 453): SteamUtils010 /
RecordSteamInterfaceCreation (PID 453): SteamNetworking006 /
RecordSteamInterfaceCreation (PID 453): SteamGameServerStats001 /
RecordSteamInterfaceCreation (PID 453): STEAMHTTP_INTERFACE_VERSION003 /
RecordSteamInterfaceCreation (PID 453): STEAMINVENTORY_INTERFACE_V003 /
RecordSteamInterfaceCreation (PID 453): STEAMUGC_INTERFACE_VERSION014 /
RecordSteamInterfaceCreation (PID 453): STEAMAPPS_INTERFACE_VERSION008 /
Setting breakpad minidump AppID = 232250
No account token specified; logging into anonymous game server account.  (Use sv_setsteamaccount to login to a persistent account.)
RecordSteamInterfaceCreation (PID 453): SteamGameServer013 /
RecordSteamInterfaceCreation (PID 453): SteamUtils010 /
RecordSteamInterfaceCreation (PID 453): SteamNetworking006 /
RecordSteamInterfaceCreation (PID 453): SteamGameServerStats001 /
RecordSteamInterfaceCreation (PID 453): STEAMHTTP_INTERFACE_VERSION003 /
RecordSteamInterfaceCreation (PID 453): STEAMINVENTORY_INTERFACE_V003 /
RecordSteamInterfaceCreation (PID 453): STEAMUGC_INTERFACE_VERSION014 /
RecordSteamInterfaceCreation (PID 453): STEAMAPPS_INTERFACE_VERSION008 /
ConVarRef room_type doesn't point to an existing ConVar
Executing dedicated server config file server.cfg
Using map cycle file 'cfg/mapcycle.txt'.
RecordSteamInterfaceCreation (PID 453): SteamGameStats001 /
Warning: failed to init SDL thread priority manager: SDL not found
Set motd from file 'cfg/motd_default.txt'.  ('cfg/motd.txt' was not found.)
Set motd_text from file 'cfg/motd_text_default.txt'.  ('cfg/motd_text.txt' was not found.)
SV_ActivateServer: setting tickrate to 66.7
func_regenerate(func_regenerate) has no associated model.
RecordSteamInterfaceCreation (PID 453): SteamGameCoordinator001 /
Connection to game coordinator established.
Current item schema is up-to-date with version 2B55A3E4.
--------------------------------------------------------
sv_pure set to -1.
Note: Waiting for the next changelevel to apply the current value.
--------------------------------------------------------
'airborne2.cfg' not present; not executing.
Server is hibernating
Connection to Steam servers successful.
Assigned anonymous gameserver Steam ID [A:1:929544195:17849].
VAC secure mode is activated.

From here we know that the server is running, and we can check it ingame:

Now that's done, we verified that we could run the srcds binary like this, however we could have a more refined approach and actually make a systemd service to run this as the debian LXC container starts.


root@tf2local:~# vim /etc/systemd/system/tf2server.service

root@tf2local:~/tf2# cat /etc/systemd/system/tf2server.service
[Unit]
Description=TF2 Server
After=network.target
After=systemd-user-sessions.service
After=network-online.target

[Service]
Type=simple
ExecStart=/root/tf2/srcds_run -game tf +map airborne2 
ExecStop=/root/tf2/killserver.sh
KillMode=process

[Install]
WantedBy=multi-user.target

root@tf2local:~/tf2# vim killserver.sh
root@tf2local:~/tf2# cat killserver.sh
#!/bin/bash
kill -9 $(pidof srcds_linux)

root@tf2local:~/tf2# chmod +x killserver.sh

root@tf2local:~# systemctl enable --now tf2server

root@tf2local:~# systemctl status tf2server
* tf2server.service - TF2 Server
   Loaded: loaded (/etc/systemd/system/tf2server.service; disabled; vendor preset: enabled)
   Active: active (running) since Fri 2021-07-02 21:13:15 UTC; 3s ago
 Main PID: 10722 (srcds_run)
    Tasks: 2 (limit: 7372)
   Memory: 1.2M
   CGroup: /system.slice/tf2server.service
           |-10722 /bin/sh /home/steam/tf2/srcds_run
           `-10732 sleep 1

Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamGameServer013 /
Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamUtils010 /
Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamNetworking006 /
Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamGameServerStats001 /
Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): STEAMHTTP_INTERFACE_VERSION003 /
Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): STEAMINVENTORY_INTERFACE_V003 /
Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): STEAMUGC_INTERFACE_VERSION014 /
Jul 02 23:03:55 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): STEAMAPPS_INTERFACE_VERSION008 /
Jul 02 23:04:05 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamGameStats001 /
Jul 02 23:04:09 tf2local srcds_run[778]: RecordSteamInterfaceCreation (PID 778): SteamGameCoordinator001 /

And that's it! We managed to setup a simple local tf2 server.

In-game RCON and Bonus plugins



if you want to run console comamnds that require privileges to do so on your local server, you need to use rcon, and since we specified the password earlier, we do the following:

Obviously don't give the rcon password to anyone you don't trust. Now if you want some plugins you can install sourcemod and metamod:


root@tf2local:~/tf2# cd tf/
root@tf2local:~/tf2/tf# ls
bin                         maps               steam.inf         tf2_misc_006.vpk  tf2_misc_013.vpk  tf2_misc_020.vpk                tf2_sound_misc_dir.vpk
cfg                         materials          tf2_misc_000.vpk  tf2_misc_007.vpk  tf2_misc_014.vpk  tf2_misc_021.vpk                tf2_sound_vo_english.vpk.sound.cache
custom                      media              tf2_misc_001.vpk  tf2_misc_008.vpk  tf2_misc_015.vpk  tf2_misc_022.vpk                tf2_sound_vo_english_dir.vpk
download                    modelsounds.cache  tf2_misc_002.vpk  tf2_misc_009.vpk  tf2_misc_016.vpk  tf2_misc_023.vpk                tf2_textures_dir.vpk
downloadlists               replay             tf2_misc_003.vpk  tf2_misc_010.vpk  tf2_misc_017.vpk  tf2_misc_024.vpk                workshop
gameinfo.txt                resource           tf2_misc_004.vpk  tf2_misc_011.vpk  tf2_misc_018.vpk  tf2_misc_dir.vpk
item_whitelist_example.txt  scripts            tf2_misc_005.vpk  tf2_misc_012.vpk  tf2_misc_019.vpk  tf2_sound_misc.vpk.sound.cache
root@tf2local:~/tf2/tf# wget https://sm.alliedmods.net/smdrop/1.10/sourcemod-1.10.0-git6509-linux.tar.gz
--2021-07-03 17:25:03--  https://sm.alliedmods.net/smdrop/1.10/sourcemod-1.10.0-git6509-linux.tar.gz
Resolving sm.alliedmods.net (sm.alliedmods.net)... 104.26.8.106, 104.26.9.106, 172.67.73.151, ...
Connecting to sm.alliedmods.net (sm.alliedmods.net)|104.26.8.106|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 17422077 (17M) [application/x-gzip]
Saving to: 'sourcemod-1.10.0-git6509-linux.tar.gz'

sourcemod-1.10.0-git6509-linux.tar.gz         100%[===============================================================================================>]  16.61M  1.03MB/s    in 17s

2021-07-03 17:25:21 (998 KB/s) - 'sourcemod-1.10.0-git6509-linux.tar.gz' saved [17422077/17422077]

root@tf2local:~/tf2/tf# wget https://mms.alliedmods.net/mmsdrop/1.11/mmsource-1.11.0-git1144-linux.tar.gz
--2021-07-03 17:30:14--  https://mms.alliedmods.net/mmsdrop/1.11/mmsource-1.11.0-git1144-linux.tar.gz
Resolving mms.alliedmods.net (mms.alliedmods.net)... 104.26.8.106, 172.67.73.151, 104.26.9.106, ...
Connecting to mms.alliedmods.net (mms.alliedmods.net)|104.26.8.106|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1859179 (1.8M) [application/x-gzip]
Saving to: 'mmsource-1.11.0-git1144-linux.tar.gz'

mmsource-1.11.0-git1144-linux.tar.gz          100%[===============================================================================================>]   1.77M   677KB/s    in 2.7s

2021-07-03 17:30:18 (677 KB/s) - 'mmsource-1.11.0-git1144-linux.tar.gz' saved [1859179/1859179]

then extract both files:


root@tf2local:~/tf2/tf# tar -xzf mmsource-1.11.0-git1144-linux.tar.gz
root@tf2local:~/tf2/tf# tar -xzf sourcemod-1.10.0-git6509-linux.tar.gz

root@tf2local:~/tf2/tf# rm mmsource-1.11.0-git1144-linux.tar.gz
root@tf2local:~/tf2/tf# rm sourcemod-1.10.0-git6509-linux.tar.gz

root@tf2local:~/tf2/tf# ls -lash addons/
total 24K
4.0K drwx------  4 1000 1000 4.0K May  6  2018 .
4.0K drwxr-xr-x 15 root root 4.0K Jul  3 17:32 ..
4.0K drwx------  3 1000 1000 4.0K May  6  2018 metamod
4.0K -rw-------  1 1000 1000   50 May 26  2014 metamod.vdf
4.0K -rw-------  1 1000 1000   58 Dec 20  2017 metamod_x64.vdf
4.0K drwx------ 11 1000 1000 4.0K Oct  1  2019 sourcemod

Now that's done we have our addons folder, we will need to configure admins_simple.ini


root@tf2local:~/tf2/tf# cd addons/sourcemod/configs/
root@tf2local:~/tf2/tf/addons/sourcemod/configs# ls
admin_groups.cfg  admin_overrides.cfg  adminmenu_custom.txt    adminmenu_sorting.txt  admins_simple.ini  core.cfg       geoip          maplists.cfg
admin_levels.cfg  adminmenu_cfgs.txt   adminmenu_grouping.txt  admins.cfg             banreasons.txt     databases.cfg  languages.cfg  sql-init-scripts
root@tf2local:~/tf2/tf/addons/sourcemod/configs# vim admins_simple.ini

Basically in here we add our SteamID with the "99:z" permissions


root@tf2local:~/tf2/tf/addons/sourcemod/configs# tail -n 3 admins_simple.ini
"STEAM_0:0:576829438"   "99:z"


And with this we can restart our tf2 server:


root@tf2local:~/tf2/tf/addons/sourcemod/configs# systemctl restart tf2server

Now when we connect back to the server we can type !sm_admin in chat to use the sourcemod admin commands pannel:

If you need to make any custom scripts, for example making players and bots spawn with extra health, you can use the scripting directory in sourcemod:


root@tf2local:~/tf2/tf/addons/sourcemod# cd scripting/
root@tf2local:~/tf2/tf/addons/sourcemod/scripting# ls -l
total 1080
drwx------ 2 1000 1000   4096 May  6  2018 admin-flatfile
-rw------- 1 1000 1000   9857 May  6  2018 admin-sql-prefetch.sp
-rw------- 1 1000 1000  21482 Dec 17  2018 admin-sql-threaded.sp
-rw------- 1 1000 1000   4822 Jul 12  2018 adminhelp.sp
drwx------ 2 1000 1000   4096 Sep 15  2019 adminmenu
-rw------- 1 1000 1000   7284 May 29  2019 adminmenu.sp
-rw------- 1 1000 1000   3637 Dec 17  2018 antiflood.sp
drwx------ 2 1000 1000   4096 Dec 17  2018 basebans
-rw------- 1 1000 1000   9755 Dec 17  2018 basebans.sp
-rw------- 1 1000 1000  12112 May  6  2018 basechat.sp
drwx------ 2 1000 1000   4096 Oct 24  2020 basecomm
-rw------- 1 1000 1000   7206 Dec 17  2018 basecomm.sp
drwx------ 2 1000 1000   4096 Oct  7  2019 basecommands
-rw------- 1 1000 1000  11414 Feb 25  2020 basecommands.sp
-rw------- 1 1000 1000  12849 Jul 12  2018 basetriggers.sp
drwx------ 2 1000 1000   4096 Mar  3  2019 basevotes
-rw------- 1 1000 1000  12326 May 12  2019 basevotes.sp
-rw------- 1 1000 1000   4386 May  6  2018 clientprefs.sp
-rwx------ 1 1000 1000    452 May  6  2018 compile.sh
drwx------ 2 1000 1000   4096 May  6  2018 funcommands
-rw------- 1 1000 1000  10977 Oct 12  2018 funcommands.sp
drwx------ 2 1000 1000   4096 May  6  2018 funvotes
-rw------- 1 1000 1000  10707 May 12  2019 funvotes.sp
drwx------ 2 1000 1000   4096 Jun 25 15:36 include
-rw------- 1 1000 1000  34195 May 29  2019 mapchooser.sp
-rw------- 1 1000 1000   6878 May  6  2018 nextmap.sp
-rw------- 1 1000 1000  13402 Apr 30  2020 nominations.sp
drwx------ 2 1000 1000   4096 May  6  2018 playercommands
-rw------- 1 1000 1000   3351 May  6  2018 playercommands.sp
-rw------- 1 1000 1000   3484 May  6  2018 randomcycle.sp
-rw------- 1 1000 1000   8191 May  6  2018 reservedslots.sp
-rw------- 1 1000 1000   7322 Jul 12  2018 rockthevote.sp
-rw------- 1 1000 1000   3712 May  6  2018 sounds.sp
-rwx------ 1 1000 1000 333328 Jun 25 15:37 spcomp
-rwx------ 1 1000 1000 434152 Jun 25 15:38 spcomp64
-rw------- 1 1000 1000  25196 Apr  6  2019 sql-admin-manager.sp
drwx------ 2 1000 1000   4096 May  6  2018 testsuite

root@tf2local:~/tf2/tf/addons/sourcemod/scripting# cat maxhealth.sp
/**
 * MaxHealth Changer by bl4nk
 *
 * Description:
 *   Change the max health of players at spawn.
 *
 */

#pragma semicolon 1

#include <sourcemod>

// Global Definitions
#define PLUGIN_VERSION "1.0.0"

new Handle:cvarAmount;

public Plugin:myinfo =
{
    name = "MaxHealth Changer",
    author = "bl4nk",
    description = "Change the max health of players at spawn",
    version = PLUGIN_VERSION,
    url = "http://forums.alliedmods.net"
};

public OnPluginStart()
{
    CreateConVar("sm_maxhealthchanger_version", PLUGIN_VERSION, "MaxHealth Changer Version");
    cvarAmount = CreateConVar("sm_maxhealth", "200", "Amount of life to change health to upon spawn");

    HookEvent("player_spawn", event_PlayerSpawn);
}

public event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
    new client = GetClientOfUserId(GetEventInt(event,"userid"));
    CreateTimer(0.1, timer_PlayerSpawn, client);
}

public Action:timer_PlayerSpawn(Handle:timer, any:client)
{
    new MaxHealth = GetConVarInt(cvarAmount);
    SetEntData(client, FindDataMapInfo(client, "m_iMaxHealth"), MaxHealth, 4, true);
    SetEntData(client, FindDataMapInfo(client, "m_iHealth"), MaxHealth, 4, true);
}


Now before we move on we need to compile that .sp file:


root@tf2local:~/tf2/tf/addons/sourcemod/scripting# ./compile.sh maxhealth.sp

Compiling maxhealth.sp...
SourcePawn Compiler 1.10.0.6509
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC

Code size:             3668 bytes
Data size:             2600 bytes
Stack/heap size:      16384 bytes
Total requirements:   22652 bytes

root@tf2local:~/tf2/tf/addons/sourcemod/scripting# ls -lash compiled/
total 16K
4.0K drwxr-xr-x  2 root root 4.0K Jul  3 18:17 .
4.0K drwx------ 14 1000 1000 4.0K Jul  3 18:30 ..
8.0K -rw-r--r--  1 root root 4.3K Jul  3 18:26 maxhealth.smx

root@tf2local:~/tf2/tf/addons/sourcemod/scripting# cp compiled/maxhealth.smx ../plugins/maxhealth.smx

Now that we moved the compiled plugin into the plugins directory, we restart the server to reload the configs:


root@tf2local:~/tf2/tf/addons/sourcemod/scripting# cd ..
root@tf2local:~/tf2/tf/addons/sourcemod# systemctl restart tf2server

We restart the server to reload the configs, and we can verify it is working by executing the sm_maxhealth x command, if you use it ingame you need to use rcon sm_maxhealth x:

likewise, we can also just put it in the server.cfg file or just pass it as arguements when we run the srcds_run binary.


root@tf2local:~/tf2/tf/cfg# vim server.cfg
root@tf2local:~/tf2/tf/cfg# cat server.cfg
hostname "void.yt"
sv_password ""
sv_lan 1
sv_cheats 1

rcon_password "void.yt"
mp_enableroundwaittime 0
sv_rcon_banpenalty 15
sv_rcon_minfailures 15
sv_rcon_maxfailures 15
log off
sv_logfile 0
sv_logecho 0
sv_logbans 0
sm_maxhealth 100000
tf_bot_force_class soldier

sv_pure -1
sv_pure_kick_clients 0
sv_alltalk 1
mp_allowspectators 0
mp_autoteambalance 0
mp_teams_unbalance_limit 30
mp_disable_respawn_times 1
tf_bot_force_class soldier

mp_forcecamera 0
sv_allow_wait_command 0
sv_cheats 0
sv_pausable 0
mp_stalemate_enable 0
mp_stalemate_timelimit 240
mp_winlimit 0
mp_timelimit 0
tf_weapon_criticals 0
tf_use_fixed_weaponspreads 0

sv_maxrate 50000
sv_minrate 7500
sv_maxupdaterate 66
sv_minupdaterate 20
sv_maxcmdrate 66
sv_mincmdrate 0
sv_allow_point_servercommand always
tf_bot_add 1 soldier red expert


root@tf2local:~/tf2/tf/cfg# systemctl restart tf2server

And that's how i setup my own personal TF2 training server!

Docker Setup



With further testing, i realised that setting up tf2 servers is dependant on old 32 bit librairies, and you can face any number of problems (most notably the segmentation fault core dumped crashes that will never tell you the source of the issue, even with the -debug flag). So instead let's set it up using docker:



root@docker0:/home# mkdir -p /home/tf2/server/tf/maps/
root@docker0:/home# tree .
.
├── nothing
└── tf2
    └── server
        └── tf
            └── maps
                └── altar.bsp

root@docker0:~# cd ~ ; 	

root@docker0:~# docker pull cm2network/tf2:latest
root@docker0:~# docker pull cm2network/tf2:sourcemod

root@docker0:~# mkdir tf2
root@docker0:~/tf2# vim docker-compose.yml
root@docker0:~/tf2# cat docker-compose.yml

version: "3"
services:
    tf2:
        image: cm2network/tf2:sourcemod
        container_name: tf2
        environment:
          - SRCDS_RCONPW=void.yt
          - SRCDS_PW=void.yt
          - SRCDS_PORT=27015
          - SRCDS_TV_PORT=27020
          #- SRCDS_NET_PUBLIC_ADDRESS="0"
          - SRCDS_IP="0"
          - SRCDS_FPSMAX=300
          - SRCDS_TICKRATE=66
          - SRCDS_MAXPLAYERS=14
          - SRCDS_HOSTNAME=void.yt
          - SRCDS_TOKEN="void.yt"
          - SRCDS_STARTMAP="altar"
        volumes:
            - ./data:/home/steam/tf-dedicated/
            - ./logs:/home/steam/Steam/logs
        ports:
            - 27015:27015
            - 27020:27020
        network_mode: host


root@docker0:~/tf2# mkdir data
root@docker0:~/tf2# mkdir logs
root@docker0:~/tf2# chmod 777 data/
root@docker0:~/tf2# chmod 777 logs/


root@docker0:~/tf2# docker-compose up
#let it finish then CTRL+C
#move altar.bsp in ~/tf2/data/tf/maps 

root@docker0:~/tf2/data/tf/maps# ls -lash altar.bsp
172K -rw-r--r-- 1 root root 169K Oct 30 16:12 altar.bsp

#append the sourcemodded commands you want to server.cfg :

root@docker0:~# tail -n13 tf2/data/tf/cfg/server.cfg

sm_maxhealth 100000
tf_bot_add 1 soldier expert
tf_bot_force_class soldier
mp_allowspectators 0
mp_autoteambalance 0
mp_teams_unbalance_limit 30
mp_disable_respawn_times 1
tf_bot_force_class soldier
sv_allow_point_servercommand always

Then compile the maxhealth mod in the container:


root@docker0:~# docker exec -it tf2 bash
steam@docker0:~/tf-dedicated/tf/addons/sourcemod/scripting$ nano maxhealth.sp
steam@docker0:~/tf-dedicated/tf/addons/sourcemod/scripting$ cat maxhealth.sp
/**
 * MaxHealth Changer by bl4nk
 *
 * Description:
 *   Change the max health of players at spawn.
 *
 */

#pragma semicolon 1

#include 

// Global Definitions
#define PLUGIN_VERSION "1.0.0"

new Handle:cvarAmount;

public Plugin:myinfo =
{
    name = "MaxHealth Changer",
    author = "bl4nk",
    description = "Change the max health of players at spawn",
    version = PLUGIN_VERSION,
    url = "http://forums.alliedmods.net"
};

public OnPluginStart()
{
    CreateConVar("sm_maxhealthchanger_version", PLUGIN_VERSION, "MaxHealth Changer Version");
    cvarAmount = CreateConVar("sm_maxhealth", "200", "Amount of life to change health to upon spawn");

    HookEvent("player_spawn", event_PlayerSpawn);
}

public event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
    new client = GetClientOfUserId(GetEventInt(event,"userid"));
    CreateTimer(0.1, timer_PlayerSpawn, client);
}

public Action:timer_PlayerSpawn(Handle:timer, any:client)
{
    new MaxHealth = GetConVarInt(cvarAmount);
    SetEntData(client, FindDataMapInfo(client, "m_iMaxHealth"), MaxHealth, 4, true);
    SetEntData(client, FindDataMapInfo(client, "m_iHealth"), MaxHealth, 4, true);
}

steam@docker0:~/tf-dedicated/tf/addons/sourcemod/scripting$ ./compile.sh maxhealth.sp

Compiling maxhealth.sp...
SourcePawn Compiler 1.10.0.6522
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC

Code size:             3668 bytes
Data size:             2600 bytes
Stack/heap size:      16384 bytes
Total requirements:   22652 bytes

steam@docker0:~/tf-dedicated/tf/addons/sourcemod/scripting$ cp compiled/maxhealth.smx ../plugins/maxhealth.smx

steam@docker0:~/tf-dedicated/tf/addons/sourcemod/configs# vim admins_simple.ini
"STEAM_0:0:576829438"   "99:z"


Then restart the container:


CTRL+C
root@docker0:~/tf2# docker-compose up

	
[ 10.66.66.2/32 ] [ /dev/pts/19 ] [~]
→ cat tf2.sh
#!/bin/sh

 /usr/bin/steam -silent -no-browser -offline -applaunch 440 -windowed -w 3840 -h 2160 +connect 192.168.0.200 -noborder -console -novid +viewmodel_fov 130 >/dev/null 2>/dev/null &
echo 'rcon_password void.yt ; rcon sv_cheats 1; rcon tf_bot_add 2 soldier red expert; rcon buddha'

My Bunker

Some Address 67120,
Duttlenheim, France.

About Ech0

This cute theme was created to showcase your work in a simple way. Use it wisely.