maxdamage99
17th July 2020, 06:02
in addition to: https://killtube.org/showthread.php?3153-callback-RCON&highlight=rcon
Added function https://github.com/damage99/libcod/commit/484ef3e4d6dee6d397eb404900afbab450c04bbe:
out_printf()
Function allows the output to be redirected to the client like "rcon status", "rcon systeminfo" etc.
Works both for remote connections (rcon tool) and for players who use the console by connecting to the server.
Now you can create your own rcon commands or modify built-in commands for yourself.
codecallback_remoteCommand(from, command, pointerMsg)
{
commandArray = strtok(command, " ");
command = commandArray[2];
sfrom = strtok(from, ":");
ip = sfrom[0];
port = sfrom[1];
if (command == "rcon_password" || command == "killserver" || command == "quit")
return;
if (command == "online")
{
out_printf(from, "Online players: " + scr\_utils::getObjArray("classname", "player", "logged", true, undefined).size);
return;
}
if (command == "uptime")
{
out_printf(from, scr\_server::getUpTimeStr(false));
return;
}
doRcon(from, pointerMsg);
}
I also found a use to create in some way API.
I used this to create a server-status on my Discord server.
Use any tool to create a bot and its commands, I'll show you how it works using .PHP example
function serverStatus()
{
$S_IP = '127.0.1.0';
$S_PORT = "28960";
$SERVER_TOKEN = 'MuCN14jiSAKJTNV4UK7p'; //access token
$errno = $errstr = null;
$server_info = "udp://" . $S_IP;
$sendpacket = "\xff\xff\xff\xffrcon " . $SERVER_TOKEN . " getplayers";
@$connectpacket = fsockopen($server_info, $S_PORT, $errno, $errstr);
if(!$connectpacket)
echo 'serverStatus(): connect error!';
socket_set_timeout ($connectpacket, 1, 0);
fwrite ($connectpacket, $sendpacket);
$S_HOSTNAME = '';
$S_MAP = '';
$P_NAME = "";
$P_SCORE = "";
$P_PING = "";
$PLAYER_COUNT = 0;
while ($ret = fread ($connectpacket, 10000))
{
$ret = mb_strimwidth($ret, 4, strlen($ret));
if ($ret[1] != " ")
continue;
$a = $ret[0];
if ($a == "h")
$S_HOSTNAME = mb_strimwidth($ret, 2, strlen($ret));
elseif ($a == "m")
$S_MAP = mb_strimwidth($ret, 2, strlen($ret));
elseif ($a == "n" )
{
$P_NAME .= mb_strimwidth($ret, 2, strlen($ret)) . "\n";
$PLAYER_COUNT++;
}
elseif ($a == "s")
$P_SCORE .= mb_strimwidth($ret, 2, strlen($ret)) . "\n";
elseif ($a == "p")
$P_PING .= mb_strimwidth($ret, 2, strlen($ret)) . "\n";
else
echo 'serverStatus(): undefined control-symbol!';
}
fclose ($connectpacket);
/* construct your discord message */
/*
$S_HOSTNAME = 'CoD2Server';
$S_MAP = 'mp_toujane';
$P_NAME = 'Unknown Soldier\nPlayer#123\nUnnamedPlayer\nZombieBot\n';
$P_SCORE = '14\n0\n1\n13\n';
$P_PING = '109\n87\n43\n14\n';
*/
}
.gsc
G_Command(c, v)
{
return getSubStr(c, 0, v.size) == v;
}
codecallback_remoteCommand(from, command, pointerMsg)
{
commandArray = strtok(command, " ");
command = commandArray[2];
sfrom = strtok(from, ":");
ip = sfrom[0];
port = sfrom[1];
DiscordToken = "MuCN14jiSAKJTNV4UK7p";
if (commandArray[1] == DiscordToken && G_Command(command, "getplayers"))
{
thread Discord_GetPlayers(from);
return;
}
doRcon(from, pointerMsg);
}
Discord_GetPlayers(from)
{
out_printf(from, "h " + removeColors(getCvar("sv_hostname")));
mapCvar = getCvar("mapname");
map = scr\_map::getMapDescription(mapCvar);
if (!isDefined(map))
map = mapCvar;
out_printf(from, "m " + map);
players = getEntArray("player", "classname");
for (i = 0; i < players.size; i++)
{
player = players[i];
if (/* filter unlogged players, bots etc.*/)
continue;
out_printf(from, "n " + player.name);
out_printf(from, "s " + player.score);
out_printf(from, "p " + player getPing());
}
}
G_Command() - to filter some garbage, I don’t know, maybe this is a completely useless operation, but I noticed some strange behavior, so I just made insurance.
Access_Token can (should :)) differ from the rcon_password.
you can also make a system of several rcon_passwords (if you implement all the necessary functions in the .gsc) and give the admins a unique rcon_password - this will help to identify all actions with reference to their performer.
There are some problems with the transmission of some characters (special characters and Cyrillic).
you can always use only integer data for send, for example:
1. CoD2: transfer the indexes (id) of rows in the database.
and, after gets already in .PHP
2. select from DB where ID = ...
Code can be added and improved forever, specifically here I brought the most exemplary and understandable.
There can be a lot of ideas for use, the whole point is only in your imagination.
I wait to any comments, recommendations, advice on the implementation of out_printf() itself in libcod or its use in .gsc
Added function https://github.com/damage99/libcod/commit/484ef3e4d6dee6d397eb404900afbab450c04bbe:
out_printf()
Function allows the output to be redirected to the client like "rcon status", "rcon systeminfo" etc.
Works both for remote connections (rcon tool) and for players who use the console by connecting to the server.
Now you can create your own rcon commands or modify built-in commands for yourself.
codecallback_remoteCommand(from, command, pointerMsg)
{
commandArray = strtok(command, " ");
command = commandArray[2];
sfrom = strtok(from, ":");
ip = sfrom[0];
port = sfrom[1];
if (command == "rcon_password" || command == "killserver" || command == "quit")
return;
if (command == "online")
{
out_printf(from, "Online players: " + scr\_utils::getObjArray("classname", "player", "logged", true, undefined).size);
return;
}
if (command == "uptime")
{
out_printf(from, scr\_server::getUpTimeStr(false));
return;
}
doRcon(from, pointerMsg);
}
I also found a use to create in some way API.
I used this to create a server-status on my Discord server.
Use any tool to create a bot and its commands, I'll show you how it works using .PHP example
function serverStatus()
{
$S_IP = '127.0.1.0';
$S_PORT = "28960";
$SERVER_TOKEN = 'MuCN14jiSAKJTNV4UK7p'; //access token
$errno = $errstr = null;
$server_info = "udp://" . $S_IP;
$sendpacket = "\xff\xff\xff\xffrcon " . $SERVER_TOKEN . " getplayers";
@$connectpacket = fsockopen($server_info, $S_PORT, $errno, $errstr);
if(!$connectpacket)
echo 'serverStatus(): connect error!';
socket_set_timeout ($connectpacket, 1, 0);
fwrite ($connectpacket, $sendpacket);
$S_HOSTNAME = '';
$S_MAP = '';
$P_NAME = "";
$P_SCORE = "";
$P_PING = "";
$PLAYER_COUNT = 0;
while ($ret = fread ($connectpacket, 10000))
{
$ret = mb_strimwidth($ret, 4, strlen($ret));
if ($ret[1] != " ")
continue;
$a = $ret[0];
if ($a == "h")
$S_HOSTNAME = mb_strimwidth($ret, 2, strlen($ret));
elseif ($a == "m")
$S_MAP = mb_strimwidth($ret, 2, strlen($ret));
elseif ($a == "n" )
{
$P_NAME .= mb_strimwidth($ret, 2, strlen($ret)) . "\n";
$PLAYER_COUNT++;
}
elseif ($a == "s")
$P_SCORE .= mb_strimwidth($ret, 2, strlen($ret)) . "\n";
elseif ($a == "p")
$P_PING .= mb_strimwidth($ret, 2, strlen($ret)) . "\n";
else
echo 'serverStatus(): undefined control-symbol!';
}
fclose ($connectpacket);
/* construct your discord message */
/*
$S_HOSTNAME = 'CoD2Server';
$S_MAP = 'mp_toujane';
$P_NAME = 'Unknown Soldier\nPlayer#123\nUnnamedPlayer\nZombieBot\n';
$P_SCORE = '14\n0\n1\n13\n';
$P_PING = '109\n87\n43\n14\n';
*/
}
.gsc
G_Command(c, v)
{
return getSubStr(c, 0, v.size) == v;
}
codecallback_remoteCommand(from, command, pointerMsg)
{
commandArray = strtok(command, " ");
command = commandArray[2];
sfrom = strtok(from, ":");
ip = sfrom[0];
port = sfrom[1];
DiscordToken = "MuCN14jiSAKJTNV4UK7p";
if (commandArray[1] == DiscordToken && G_Command(command, "getplayers"))
{
thread Discord_GetPlayers(from);
return;
}
doRcon(from, pointerMsg);
}
Discord_GetPlayers(from)
{
out_printf(from, "h " + removeColors(getCvar("sv_hostname")));
mapCvar = getCvar("mapname");
map = scr\_map::getMapDescription(mapCvar);
if (!isDefined(map))
map = mapCvar;
out_printf(from, "m " + map);
players = getEntArray("player", "classname");
for (i = 0; i < players.size; i++)
{
player = players[i];
if (/* filter unlogged players, bots etc.*/)
continue;
out_printf(from, "n " + player.name);
out_printf(from, "s " + player.score);
out_printf(from, "p " + player getPing());
}
}
G_Command() - to filter some garbage, I don’t know, maybe this is a completely useless operation, but I noticed some strange behavior, so I just made insurance.
Access_Token can (should :)) differ from the rcon_password.
you can also make a system of several rcon_passwords (if you implement all the necessary functions in the .gsc) and give the admins a unique rcon_password - this will help to identify all actions with reference to their performer.
There are some problems with the transmission of some characters (special characters and Cyrillic).
you can always use only integer data for send, for example:
1. CoD2: transfer the indexes (id) of rows in the database.
and, after gets already in .PHP
2. select from DB where ID = ...
Code can be added and improved forever, specifically here I brought the most exemplary and understandable.
There can be a lot of ideas for use, the whole point is only in your imagination.
I wait to any comments, recommendations, advice on the implementation of out_printf() itself in libcod or its use in .gsc