Welcome, Guest. Please login or register.
Did you miss your activation email?
June 04, 2020, 11:24:56 am

Login with username, password and session length
Search:     Advanced search
Savage: XR is a new patch for Savage, created by the Newerth.com staff. The XR1.1 Client is out now! Download it now!
189999 Posts in 11002 Topics by 18510 Members
Latest Member: vollfrucht
* Home Forum Wiki Help Search Login Register
+  Newerth Forums
|-+  Savage XR
| |-+  Support Forum
| | |-+  Server Monitor
0 Members and 1 Guest are viewing this topic. « previous next »
Pages: [1] Go Down Print
Author Topic: Server Monitor  (Read 361 times)
Badyyy
Newerth Donator
Newbie
****
Posts: 9


View Profile
« on: March 06, 2020, 07:20:41 am »

Hi there. I wanted to create a gameserver monitor on my website. php script. My question. Is there a query port to listen? There is no response via the set server port 11235.
Logged
Crashday
XR Coder
Sr. Member
***
Posts: 357


soundcloud.com/bernhardfritz


View Profile
« Reply #1 on: March 07, 2020, 05:19:35 pm »

Hi Badyyy,

you could either ask one of our Newerth server admins (maybe Groentjuh?) to share their implementation of the serverlist_impl.php, or simply parse the result of your server listed on newerth.com, e.g. for the Community Server (NL) this would be https://www.newerth.com/serverlist_impl.php?id=serverlist&details=31.220.42.92:11235

Another way would be to reverse engineer how the the master server communicates with your server. The master server has been written by valli and is open source on GitHub: https://github.com/valliman/savage-xr-master-server

Or you look into how the Savage Remote Controller Pro has been implemented which can also be found on GitHub: https://github.com/valliman/Savage-Server-Remote
Logged

Groentjuh
Newerth Serveradmin, German Mirror and Webdeveloper
Administrator
Super Hero Member
*****
Posts: 1376


View Profile WWW
« Reply #2 on: March 07, 2020, 09:52:45 pm »

Another way would be to reverse engineer how the the master server communicates with your server. The master server has been written by valli and is open source on GitHub: https://github.com/valliman/savage-xr-master-server
Wrong protocol. That's implementing the master server, which receives heartbeats from savage servers and generates a .dat file for savage clients (and webbased serverlists) to download and use to contact serverlists.
It don't do Savage server firewall tests or request queries like the original master server list, so it will not contain the implementations of the needed protocol.

Or you look into how the Savage Remote Controller Pro has been implemented which can also be found on GitHub: https://github.com/valliman/Savage-Server-Remote
The uses a TCP remote admin protocol. Technically you can do some of the webbased serverlist with that, but it will be way more difficult to do.

So now how is it actually done:

Let's start with master server to Savage client:
Step one: Download and read serverlist from the master server (optional in case you hard-code your server IP and port into your script)
Download http://masterserver.newerth.com/gamelist_full.dat
This file contains a list of IP addresses and ports of all savage servers. The first 5 characters should be in hexadecimal values: 0x7E, 0x41, 0x03, 0x00, 0x00. This is just a header!
Each group of 6 characters after that is an IP and port of a Savage server. The first four characters are binary representation of an IPv4 address. The port is formed by taking the decimal value of character #5 plus the decimal value of character #6 multiplied by 256. In code: ( decimal value of character #5 + (decimal value of character #6 * 256) )

That should give you the list of all savage servers in the master serverlist!

Savage client to Savage server:
Step two: Query Savage server
Now that you have the IPs and ports, you must contact each savage server.
Using UDP: sent the hexadecimal characters: 0x9E, 0x4C, 0x23, 0x00, 0x00, 0xFF, 0xFF, 0xCE, 0xF2, 0x3B, 0x18, 0x80 to the server and if you did the well, the savage server will return you its current status. Given the nature of UDP, you might want to retry sending once or twice the packet if no response is received within a reasonable timeout. (999ms should be plenty, extra credits if you maintain statistics of response times to lower this time-out and speed up processing)

Step three: Process Savage server response
The response you receive can be split with the hexadecimal character 0xFF. This splits the response into different keyvalue pair. The key and values can be split using the hexadecimal character 0xFE.

