I have a websocket application that I am building a game on, built on Ratchet which uses the React event loop. At the start of this script, I have already figured out how to implement a periodictimer, to send a pulse to the game every second, and then execute ticks and combat rounds. This works great.
However, I have recently realized that I will also need to add the ability to "lag" clients, or pause execution in a function. For example, if a player is stunned, or I want an NPC to wait for 1.5 seconds before replying to a trigger for a more "realistic" conversational feel.
Is this functionality built into the react library, or is it something that I am going to have to achieve through other means? After some research, it looks like maybe pthreads is what I may be looking for, see this question/answer: How can one use multi threading in PHP applications
To be more clear with what I am trying to achieve, take this code as an example:
function onSay($string)
{
global $world;
$trigger_words = array(
'hi',
'hello',
'greetings'
);
$triggered = false;
foreach($trigger_words as $trigger_word)
{
if(stristr($string, $trigger_word))
{
$triggered = true;
}
}
if($triggered)
{
foreach($world->players as $player)
{
if($player->pData->in_room === $this->mobile->in_room)
{
sleep(1);
$this->toChar($player, $this->mobile->short . " says '`kOh, hello!``'");
}
}
}
}
Obviously, this doesn't work, as the sleep(1) function will halt the entire server process.
Any insight would be greatly appreciated. Thank you!
Update: My server script:
require 'vendor/autoload.php';
require 'src/autoload.php';
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\Socket\Server as Reactor;
use React\EventLoop\Factory as LoopFactory;;
$world = new WorldInterface();
class Server implements MessageComponentInterface
{
public function __construct(React\EventLoop\LoopInterface $loop)
{
$update = new Update();
$update->doTick();
$loop->addPeriodicTimer(1, function()
{
$this->doBeat();
});
}
public function onOpen(ConnectionInterface $ch)
{
global $world;
$world->connecting[$ch->resourceId] = $ch;
$ch->CONN_STATE = "GET_NAME";
$ch->pData = new stdClass();
$ch->send("Who dares storm our wayward path? ");
}
public function onMessage(ConnectionInterface $ch, $args)
{
if($ch->CONN_STATE == "CONNECTED")
{
$ch->send("> " . $args . "\n");
$interpreter = new Interpreter($ch);
$interpreter->interpret($args);
}
else
{
$ch->send($args);
$login = new Login($ch, $args);
$login->start();
}
}
public function onClose(ConnectionInterface $ch)
{
global $world;
if(isset($ch->pData->name))
{
if(isset($world->players[$ch->pData->name]))
{
echo "Player {$ch->pData->name} has disconnected\n";
unset($world->players->{$ch->pData->name});
}
}
if(isset($world->connecting->{$ch->resourceId}))
{
echo "Connection " . $ch->resourceId . " has disconnected.";
unset($world->connecting->{$ch->resourceId});
}
}
public function onError(ConnectionInterface $conn, \Exception $e)
{
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
public function doBeat()
{
global $world;
++$world->beats;
foreach($world->process_queue as $trigger_beat => $process_array)
{
// if the beat # that the function should fire on is less than,
// or equal to the current beat, fire the function.
if($trigger_beat <= $world->beats)
{
foreach($process_array as $process)
{
$class = new $process->class();
call_user_func_array(array($class, $process->function), $process->params);
}
// remove it from the queue
unset($world->process_queue[$trigger_beat]);
}
// else, the beat # the function should fire on is greater than the current beat,
// so break out of the loop.
else
{
break;
}
}
if($world->beats % 2 === 0)
{
$update = new Update();
$update->doBeat();
}
}
}
$loop = LoopFactory::create();
$socket = new Reactor($loop);
$socket->listen(9000, 'localhost');
$server = new IoServer(new HttpServer(new WsServer(new Server($loop))), $socket, $loop);
$server->run();
$this->loop->addTimer(1, function() use {$player} {$this->toChar($player, $this->mobile->short . " says '
kOh, hello!``'");})` – Horney$loop
must exist at this point, as socket requires it in the constructor. The My server script part is a mess tbh. – Horney