56 public function __construct(
string $namespace,
string $name){
60 KnownTranslationFactory::pocketmine_command_timings_description(),
61 KnownTranslationFactory::pocketmine_command_timings_usage()
63 $this->setPermission(DefaultPermissionNames::COMMAND_TIMINGS);
67 if(count($args) !== 1){
71 $mode = strtolower($args[0]);
74 if(TimingsHandler::isEnabled()){
75 $sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_alreadyEnabled());
78 TimingsHandler::setEnabled();
79 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_enable());
82 }elseif($mode ===
"off"){
83 TimingsHandler::setEnabled(
false);
84 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_disable());
88 if(!TimingsHandler::isEnabled()){
89 $sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_timingsDisabled());
94 $paste = $mode ===
"paste";
96 if($mode ===
"reset"){
97 TimingsHandler::reload();
98 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_reset());
99 }elseif($mode ===
"merged" || $mode ===
"report" || $paste){
101 $timingsPromise = TimingsHandler::requestPrintTimings();
102 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_collect());
103 $timingsPromise->onCompletion(
104 fn(array $lines) => $this->uploadReport($lines, $sender),
108 TimingsHandler::createReportFile(Path::join($sender->getServer()->getDataPath(),
"timings"))->onCompletion(
109 function(
string $timingsFile) use ($sender) :
void{
110 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsWrite($timingsFile));
112 fn() => $sender->getServer()->getLogger()->error(
"Failed to create timings report file")
126 private function uploadReport(array $lines,
CommandSender $sender) : void{
128 "browser" => $agent = $sender->getServer()->
getName() .
" " . $sender->getServer()->getPocketMineVersion(),
129 "data" => implode(
"\n", $lines),
133 $host = $sender->getServer()->getConfigGroup()->getPropertyString(YmlServerProperties::TIMINGS_HOST,
"timings.pmmp.io");
135 $sender->getServer()->getAsyncPool()->submitTask(
new BulkCurlTask(
137 "https://$host?upload=true",
141 CURLOPT_HTTPHEADER => [
142 "User-Agent: $agent",
143 "Content-Type: application/x-www-form-urlencoded"
145 CURLOPT_POST =>
true,
146 CURLOPT_POSTFIELDS => http_build_query($data),
147 CURLOPT_AUTOREFERER =>
false,
148 CURLOPT_FOLLOWLOCATION =>
false
151 function(array $results) use ($sender, $host) :
void{
153 if($sender instanceof
Player && !$sender->isOnline()){
156 $result = $results[0];
157 if($result instanceof InternetException){
158 $sender->getServer()->getLogger()->logException($result);
161 $response = json_decode($result->getBody(),
true);
162 if(is_array($response) && isset($response[
"id"]) && (is_int($response[
"id"]) || is_string($response[
"id"]))){
163 $url =
"https://" . $host .
"/?id=" . $response[
"id"];
164 if(isset($response[
"access_token"]) && is_string($response[
"access_token"])){
165 $url .=
"&access_token=" . $response[
"access_token"];
167 $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.");
169 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsRead($url));
171 $sender->getServer()->getLogger()->debug(
"Invalid response from timings server (" . $result->getCode() .
"): " . $result->getBody());
172 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_pasteError());