Step four: Process the "player"-field.
Each playername is indeed on a different line. But not all lines are player names. For example:
Code:
^900Team 1 (human)
and
Code:
^900Team 2 (beast)
and
Code:
^900Spectators
are lines in the player field, but not actual players.

In the webbased serverlist I used 2 regex (Please note, these are PCRE, not javascript regex. You might have to adjust them):
Code:
/^(\^900Team|Team) (\d) \((.+)\)(:|)/
Code:
/^(\^900|)Spectators(:|)/

These 2 will detect those lines. If the line is followed by the lines:
"--empty--", "---empty---" or " --empty--" that team is empty.
If it is neither all of those special situations, then it is a player name.

Step five: Further process player names.
Of course those players belong to the previously found team and race.

In the player name you can still do some further processing:
Detect referee tag "^y[R]^w".
Detect officer tag "^b[O]^w".
Detect AO officer tag "^050[AO]^w"
Detect commander tag "^g[C]^w"
And if you want legacy support: Detect the old commander tag "(Commander)" at the end of the player name, but ONLY on servers which do not sent the "ver" value or the "ver" value starts with "EX2" (and ofcourse only if none of the above tags are present in any names)

Lastly you can detect using regex /\^clan (\d+)\^/ to fetch clan id of the player and get the clan icon for them using that.

There you go! All you need... You just need to do some programming.
« Last Edit: March 07, 2020, 09:55:44 pm by Groentjuh » Logged


Before adding any of my IMs, ask yourself: Can I ask it in a PM?
Before sending me a PM with questions, Search the forums!
Wanna be ref? Post on my Server Forum
Trigardon
Forum Administrator
Legendary Member
****
Posts: 4825


Demonic Monster


View Profile WWW
« Reply #3 on: March 08, 2020, 01:21:24 am »

Stickied.
Logged

Badyyy
Newerth Donator
Newbie
****
Posts: 9


View Profile
« Reply #4 on: March 08, 2020, 06:14:58 am »

wow thank you Groentjuh. Then I'll try. Grin
Logged
Badyyy
Newerth Donator
Newbie
****
Posts: 9


View Profile
« Reply #5 on: March 09, 2020, 12:49:17 pm »

I did my best but I'm not good at php, I learned everything myself.
I have the script ready but don't know how to split the array and the "map.jpg" is unfortunately not loaded either
If it doesn't make too much of a mess, could you add the part?
Of course everyone is free to use the code, change it, etc.

Code:

<?php
error_reporting(0);
header("Refresh:10");
# Configuration:
$ip = '92.42.45.50';
$queryport = 11236 ;
####################################################################
$socket = @fsockopen("udp://".$ip, $queryport, $errno, $errstr);

stream_set_timeout($socket, 1);
stream_set_blocking($socket, TRUE);
fwrite($socket, "\x9E\x4C\x23\x00\x00\xFF\xFF\xCE\xF2\x3B\x18\x80");
$response = fread($socket, 4096);
@fclose($socket);

$packet = explode("\xFF", substr($response,1));
$server = array();

$server['name'] = $packet[1];
$server['map'] = $packet[2];
$server['status'] = $packet[0];
$server['version'] = $packet[7];
$server['players'] = $packet[3];
$server['playersmax'] = $packet[5];
$server['password'] = $packet[10];
$file="img/maps/$server[map].jpg";

if ($server['status']) {
   $status="<span style='color:green;'>Server Online</span>";
} else {
   $status="<span style='color:red;'>Server Offline</span>";
}

if (file_exists($file)) {
    $img="$file";
} else {
    $img="img/maps/default.jpg";
}

if ($server['password']==1) {
   $password="Yes";
} else {
   $password="No";
}

?>

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Savage XR Server Status</title>
      <link href="style.css" type="text/css" rel="stylesheet"/>
        <meta name="robots" content="noindex,nofollow"/>
      <meta charset="UTF-8"/>
    </head>
   
    <body>
        <div class="main-box">
            <header><h2>Simple Monitor Test</h2></header>
            <main>
                <div class="flex">
                    <div class="flex-1">
                        <div>
                            <img src="<?php echo $img ?>"/>
                            <h4><?php echo $server['map']; ?></h4>
                        </div>
                    </div>
                    <div class="flex-2">
                        <h3>Status: <?php echo $status ?></h3>
                        <h3>Name: <?php echo $server['name']; ?></h3>
                        <br/>
                        <h3>Version: <?php echo $server['version']; ?></h3>
                        <h3>Map: <?php echo $server['map']; ?></h3>
                        <h3>Players: <?php echo $server['players']; ?>/<?php echo $server['playersmax']; ?></h3>
                        <br/>                        
                        <h3>Password: <?php echo $server['password']; ?></h3>
                  <h3>Password: <?php echo $password; ?></h3>
                    </div>
                </div>
            </br>
            </main>
            
         <footer>
            <h2>Simple Monitor Test</h2>
         </footer>
        </div>
    </body>
