56 public function __construct(){
59 KnownTranslationFactory::pocketmine_command_timings_description(),
60 KnownTranslationFactory::pocketmine_command_timings_usage()
62 $this->setPermission(DefaultPermissionNames::COMMAND_TIMINGS);
66 if(count($args) !== 1){
70 $mode = strtolower($args[0]);
73 if(TimingsHandler::isEnabled()){
74 $sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_alreadyEnabled());
77 TimingsHandler::setEnabled();
78 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_enable());
81 }elseif($mode ===
"off"){
82 TimingsHandler::setEnabled(
false);
83 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_disable());
87 if(!TimingsHandler::isEnabled()){
88 $sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_timingsDisabled());
93 $paste = $mode ===
"paste";
95 if($mode ===
"reset"){
96 TimingsHandler::reload();
97 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_reset());
98 }elseif($mode ===
"merged" || $mode ===
"report" || $paste){
100 $timingsPromise = TimingsHandler::requestPrintTimings();
101 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_collect());
102 $timingsPromise->onCompletion(
103 fn(array $lines) => $this->uploadReport($lines, $sender),
107 TimingsHandler::createReportFile(Path::join($sender->getServer()->getDataPath(),
"timings"))->onCompletion(
108 function(
string $timingsFile) use ($sender) :
void{
109 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsWrite($timingsFile));
111 fn() => $sender->getServer()->getLogger()->error(
"Failed to create timings report file")
125 private function uploadReport(array $lines,
CommandSender $sender) : void{
127 "browser" => $agent = $sender->getServer()->getName() .
" " . $sender->getServer()->getPocketMineVersion(),
128 "data" => implode(
"\n", $lines),
132 $host = $sender->getServer()->getConfigGroup()->getPropertyString(YmlServerProperties::TIMINGS_HOST,
"timings.pmmp.io");
134 $sender->getServer()->getAsyncPool()->submitTask(
new BulkCurlTask(
136 "https://$host?upload=true",
140 CURLOPT_HTTPHEADER => [
141 "User-Agent: $agent",
142 "Content-Type: application/x-www-form-urlencoded"
144 CURLOPT_POST =>
true,
145 CURLOPT_POSTFIELDS => http_build_query($data),
146 CURLOPT_AUTOREFERER =>
false,
147 CURLOPT_FOLLOWLOCATION =>
false
150 function(array $results) use ($sender, $host) :
void{
152 if($sender instanceof
Player && !$sender->isOnline()){
155 $result = $results[0];
156 if($result instanceof InternetException){
157 $sender->getServer()->getLogger()->logException($result);
160 $response = json_decode($result->getBody(),
true);
161 if(is_array($response) && isset($response[
"id"]) && (is_int($response[
"id"]) || is_string($response[
"id"]))){
162 $url =
"https://" . $host .
"/?id=" . $response[
"id"];
163 if(isset($response[
"access_token"]) && is_string($response[
"access_token"])){
164 $url .=
"&access_token=" . $response[
"access_token"];
166 $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.");
168 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsRead($url));
170 $sender->getServer()->getLogger()->debug(
"Invalid response from timings server (" . $result->getCode() .
"): " . $result->getBody());
171 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_pasteError());