22declare(strict_types=1);
24namespace pocketmine\command\defaults;
39use Symfony\Component\Filesystem\Path;
42use
function file_exists;
46use
function http_build_query;
48use
function json_decode;
50use
function stream_get_contents;
51use
function strtolower;
52use
const CURLOPT_AUTOREFERER;
53use
const CURLOPT_FOLLOWLOCATION;
54use
const CURLOPT_HTTPHEADER;
55use
const CURLOPT_POST;
56use
const CURLOPT_POSTFIELDS;
61 public function __construct(){
64 KnownTranslationFactory::pocketmine_command_timings_description(),
65 KnownTranslationFactory::pocketmine_command_timings_usage()
67 $this->setPermission(DefaultPermissionNames::COMMAND_TIMINGS);
71 if(count($args) !== 1){
75 $mode = strtolower($args[0]);
78 if(TimingsHandler::isEnabled()){
79 $sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_alreadyEnabled());
82 TimingsHandler::setEnabled();
83 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_enable());
86 }elseif($mode ===
"off"){
87 TimingsHandler::setEnabled(
false);
88 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_disable());
92 if(!TimingsHandler::isEnabled()){
93 $sender->sendMessage(KnownTranslationFactory::pocketmine_command_timings_timingsDisabled());
98 $paste = $mode ===
"paste";
100 if($mode ===
"reset"){
101 TimingsHandler::reload();
102 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_reset());
103 }elseif($mode ===
"merged" || $mode ===
"report" || $paste){
106 $fileTimings =
Utils::assumeNotFalse(fopen(
"php://temp",
"r+b"),
"Opening php://temp should never fail");
109 $timingFolder = Path::join($sender->getServer()->getDataPath(),
"timings");
111 if(!file_exists($timingFolder)){
112 mkdir($timingFolder, 0777);
114 $timings = Path::join($timingFolder,
"timings.txt");
115 while(file_exists($timings)){
116 $timings = Path::join($timingFolder,
"timings" . (++$index) .
".txt");
119 $fileTimings = fopen($timings,
"a+b");
122 foreach($lines as $line){
123 fwrite($fileTimings, $line . PHP_EOL);
127 fseek($fileTimings, 0);
129 "browser" => $agent = $sender->getServer()->getName() .
" " . $sender->getServer()->getPocketMineVersion(),
130 "data" => $content = stream_get_contents($fileTimings)
132 fclose($fileTimings);
134 $host = $sender->getServer()->getConfigGroup()->getPropertyString(YmlServerProperties::TIMINGS_HOST,
"timings.pmmp.io");
136 $sender->getServer()->getAsyncPool()->submitTask(
new BulkCurlTask(
138 "https://$host?upload=true",
142 CURLOPT_HTTPHEADER => [
143 "User-Agent: $agent",
144 "Content-Type: application/x-www-form-urlencoded"
146 CURLOPT_POST =>
true,
147 CURLOPT_POSTFIELDS => http_build_query($data),
148 CURLOPT_AUTOREFERER =>
false,
149 CURLOPT_FOLLOWLOCATION =>
false
152 function(array $results) use ($sender, $host) :
void{
154 if($sender instanceof
Player && !$sender->isOnline()){
157 $result = $results[0];
159 $sender->getServer()->getLogger()->logException($result);
162 $response = json_decode($result->getBody(),
true);
163 if(is_array($response) && isset($response[
"id"])){
164 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsRead(
165 "https://" . $host .
"/?id=" . $response[
"id"]));
167 $sender->getServer()->getLogger()->debug(
"Invalid response from timings server (" . $result->getCode() .
"): " . $result->getBody());
168 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_pasteError());
173 fclose($fileTimings);
174 Command::broadcastCommandMessage($sender, KnownTranslationFactory::pocketmine_command_timings_timingsWrite($timings));
execute(CommandSender $sender, string $commandLabel, array $args)
static assumeNotFalse(mixed $value, \Closure|string $context="This should never be false")