</html>

« Last Edit: March 13, 2020, 11:01:09 pm by Badyyy » Logged
Badyyy
Newerth Donator
Newbie
****
Posts: 9


View Profile
« Reply #6 on: March 13, 2020, 11:03:34 pm »

After many hours of anger Angry Evil Ticked Off You Ugly & Stupid  I found a way. i think it's not the best but it works  Cheesy

code can thus be built into the website and adapted

<?php
error_reporting(0);
header("Refresh:10");
# Configuration:
$ip = '92.42.45.50';
$queryport = 11236 ;
####################################################################
$socket = @fsockopen("udp://".$ip, $queryport, $errno, $errstr);

stream_set_timeout($socket, 1);
stream_set_blocking($socket, TRUE);
fwrite($socket, "\x9E\x4C\x23\x00\x00\xFF\xFF\xCE\xF2\x3B\x18\x80");
$response = fread($socket, 4096);
@fclose($socket);

$packet = explode("\xFF", substr($response,1));
$server = array();
$map = array ($packet[2]);
$version = array ($packet[7]);
$player = array ($packet[3]);
$playermax = array ($packet[5]);

foreach ($map as $val )
{
    $mappack = explode ("\xFE" , substr( $val, 1));
   $map = array();
}
foreach ($version as $val1)
{
   $verpack = explode ("\xFE" , substr( $val1, 1));
   $version=array();
}
foreach ($player as $val2)
{
   $playerpack = explode ("\xFE" , substr( $val2, 1));
   $player=array();
}
foreach ($playermax as $val3)
{
   $maxpack = explode ("\xFE" , substr( $val3, 1));
   $playermax=array();
}
   




#$server['name'] = $packet[1];
$map['map'] = $mappack[1];
$server['status'] = $packet[0];
$version['version'] = $verpack[1];
$player['players'] = $playerpack[1];
$playermax['playersmax'] = $maxpack[1];
$server['password'] = $packet[10];
$file="img/maps/$map[map].jpg";

if ($server['status']) {
   $status="<span style='color:green;'>Server Online</span>";
} else {
   $status="<span style='color:red;'>Server Offline</span>";
}

if (file_exists($file)) {
    $img="$file";
} else {
    $img="img/maps/default.jpg";
}

if ($server['password']==1) {
   $password="Yes";
} else {
   $password="No";
}

?>

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Savage Server Status</title>
      <link href="style.css" type="text/css" rel="stylesheet"/>
        <meta name="robots" content="noindex,nofollow"/>
      <meta charset="UTF-8"/>
    </head>
   
    <body>
        <div class="main-box">
            <header><h2>SavageXr Server Status</h2></header>
            <main>
                <div class="flex">
                    <div class="flex-1">
                        <div>
                            <img src="<?php echo $img ?>"/>
                            <h4><?php echo $map['map']; ?></h4>
                        </div>
                    </div>
                    <div class="flex-2">
                        <h3>Status: <?php echo $status ?></h3>
                  <br/>
<!--                    <h3>Name: <?php echo $server['name']; ?></h3> -->
                  <h3>Name: SaVaGe Mods | Badyyy.de</h3>
                        <h3>Mode: <?php echo $version['version']; ?></h3>
                        <h3>Map: <?php echo $map['map']; ?></h3>
                        <h3>Players: <?php echo $player['players']; ?>/<?php echo $playermax['playersmax']; ?></h3>                                             
                  <h3>Password: <?php echo $password; ?></h3>
                    </div>
                </div>
            </br>
            </main>
           
         <footer>
            <h2>SavageXr.com | Newerth.com</h2>
         </footer>
        </div>
    </body>
</html>
Logged
Pages: [1] Go Up Print 
« previous next »
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2007, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.027 seconds with 20 queries.