Closed steffalon closed 6 years ago
Thank you very much, this looks great. 👍 The only thing is, that this function should not echo something out. This output is unwanted for the most devs, because ARC runs in the background of their main program. Another “problem” is your code-style, this library complies with the PSR-2 CS in order to be readable for all devs. And switching the CS multiple times a class is not something preferable 😉 Cheers!
I just remembered, there’s a tool helping you with the style guide: https://github.com/FriendsOfPHP/PHP-CS-Fixer
I have added PSR-2 style and made all echo's only possible via debug mode.
@schaeferfelix I think it is all done. This method works good and also can work together with other methods for example say or sayglobal if you remove this: $this->disconnect(); // Runs if process is done.
. So no reconnects are needed.
@schaeferfelix I have found a solution. Now it is even more efficient. It can handle other methods without reconnecting with an extra boolean added called $closeCon
.
For example:
$rcon->getSocketStream(1, false, true);
$rcon->command("say -1 test1");
$rcon->getSocketStream(1, false, true);
$rcon->command("say -1 test2");
$rcon->getSocketStream(1, false, true);
$rcon->command("say -1 test3");
$rcon->getSocketStream(1, false, true);
$rcon->sayGlobal("And I didn't even reconnect!");
$rcon->getSocketStream(-1, true, true); // Now keep going without sending any commands.
Very cool! 👍
What do you think about adding a callback closure to the function, which gets called whenever a package is received? Also Taylor Otwell from Laravel lately has stated in his newsletter, that many boolean arguments for a function should be avoided, in order to keep it user friendly. So instead multiple methods should be used.
So we could do some renaming for the public functions like socketLoop(int $loop, closure $callback)
and socketLoopClose(int $loop, closure $callback)
.
Please let me know what you think and if you can implement it, I am currently on vacation and have limited possibilities to work 😄
Hey @schaeferfelix, is this what you were looking for as 2 seperate functions?
private $end = 0; // required to remember the sequence.
/**
* Get socket and continue streaming and disconnect after looping.
*
* @author steffalon (https://github.com/steffalon)
* @link https://github.com/schaeferfelix/arma-rcon-class-php/issues/30 issue part 1
* @link https://github.com/schaeferfelix/arma-rcon-class-php/issues/31 issue part 2
*
* @param integer $loop Number of loops through this funtion. By default, (-1) for no ending.
* @param boolean $debug Useful boolean for debugging. By default, (false).
*
* @return boolean
*/
public function socketLoopClose($loop = -1, $debug = false)
{
if ($this->end !== null) {
$loop = $this->end + $loop;
}
while ($this->end !== $loop) {
$msg = fread($this->socket, 9000);
if ($debug) {
echo preg_replace("/\r|\n/", "", substr($msg, 9)).PHP_EOL;
}
$timeout = stream_get_meta_data($this->socket);
if ($timeout['timed_out']) {
$this->keepAlive($debug);
} else {
$this->end = $this->readPackage($msg);
}
}
$this->end = 0;
$this->disconnect();
return true; // Completed
}
/**
* Get socket and continue streaming and don't disconnect after looping.
*
* @author steffalon (https://github.com/steffalon)
* @link https://github.com/schaeferfelix/arma-rcon-class-php/issues/30 issue part 1
* @link https://github.com/schaeferfelix/arma-rcon-class-php/issues/31 issue part 2
*
* @param integer $loop Number of loops through this funtion. By default, (-1) for no ending.
* @param boolean $debug Useful boolean for debugging. By default, (false).
*
* @return boolean
*/
public function socketLoop($loop = -1, $debug = false)
{
if ($this->end !== null) {
$loop = $this->end + $loop;
}
while ($this->end !== $loop) {
$msg = fread($this->socket, 9000);
if ($debug) {
echo preg_replace("/\r|\n/", "", substr($msg, 9)).PHP_EOL;
}
$timeout = stream_get_meta_data($this->socket);
if ($timeout['timed_out']) {
$this->keepAlive($debug);
} else {
$this->end = $this->readPackage($msg);
}
}
return true; // Completed
}
/**
* Reads what kind of package it is.
*
* @author steffalon (https://github.com/steffalon)
* @link https://github.com/schaeferfelix/arma-rcon-class-php/issues/30 issue part 1
* @link https://github.com/schaeferfelix/arma-rcon-class-php/issues/31 issue part 2
*
* @param string $msg message received from BE with unreadable header.
*
* @throws \Exception by invalid BERCon login details.
*
* @return integer
*/
private function readPackage($msg)
{
$responseCode = unpack('H*', $msg); // Make message usefull for battleye packet by unpacking it to hexbyte.
$responseCode = str_split(substr($responseCode[1], 12), 2); // Get important hexbytes.
switch ($responseCode[1]) { // See https://www.battleye.com/downloads/BERConProtocol.txt for packet info.
case "00": // Login WILL NOT BE USED IN THIS LOOP!
if ($responseCode[2] == "01") { // Login successful.
if ($debug) {
echo "Accepted BERCon login.".PHP_EOL;
}
} else { // Otherwise $responseCode[2] == "0x00" (Login failed)
if ($debug) {
echo "Invalid BERCon login details. This process is getting stopped.".PHP_EOL;
}
throw new \Exception('Invalid BERCon login details. This process is getting stopped!');
}
break;
case "01": // Send commands by this client.
if (count($responseCode) == 3) {
break;
}
if ($responseCode[3] !== "00") { // This package is small.
if ($debug) {
echo "This is a small package.".PHP_EOL;
}
} else {
if ($debug) { //This package is multi-packet.
echo "Multi-packet.".PHP_EOL;
}
// if (debug) var_dump($responseCode); //Useful developer information.
// if ($responseCode[5] == "00") {
// $getAmount = $responseCode[4];
// if (debug) var_dump($getAmount);
// }
}
break;
case "02": // Acknowledge as client.
return $this->acknowledge($this->end, $debug);
break;
}
}
What do you think about adding a callback closure to the function, which gets called whenever a package is received?
I think it is better to build a private function for that.
Yep, a private functions on which the public functions wrap around would be smart. But don’t forget the closure, which gets called with the message as payload $callback($msg)
.
Cheers! Also happy new year to all contributors 🎉
Hi
To clean stuff up i think the $debug flag should be global and be set in the $options array. this give lesser arguments and the possibility for other to use debug if they come up with a new function.
Also the login part of the stream, is it necessary or can't we use the existing connect function ? (just asking havet, teste the code)
@nerdalertdk
Hi
To clean stuff up i think the $debug flag should be global and be set in the $options array. this give lesser arguments and the possibility for other to use debug if they come up with a new function.
Also the login part of the stream, is it necessary or can't we use the existing connect function ? (just asking havet, teste the code)
I agree about the $debug
boolean being set in $option array. But about the login part, I kept that in code because maybe it could be very useful for some developers. Also it will go into "00" if socketLoopClose() got called and is done looping so the user is disconnected and have to be re authenticate.
@nerdalertdk @schaeferfelix I have updated it but doesn't contain a closure yet. But I haven't work with closures alot so I have to find out how it works.
@steffalon since devs "can't/should" change the ARC.php file, the login and "commands by this client" don't make since including.
What you could do was make an readPackageRaw function that just returns the $responseCode that why people can code what the need them self's
@nerdalertdk like this?
/**
* Reads what kind of package it is.
*
* @author steffalon (https://github.com/steffalon)
*
* @param string $msg message received from BE with unreadable header.
*
* @throws \Exception by invalid BERCon login details.
*
* @return integer by package status.
* @return boolean by login status.
*/
public function readPackageRaw($msg)
{
$responseCode = unpack('H*', $msg); // Make message usefull for battleye packet by unpacking it to hexbyte.
$responseCode = str_split(substr($responseCode[1], 12), 2); // Get important hexbytes.
switch ($responseCode[1]) { // See https://www.battleye.com/downloads/BERConProtocol.txt for packet info.
case "00": // Login
if ($responseCode[2] == "01") { // Login successful.
if ($this->options['debug']) {
echo "Accepted BERCon login.".PHP_EOL;
}
return true; // Login accepted
} else { // Otherwise $responseCode[2] == "0x00" (Login failed)
throw new \Exception('Invalid BERCon login details!');
return false;
}
break;
case "01": // Command got send.
if (count($responseCode) == 3) {
break;
}
if ($responseCode[3] !== "00") { // This package is small.
if ($this->options['debug']) {
echo "This is a small package.".PHP_EOL;
}
} else {
if ($this->options['debug']) { // This package is multi-packet.
echo "Multi-packet.".PHP_EOL;
}
}
return "01";
break;
case "02": // Acknowledge request
return "02";
break;
}
}
Hi,
No more like this. that way we can use it the way we want For me ARC is a low level library, it should only do the minimum work. the rest is op for you and what you need for your site.
public function readPackageRaw($msg)
{
$responseCode = unpack('H*', $msg); // Make message usefull for battleye packet by unpacking it to hexbyte.
$responseCode = str_split(substr($responseCode[1], 12), 2); // Get important hexbytes.
return $responseCode;
}
Alright, it is added to the code. Also I have updated the README.md for that function.
Issue #30 #31 fixed
This allows users to listen to a constant socket stream. It also allow users to set amount of streaming loops or debug mode when making changes to the code. Switch case "00" isn't getting used but I decided to keep it there for developers who want to make some changes in ARC script.