AMXXプラグイン作ってた。


名づけて「Connect And Disconnect Auto Config Loader」略して「CACACL」。
たいそうな名前をつけたけど、やることは勝手に設定ファイルを読み込むだけー。
製作時間5時間ほど。
日本語の資料がないってきつい!



作るに至った理由。

CSのサーバでFPS1000にすると、CPUをその分食います。
今の環境では10%前後になりました。カーネルをいじる前は3%でした。
この差はなかなか大きいです。
そして、知り合いにBOTを撃たせたりすると、BOTを消さないで切断したりします。
BOTが残るのは大変Fu*kな事態で、BOTが居る分だけCPUも多く食べます。
しかし、
プレイヤーが居ないのに、フル稼働してる鯖とか。
プレイヤーが居ないのに、BOTが動いてる鯖とか。
これらはどうかんがえても、無駄です。
CPUを1%でも多く使っていればその分電気を食べます。


サービスを提供する必要があるときだけ提供するべきです。
こまめな稼働管理で電気代も月50円ぐらい浮くかもしれません。


実装までの考え方。

まず、稼働率を抑えるには、例に出たとおり、

  1. 稼動FPSを下げる。
  2. BOTを蹴っ飛ばす。

この2つの処理ができれば、とりあえずはいいわけです。


稼動FPSはsys_ticrateによって動的に変更できます(この設定値未満のFPSで稼動するようになる。)
zbotやpodbotはrconでキックすることができます。(bot_kick , pb removebots)
rconで実行できるコマンドであれば、設定ファイルに書き込み読み込んで反映させることができます。
なので自動的に読み込めばOKです。


読み込むタイミングは簡単で、
最初に誰かが接続してきた場合と、最後に誰かが切断するときの2つです。
前者を稼動中状態にする設定、後者を休憩状態にする設定を読み込ませることで実現できます。
前者はamx_cacacl_connect.cfg、後者はamx_cacacl_disconnect.cfgを読ませることにします。

実装とソース

#include <amxmodx>

new bool:cacacl_flag=false

public plugin_init() { 
	register_plugin("amx_cacacl","0.0","noob")
	set_task(10.0,"runnning_server")
	if (!cvar_exists("sv_dropwpn"))	register_cvar("sv_dropwpn", "0" )
}

public runnning_server(){
	if(!cacacl_flag){
		server_cmd("exec amx_cacacl_disconnect.cfg")
	}
	return PLUGIN_CONTINUE
}

// 接続した
public client_connect(id){
	if(!cacacl_flag){
		server_cmd("exec amx_cacacl_connect.cfg")
		cacacl_flag = true
	}
	return PLUGIN_CONTINUE
}

// 切断した
public client_disconnect(id){
	new player[32], num;
	get_players(player, num, "c");
	
	if(cacacl_flag && num <= 1){
		server_cmd("exec amx_cacacl_disconnect.cfg")
		cacacl_flag = false
	}
	return PLUGIN_CONTINUE
}


AMXとAMXXの両方で動作するはず。

メモ

server_cmd関数を使うことで、サーバやrconからやるのと同じ操作をすることができる。


BOTの駆除。
人数を取得するときに、get_playersnum関数があるのだが、BOTも含まれてしまう。
人数をカウントするときは、BOTを含めたくない。
調べると、プレイヤーの人数を取得するときのget_players関数で、cオプションをつけると、
BOTを除いた人数を取得できるので、コレを用いる。


一応考える必要もなさそうなのだが、負荷について考えた。
オプション次第で定期的に実行できるようにするset_task関数は使いたくなかった。
なぜなら、人数を5秒〜10秒周期で取得するのはちょっと負担になるんじゃ?と思ったから。
調べると、ユーザーの接続・切断を検出する関数があった。
client_connect関数とclient_disconnect関数。それぞれ引数に接続・切断したプレイヤーのidがつく。
コレを用いれば、必要な動作を最小限で済むのではないか、と思った。
これなら、切断時にだけ人数チェックするだけでOKになり、定期的にチェックするより効率がいいと思う。
ちなみに、client_disconnectは切断判定→切断の切断判定時に行われるので、
プレイヤーが1人居た場合、client_disconnectでプレイヤー人数を調べると、1が返ってくる。
なので1以下の場合は休憩状態に入るようにした。


ここまで書いて思ったが、一番よさげなのはグローバル変数に0を持たせて、
接続したら1増やし、切断したら1減らして、0になったら休憩状態、1になったら稼動状態にする方法。
これなら、get_players関数を使わなくて済む、と・・・てか、これでよかったじゃん!!
文法的にも処理系的に考えてこっちのほうがラクで早いじゃん・・・



初回起動時は、server.cfgよりも先にAMXXプラグインの処理が行われる事が多いようなので、
set_taskで起動して約10秒後に休憩状態の設定になるようにした。
set_taskは余計なオプションをつけないと、初回の1度だけ実行してくれる。


また、何度も読み込む必要もないので、
1度読み込んだらまた読み込む必要があるときまで読み込まないようにする。(フラグで判断)



FPS低減の効果。

稼動状態
stats
CPU   In    Out   Uptime  Users   FPS    Players
 9.00  3.26  4.87      35    10  767.46       1

休止状態
stats
CPU   In    Out   Uptime  Users   FPS    Players
 3.00  0.00  0.00      42    10   50.96       0


稼動状態にするときはserver.cfgだけexecしてもOKだと思う。
休止状態は、BOTの排除、sys_ticrateの変更をする(↑は50設定)

後日談

メモで書いたことに、
グローバル変数に0を持たせてそれでカウントする〜ってのを考えたけど、
コレを実際に試してみたら、意図したとおり動作するんだけど、問題があった。
BOTの追加時にclient_connect、BOTの削除時にclient_disconnectが呼ばれてしまうんですよ。
なので今回やった方法がbestなのかな。と思う。