63    public function __construct(){
 
   66            KnownTranslationFactory::pocketmine_command_timings_description(),
 
   67            KnownTranslationFactory::pocketmine_command_timings_usage()
 
   69        $this->setPermission(DefaultPermissionNames::COMMAND_TIMINGS);
 
   73        if(count($args) !== 1){
 
   77        $mode = strtolower($args[0]);
 
   80            if(TimingsHandler::isEnabled()){
 
   81                $sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_alreadyEnabled());
 
   84            TimingsHandler::setEnabled();
 
   85            Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_enable());
 
   88        }elseif($mode === 
"off"){
 
   89            TimingsHandler::setEnabled(
false);
 
   90            Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_disable());
 
   94        if(!TimingsHandler::isEnabled()){
 
   95            $sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_timingsDisabled());
 
  100        $paste = $mode === 
"paste";
 
  102        if($mode === 
"reset"){
 
  103            TimingsHandler::reload();
 
  104            Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_reset());
 
  105        }elseif($mode === 
"merged" || $mode === 
"report" || $paste){
 
  106            $timingsPromise = TimingsHandler::requestPrintTimings();
 
  107            Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_collect());
 
  108            $timingsPromise->onCompletion(
 
  109                fn(array $lines) => $paste ? $this->uploadReport($lines, $sender) : $this->createReportFile($lines, $sender),
 
 
  123    private function createReportFile(array $lines, 
CommandSender $sender) : void{
 
  125        $timingFolder = Path::join($sender->getServer()->getDataPath(), 
"timings");
 
  127        if(!file_exists($timingFolder)){
 
  128            mkdir($timingFolder, 0777);
 
  130        $timings = Path::join($timingFolder, 
"timings.txt");
 
  131        while(file_exists($timings)){
 
  132            $timings = Path::join($timingFolder, 
"timings" . (++$index) . 
".txt");
 
  136        foreach($lines as $line){
 
  137            fwrite($fileTimings, $line . PHP_EOL);
 
  139        fclose($fileTimings);
 
  141        Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsWrite($timings));
 
  148    private function uploadReport(array $lines, CommandSender $sender) : void{
 
  150            "browser" => $agent = $sender->getServer()->getName() . 
" " . $sender->getServer()->getPocketMineVersion(),
 
  151            "data" => implode(
"\n", $lines),
 
  155        $host = $sender->getServer()->getConfigGroup()->getPropertyString(YmlServerProperties::TIMINGS_HOST, 
"timings.pmmp.io");
 
  157        $sender->getServer()->getAsyncPool()->submitTask(
new BulkCurlTask(
 
  158            [
new BulkCurlTaskOperation(
 
  159                "https://$host?upload=true",
 
  163                    CURLOPT_HTTPHEADER => [
 
  164                        "User-Agent: $agent",
 
  165                        "Content-Type: application/x-www-form-urlencoded" 
  167                    CURLOPT_POST => 
true,
 
  168                    CURLOPT_POSTFIELDS => http_build_query($data),
 
  169                    CURLOPT_AUTOREFERER => 
false,
 
  170                    CURLOPT_FOLLOWLOCATION => 
false 
  173            function(array $results) use ($sender, $host) : 
void{
 
  175                if($sender instanceof Player && !$sender->isOnline()){ 
 
  178                $result = $results[0];
 
  179                if($result instanceof InternetException){
 
  180                    $sender->getServer()->getLogger()->logException($result);
 
  183                $response = json_decode($result->getBody(), 
true);
 
  184                if(is_array($response) && isset($response[
"id"]) && (is_int($response[
"id"]) || is_string($response[
"id"]))){
 
  185                    $url = 
"https://" . $host . 
"/?id=" . $response[
"id"];
 
  186                    if(isset($response[
"access_token"]) && is_string($response[
"access_token"])){
 
  187                        $url .= 
"&access_token=" . $response[
"access_token"];
 
  189                        $sender->getServer()->getLogger()->warning(
"Your chosen timings host does not support private reports. Anyone will be able to see your report if they guess the ID.");
 
  191                    Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsRead($url));
 
  193                    $sender->getServer()->getLogger()->debug(
"Invalid response from timings server (" . $result->getCode() . 
"): " . $result->getBody());
 
  194                    Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_pasteError());