mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-08-30 23:11:06 +00:00
Merge branch 'next-minor'
# Conflicts: # resources/vanilla # src/plugin/PluginBase.php # src/plugin/PluginDescription.php # src/pocketmine/Player.php # src/pocketmine/network/rcon/RCON.php # src/pocketmine/network/rcon/RCONInstance.php # src/pocketmine/scheduler/AsyncTask.php # src/pocketmine/tile/Spawnable.php # src/scheduler/AsyncPool.php # src/utils/Config.php # src/utils/Timezone.php # src/utils/UUID.php # src/utils/Utils.php # src/world/format/io/region/RegionLoader.php
This commit is contained in:
commit
163c3855eb
@ -691,8 +691,8 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener,
|
|||||||
/**
|
/**
|
||||||
* Resets the player's cooldown time for the given item back to the maximum.
|
* Resets the player's cooldown time for the given item back to the maximum.
|
||||||
*/
|
*/
|
||||||
public function resetItemCooldown(Item $item) : void{
|
public function resetItemCooldown(Item $item, ?int $ticks = null) : void{
|
||||||
$ticks = $item->getCooldownTicks();
|
$ticks = $ticks ?? $item->getCooldownTicks();
|
||||||
if($ticks > 0){
|
if($ticks > 0){
|
||||||
$this->usedItemsCooldown[$item->getId()] = $this->server->getTick() + $ticks;
|
$this->usedItemsCooldown[$item->getId()] = $this->server->getTick() + $ticks;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\plugin;
|
namespace pocketmine\plugin;
|
||||||
|
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use function file_exists;
|
use function file_exists;
|
||||||
use function fopen;
|
use function fopen;
|
||||||
use function is_dir;
|
use function is_dir;
|
||||||
@ -53,8 +54,10 @@ class DiskResourceProvider implements ResourceProvider{
|
|||||||
*/
|
*/
|
||||||
public function getResource(string $filename){
|
public function getResource(string $filename){
|
||||||
$filename = rtrim(str_replace("\\", "/", $filename), "/");
|
$filename = rtrim(str_replace("\\", "/", $filename), "/");
|
||||||
if(file_exists($this->file . "/" . $filename)){
|
if(file_exists($this->file . "resources/" . $filename)){
|
||||||
return fopen($this->file . "/" . $filename, "rb");
|
$resource = fopen($this->file . "resources/" . $filename, "rb");
|
||||||
|
if($resource === false) throw new AssumptionFailedError("fopen() should not fail on a file which exists");
|
||||||
|
return $resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -30,6 +30,7 @@ use pocketmine\command\PluginCommand;
|
|||||||
use pocketmine\command\PluginIdentifiableCommand;
|
use pocketmine\command\PluginIdentifiableCommand;
|
||||||
use pocketmine\scheduler\TaskScheduler;
|
use pocketmine\scheduler\TaskScheduler;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use pocketmine\utils\Config;
|
use pocketmine\utils\Config;
|
||||||
use function count;
|
use function count;
|
||||||
use function dirname;
|
use function dirname;
|
||||||
@ -275,7 +276,10 @@ abstract class PluginBase implements Plugin, CommandExecutor{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret = stream_copy_to_stream($resource, $fp = fopen($out, "wb")) > 0;
|
$fp = fopen($out, "wb");
|
||||||
|
if($fp === false) throw new AssumptionFailedError("fopen() should not fail with wb flags");
|
||||||
|
|
||||||
|
$ret = stream_copy_to_stream($resource, $fp) > 0;
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
fclose($resource);
|
fclose($resource);
|
||||||
return $ret;
|
return $ret;
|
||||||
|
@ -27,7 +27,6 @@ use pocketmine\permission\Permission;
|
|||||||
use pocketmine\permission\PermissionParser;
|
use pocketmine\permission\PermissionParser;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
use function array_values;
|
use function array_values;
|
||||||
use function extension_loaded;
|
|
||||||
use function is_array;
|
use function is_array;
|
||||||
use function phpversion;
|
use function phpversion;
|
||||||
use function preg_match;
|
use function preg_match;
|
||||||
@ -229,11 +228,11 @@ class PluginDescription{
|
|||||||
*/
|
*/
|
||||||
public function checkRequiredExtensions() : void{
|
public function checkRequiredExtensions() : void{
|
||||||
foreach($this->extensions as $name => $versionConstrs){
|
foreach($this->extensions as $name => $versionConstrs){
|
||||||
if(!extension_loaded($name)){
|
$gotVersion = phpversion($name);
|
||||||
|
if($gotVersion === false){
|
||||||
throw new PluginException("Required extension $name not loaded");
|
throw new PluginException("Required extension $name not loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
$gotVersion = phpversion($name);
|
|
||||||
foreach($versionConstrs as $constr){ // versionConstrs_loop
|
foreach($versionConstrs as $constr){ // versionConstrs_loop
|
||||||
if($constr === "*"){
|
if($constr === "*"){
|
||||||
continue;
|
continue;
|
||||||
|
@ -34,6 +34,7 @@ use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
|||||||
use pocketmine\permission\PermissionManager;
|
use pocketmine\permission\PermissionManager;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
use pocketmine\timings\TimingsHandler;
|
use pocketmine\timings\TimingsHandler;
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
use function array_intersect;
|
use function array_intersect;
|
||||||
use function array_map;
|
use function array_map;
|
||||||
@ -208,6 +209,7 @@ class PluginManager{
|
|||||||
shuffle($files); //this prevents plugins implicitly relying on the filesystem name order when they should be using dependency properties
|
shuffle($files); //this prevents plugins implicitly relying on the filesystem name order when they should be using dependency properties
|
||||||
foreach($loaders as $loader){
|
foreach($loaders as $loader){
|
||||||
foreach($files as $file){
|
foreach($files as $file){
|
||||||
|
if(!is_string($file)) throw new AssumptionFailedError("FilesystemIterator current should be string when using CURRENT_AS_PATHNAME");
|
||||||
if(!$loader->canLoadPlugin($file)){
|
if(!$loader->canLoadPlugin($file)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,10 @@ class ScriptPluginLoader implements PluginLoader{
|
|||||||
* Gets the PluginDescription from the file
|
* Gets the PluginDescription from the file
|
||||||
*/
|
*/
|
||||||
public function getPluginDescription(string $file) : ?PluginDescription{
|
public function getPluginDescription(string $file) : ?PluginDescription{
|
||||||
$content = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
$content = @file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||||
|
if($content === false){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
|
@ -52,9 +52,15 @@ class AsyncPool{
|
|||||||
/** @var \SplQueue[]|AsyncTask[][] */
|
/** @var \SplQueue[]|AsyncTask[][] */
|
||||||
private $taskQueues = [];
|
private $taskQueues = [];
|
||||||
|
|
||||||
/** @var AsyncWorker[] */
|
/**
|
||||||
|
* @var AsyncWorker[]
|
||||||
|
* @phpstan-var array<int, AsyncWorker>
|
||||||
|
*/
|
||||||
private $workers = [];
|
private $workers = [];
|
||||||
/** @var int[] */
|
/**
|
||||||
|
* @var int[]
|
||||||
|
* @phpstan-var array<int, int>
|
||||||
|
*/
|
||||||
private $workerLastUsed = [];
|
private $workerLastUsed = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\scheduler;
|
namespace pocketmine\scheduler;
|
||||||
|
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use function is_scalar;
|
use function is_scalar;
|
||||||
use function serialize;
|
use function serialize;
|
||||||
use function spl_object_id;
|
use function spl_object_id;
|
||||||
@ -105,7 +106,11 @@ abstract class AsyncTask extends \Threaded{
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getResult(){
|
public function getResult(){
|
||||||
return $this->serialized ? unserialize($this->result) : $this->result;
|
if($this->serialized){
|
||||||
|
if(!is_string($this->result)) throw new AssumptionFailedError("Result expected to be a serialized string");
|
||||||
|
return unserialize($this->result);
|
||||||
|
}
|
||||||
|
return $this->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cancelRun() : void{
|
public function cancelRun() : void{
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\scheduler;
|
|||||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use pocketmine\utils\Internet;
|
use pocketmine\utils\Internet;
|
||||||
use pocketmine\utils\Process;
|
use pocketmine\utils\Process;
|
||||||
use pocketmine\utils\Utils;
|
use pocketmine\utils\Utils;
|
||||||
@ -149,7 +150,9 @@ class SendUsageTask extends AsyncTask{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->endpoint = $endpoint . "api/post";
|
$this->endpoint = $endpoint . "api/post";
|
||||||
$this->data = json_encode($data/*, JSON_PRETTY_PRINT*/);
|
$data = json_encode($data/*, JSON_PRETTY_PRINT*/);
|
||||||
|
if($data === false) throw new AssumptionFailedError("Statistics JSON should never fail to encode: " . json_last_error_msg());
|
||||||
|
$this->data = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onRun() : void{
|
public function onRun() : void{
|
||||||
|
@ -166,6 +166,9 @@ class Config{
|
|||||||
$this->save();
|
$this->save();
|
||||||
}else{
|
}else{
|
||||||
$content = file_get_contents($this->file);
|
$content = file_get_contents($this->file);
|
||||||
|
if($content === false){
|
||||||
|
throw new \RuntimeException("Unable to load config file");
|
||||||
|
}
|
||||||
$config = null;
|
$config = null;
|
||||||
switch($this->type){
|
switch($this->type){
|
||||||
case Config::PROPERTIES:
|
case Config::PROPERTIES:
|
||||||
@ -539,7 +542,6 @@ class Config{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed[]
|
* @return mixed[]
|
||||||
* @phpstan-return array<string, mixed>
|
|
||||||
*/
|
*/
|
||||||
private function parseProperties(string $content) : array{
|
private function parseProperties(string $content) : array{
|
||||||
$result = [];
|
$result = [];
|
||||||
|
@ -58,6 +58,7 @@ final class Filesystem{
|
|||||||
public static function recursiveUnlink(string $dir) : void{
|
public static function recursiveUnlink(string $dir) : void{
|
||||||
if(is_dir($dir)){
|
if(is_dir($dir)){
|
||||||
$objects = scandir($dir, SCANDIR_SORT_NONE);
|
$objects = scandir($dir, SCANDIR_SORT_NONE);
|
||||||
|
if($objects === false) throw new AssumptionFailedError("scandir() shouldn't return false when is_dir() returns true");
|
||||||
foreach($objects as $object){
|
foreach($objects as $object){
|
||||||
if($object !== "." and $object !== ".."){
|
if($object !== "." and $object !== ".."){
|
||||||
if(is_dir($dir . "/" . $object)){
|
if(is_dir($dir . "/" . $object)){
|
||||||
|
@ -72,7 +72,7 @@ class Internet{
|
|||||||
*
|
*
|
||||||
* @param bool $force default false, force IP check even when cached
|
* @param bool $force default false, force IP check even when cached
|
||||||
*
|
*
|
||||||
* @return string|bool
|
* @return string|false
|
||||||
*/
|
*/
|
||||||
public static function getIP(bool $force = false){
|
public static function getIP(bool $force = false){
|
||||||
if(!self::$online){
|
if(!self::$online){
|
||||||
@ -116,7 +116,10 @@ class Internet{
|
|||||||
* @throws InternetException
|
* @throws InternetException
|
||||||
*/
|
*/
|
||||||
public static function getInternalIP() : string{
|
public static function getInternalIP() : string{
|
||||||
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
$sock = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||||
|
if($sock === false){
|
||||||
|
throw new InternetException("Failed to get internal IP: " . trim(socket_strerror(socket_last_error())));
|
||||||
|
}
|
||||||
try{
|
try{
|
||||||
if(!@socket_connect($sock, "8.8.8.8", 65534)){
|
if(!@socket_connect($sock, "8.8.8.8", 65534)){
|
||||||
throw new InternetException("Failed to get internal IP: " . trim(socket_strerror(socket_last_error($sock))));
|
throw new InternetException("Failed to get internal IP: " . trim(socket_strerror(socket_last_error($sock))));
|
||||||
@ -205,6 +208,9 @@ class Internet{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$ch = curl_init($page);
|
$ch = curl_init($page);
|
||||||
|
if($ch === false){
|
||||||
|
throw new InternetException("Unable to create new cURL session");
|
||||||
|
}
|
||||||
|
|
||||||
curl_setopt_array($ch, $extraOpts + [
|
curl_setopt_array($ch, $extraOpts + [
|
||||||
CURLOPT_SSL_VERIFYPEER => false,
|
CURLOPT_SSL_VERIFYPEER => false,
|
||||||
@ -221,10 +227,10 @@ class Internet{
|
|||||||
]);
|
]);
|
||||||
try{
|
try{
|
||||||
$raw = curl_exec($ch);
|
$raw = curl_exec($ch);
|
||||||
$error = curl_error($ch);
|
if($raw === false){
|
||||||
if($error !== ""){
|
throw new InternetException(curl_error($ch));
|
||||||
throw new InternetException($error);
|
|
||||||
}
|
}
|
||||||
|
if(!is_string($raw)) throw new AssumptionFailedError("curl_exec() should return string|false when CURLOPT_RETURNTRANSFER is set");
|
||||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||||
$rawHeaders = substr($raw, 0, $headerSize);
|
$rawHeaders = substr($raw, 0, $headerSize);
|
||||||
|
@ -55,13 +55,16 @@ final class Process{
|
|||||||
$VmSize = null;
|
$VmSize = null;
|
||||||
$VmRSS = null;
|
$VmRSS = null;
|
||||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||||
$status = file_get_contents("/proc/self/status");
|
$status = @file_get_contents("/proc/self/status");
|
||||||
|
if($status === false) throw new AssumptionFailedError("/proc/self/status should always be accessible");
|
||||||
|
|
||||||
|
// the numbers found here should never be bigger than PHP_INT_MAX, so we expect them to always be castable to int
|
||||||
if(preg_match("/VmRSS:[ \t]+([0-9]+) kB/", $status, $matches) > 0){
|
if(preg_match("/VmRSS:[ \t]+([0-9]+) kB/", $status, $matches) > 0){
|
||||||
$VmRSS = $matches[1] * 1024;
|
$VmRSS = ((int) $matches[1]) * 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(preg_match("/VmSize:[ \t]+([0-9]+) kB/", $status, $matches) > 0){
|
if(preg_match("/VmSize:[ \t]+([0-9]+) kB/", $status, $matches) > 0){
|
||||||
$VmSize = $matches[1] * 1024;
|
$VmSize = ((int) $matches[1]) * 1024;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,13 +93,14 @@ final class Process{
|
|||||||
$heap = 0;
|
$heap = 0;
|
||||||
|
|
||||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||||
$mappings = file("/proc/self/maps");
|
$mappings = @file("/proc/self/maps");
|
||||||
|
if($mappings === false) throw new AssumptionFailedError("/proc/self/maps should always be accessible");
|
||||||
foreach($mappings as $line){
|
foreach($mappings as $line){
|
||||||
if(preg_match("#([a-z0-9]+)\\-([a-z0-9]+) [rwxp\\-]{4} [a-z0-9]+ [^\\[]*\\[([a-zA-z0-9]+)\\]#", trim($line), $matches) > 0){
|
if(preg_match("#([a-z0-9]+)\\-([a-z0-9]+) [rwxp\\-]{4} [a-z0-9]+ [^\\[]*\\[([a-zA-z0-9]+)\\]#", trim($line), $matches) > 0){
|
||||||
if(strpos($matches[3], "heap") === 0){
|
if(strpos($matches[3], "heap") === 0){
|
||||||
$heap += hexdec($matches[2]) - hexdec($matches[1]);
|
$heap += (int) hexdec($matches[2]) - (int) hexdec($matches[1]);
|
||||||
}elseif(strpos($matches[3], "stack") === 0){
|
}elseif(strpos($matches[3], "stack") === 0){
|
||||||
$stack += hexdec($matches[2]) - hexdec($matches[1]);
|
$stack += (int) hexdec($matches[2]) - (int) hexdec($matches[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +111,9 @@ final class Process{
|
|||||||
|
|
||||||
public static function getThreadCount() : int{
|
public static function getThreadCount() : int{
|
||||||
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
if(Utils::getOS() === "linux" or Utils::getOS() === "android"){
|
||||||
if(preg_match("/Threads:[ \t]+([0-9]+)/", file_get_contents("/proc/self/status"), $matches) > 0){
|
$status = @file_get_contents("/proc/self/status");
|
||||||
|
if($status === false) throw new AssumptionFailedError("/proc/self/status should always be accessible");
|
||||||
|
if(preg_match("/Threads:[ \t]+([0-9]+)/", $status, $matches) > 0){
|
||||||
return (int) $matches[1];
|
return (int) $matches[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,7 @@ abstract class Terminal{
|
|||||||
|
|
||||||
private static function detectFormattingCodesSupport() : bool{
|
private static function detectFormattingCodesSupport() : bool{
|
||||||
$stdout = fopen("php://stdout", "w");
|
$stdout = fopen("php://stdout", "w");
|
||||||
|
if($stdout === false) throw new AssumptionFailedError("Opening php://stdout should never fail");
|
||||||
$result = (
|
$result = (
|
||||||
stream_isatty($stdout) and //STDOUT isn't being piped
|
stream_isatty($stdout) and //STDOUT isn't being piped
|
||||||
(
|
(
|
||||||
|
@ -66,13 +66,19 @@ abstract class TextFormat{
|
|||||||
public const ITALIC = TextFormat::ESCAPE . "o";
|
public const ITALIC = TextFormat::ESCAPE . "o";
|
||||||
public const RESET = TextFormat::ESCAPE . "r";
|
public const RESET = TextFormat::ESCAPE . "r";
|
||||||
|
|
||||||
|
private static function makePcreError(string $info) : \InvalidArgumentException{
|
||||||
|
throw new \InvalidArgumentException("$info: Encountered PCRE error " . preg_last_error() . " during regex operation");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits the string by Format tokens
|
* Splits the string by Format tokens
|
||||||
*
|
*
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
public static function tokenize(string $string) : array{
|
public static function tokenize(string $string) : array{
|
||||||
return preg_split("/(" . TextFormat::ESCAPE . "[0-9a-fk-or])/u", $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
$result = preg_split("/(" . TextFormat::ESCAPE . "[0-9a-fk-or])/u", $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||||
|
if($result === false) throw self::makePcreError("Failed to tokenize string");
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,6 +89,7 @@ abstract class TextFormat{
|
|||||||
public static function clean(string $string, bool $removeFormat = true) : string{
|
public static function clean(string $string, bool $removeFormat = true) : string{
|
||||||
$string = mb_scrub($string, 'UTF-8');
|
$string = mb_scrub($string, 'UTF-8');
|
||||||
$string = preg_replace("/[\x{E000}-\x{F8FF}]/u", "", $string); //remove unicode private-use-area characters (they might break the console)
|
$string = preg_replace("/[\x{E000}-\x{F8FF}]/u", "", $string); //remove unicode private-use-area characters (they might break the console)
|
||||||
|
if($string === null) throw self::makePcreError("Failed to strip private-area characters");
|
||||||
if($removeFormat){
|
if($removeFormat){
|
||||||
$string = str_replace(TextFormat::ESCAPE, "", preg_replace("/" . TextFormat::ESCAPE . "[0-9a-fk-or]/u", "", $string));
|
$string = str_replace(TextFormat::ESCAPE, "", preg_replace("/" . TextFormat::ESCAPE . "[0-9a-fk-or]/u", "", $string));
|
||||||
}
|
}
|
||||||
@ -281,7 +288,11 @@ abstract class TextFormat{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return json_encode($newString, JSON_UNESCAPED_SLASHES);
|
$result = json_encode($newString, JSON_UNESCAPED_SLASHES);
|
||||||
|
if($result === false){
|
||||||
|
throw new \InvalidArgumentException("Failed to encode result JSON: " . json_last_error_msg());
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +48,11 @@ use function trim;
|
|||||||
abstract class Timezone{
|
abstract class Timezone{
|
||||||
|
|
||||||
public static function get() : string{
|
public static function get() : string{
|
||||||
return ini_get('date.timezone');
|
$tz = ini_get('date.timezone');
|
||||||
|
if($tz === false){
|
||||||
|
throw new AssumptionFailedError('date.timezone INI entry should always exist');
|
||||||
|
}
|
||||||
|
return $tz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function init() : void{
|
public static function init() : void{
|
||||||
@ -138,20 +142,17 @@ abstract class Timezone{
|
|||||||
return self::parseOffset($offset);
|
return self::parseOffset($offset);
|
||||||
case 'linux':
|
case 'linux':
|
||||||
// Ubuntu / Debian.
|
// Ubuntu / Debian.
|
||||||
if(file_exists('/etc/timezone')){
|
$data = @file_get_contents('/etc/timezone');
|
||||||
$data = file_get_contents('/etc/timezone');
|
if($data !== false){
|
||||||
if($data){
|
|
||||||
return trim($data);
|
return trim($data);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// RHEL / CentOS
|
// RHEL / CentOS
|
||||||
if(file_exists('/etc/sysconfig/clock')){
|
$data = @parse_ini_file('/etc/sysconfig/clock');
|
||||||
$data = parse_ini_file('/etc/sysconfig/clock');
|
if($data !== false and isset($data['ZONE']) and is_string($data['ZONE'])){
|
||||||
if(isset($data['ZONE']) and is_string($data['ZONE'])){
|
|
||||||
return trim($data['ZONE']);
|
return trim($data['ZONE']);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//Portable method for incompatible linux distributions.
|
//Portable method for incompatible linux distributions.
|
||||||
|
|
||||||
@ -163,13 +164,11 @@ abstract class Timezone{
|
|||||||
|
|
||||||
return self::parseOffset($offset);
|
return self::parseOffset($offset);
|
||||||
case 'mac':
|
case 'mac':
|
||||||
if(is_link('/etc/localtime')){
|
$filename = @readlink('/etc/localtime');
|
||||||
$filename = readlink('/etc/localtime');
|
if($filename !== false and strpos($filename, '/usr/share/zoneinfo/') === 0){
|
||||||
if(strpos($filename, '/usr/share/zoneinfo/') === 0){
|
|
||||||
$timezone = substr($filename, 20);
|
$timezone = substr($filename, 20);
|
||||||
return trim($timezone);
|
return trim($timezone);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
@ -180,7 +179,7 @@ abstract class Timezone{
|
|||||||
/**
|
/**
|
||||||
* @param string $offset In the format of +09:00, +02:00, -04:00 etc.
|
* @param string $offset In the format of +09:00, +02:00, -04:00 etc.
|
||||||
*
|
*
|
||||||
* @return string|bool
|
* @return string|false
|
||||||
*/
|
*/
|
||||||
private static function parseOffset($offset){
|
private static function parseOffset($offset){
|
||||||
//Make signed offsets unsigned for date_parse
|
//Make signed offsets unsigned for date_parse
|
||||||
|
@ -61,7 +61,12 @@ final class UUID{
|
|||||||
* Creates an UUID from an hexadecimal representation
|
* Creates an UUID from an hexadecimal representation
|
||||||
*/
|
*/
|
||||||
public static function fromString(string $uuid, ?int $version = null) : UUID{
|
public static function fromString(string $uuid, ?int $version = null) : UUID{
|
||||||
return self::fromBinary(hex2bin(str_replace("-", "", trim($uuid))), $version);
|
//TODO: should we be stricter about the notation (8-4-4-4-12)?
|
||||||
|
$binary = @hex2bin(str_replace("-", "", trim($uuid)));
|
||||||
|
if($binary === false){
|
||||||
|
throw new \InvalidArgumentException("Invalid hex string UUID representation");
|
||||||
|
}
|
||||||
|
return self::fromBinary($binary, $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,7 +114,12 @@ class Utils{
|
|||||||
//non-class function
|
//non-class function
|
||||||
return $func->getName();
|
return $func->getName();
|
||||||
}
|
}
|
||||||
return "closure@" . Filesystem::cleanPath($func->getFileName()) . "#L" . $func->getStartLine();
|
$filename = $func->getFileName();
|
||||||
|
|
||||||
|
return "closure@" . ($filename !== false ?
|
||||||
|
Filesystem::cleanPath($filename) . "#L" . $func->getStartLine() :
|
||||||
|
"internal"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,7 +130,12 @@ class Utils{
|
|||||||
public static function getNiceClassName(object $obj) : string{
|
public static function getNiceClassName(object $obj) : string{
|
||||||
$reflect = new \ReflectionClass($obj);
|
$reflect = new \ReflectionClass($obj);
|
||||||
if($reflect->isAnonymous()){
|
if($reflect->isAnonymous()){
|
||||||
return "anonymous@" . Filesystem::cleanPath($reflect->getFileName()) . "#L" . $reflect->getStartLine();
|
$filename = $reflect->getFileName();
|
||||||
|
|
||||||
|
return "anonymous@" . ($filename !== false ?
|
||||||
|
Filesystem::cleanPath($filename) . "#L" . $reflect->getStartLine() :
|
||||||
|
"internal"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $reflect->getName();
|
return $reflect->getName();
|
||||||
@ -169,14 +179,14 @@ class Utils{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$machine = php_uname("a");
|
$machine = php_uname("a");
|
||||||
$machine .= file_exists("/proc/cpuinfo") ? implode(preg_grep("/(model name|Processor|Serial)/", file("/proc/cpuinfo"))) : "";
|
$machine .= ($cpuinfo = @file("/proc/cpuinfo")) !== false ? implode(preg_grep("/(model name|Processor|Serial)/", $cpuinfo)) : "";
|
||||||
$machine .= sys_get_temp_dir();
|
$machine .= sys_get_temp_dir();
|
||||||
$machine .= $extra;
|
$machine .= $extra;
|
||||||
$os = Utils::getOS();
|
$os = Utils::getOS();
|
||||||
if($os === "win"){
|
if($os === "win"){
|
||||||
@exec("ipconfig /ALL", $mac);
|
@exec("ipconfig /ALL", $mac);
|
||||||
$mac = implode("\n", $mac);
|
$mac = implode("\n", $mac);
|
||||||
if(preg_match_all("#Physical Address[. ]{1,}: ([0-9A-F\\-]{17})#", $mac, $matches)){
|
if(preg_match_all("#Physical Address[. ]{1,}: ([0-9A-F\\-]{17})#", $mac, $matches) > 0){
|
||||||
foreach($matches[1] as $i => $v){
|
foreach($matches[1] as $i => $v){
|
||||||
if($v == "00-00-00-00-00-00"){
|
if($v == "00-00-00-00-00-00"){
|
||||||
unset($matches[1][$i]);
|
unset($matches[1][$i]);
|
||||||
@ -190,7 +200,7 @@ class Utils{
|
|||||||
}else{
|
}else{
|
||||||
@exec("ifconfig 2>/dev/null", $mac);
|
@exec("ifconfig 2>/dev/null", $mac);
|
||||||
$mac = implode("\n", $mac);
|
$mac = implode("\n", $mac);
|
||||||
if(preg_match_all("#HWaddr[ \t]{1,}([0-9a-f:]{17})#", $mac, $matches)){
|
if(preg_match_all("#HWaddr[ \t]{1,}([0-9a-f:]{17})#", $mac, $matches) > 0){
|
||||||
foreach($matches[1] as $i => $v){
|
foreach($matches[1] as $i => $v){
|
||||||
if($v == "00:00:00:00:00:00"){
|
if($v == "00:00:00:00:00:00"){
|
||||||
unset($matches[1][$i]);
|
unset($matches[1][$i]);
|
||||||
@ -270,14 +280,14 @@ class Utils{
|
|||||||
switch(Utils::getOS()){
|
switch(Utils::getOS()){
|
||||||
case "linux":
|
case "linux":
|
||||||
case "android":
|
case "android":
|
||||||
if(file_exists("/proc/cpuinfo")){
|
if(($cpuinfo = @file('/proc/cpuinfo')) !== false){
|
||||||
foreach(file("/proc/cpuinfo") as $l){
|
foreach($cpuinfo as $l){
|
||||||
if(preg_match('/^processor[ \t]*:[ \t]*[0-9]+$/m', $l) > 0){
|
if(preg_match('/^processor[ \t]*:[ \t]*[0-9]+$/m', $l) > 0){
|
||||||
++$processors;
|
++$processors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}elseif(is_readable("/sys/devices/system/cpu/present")){
|
}elseif(($cpuPresent = @file_get_contents("/sys/devices/system/cpu/present")) !== false){
|
||||||
if(preg_match("/^([0-9]+)\\-([0-9]+)$/", trim(file_get_contents("/sys/devices/system/cpu/present")), $matches) > 0){
|
if(preg_match("/^([0-9]+)\\-([0-9]+)$/", trim($cpuPresent), $matches) > 0){
|
||||||
$processors = (int) ($matches[2] - $matches[1]);
|
$processors = (int) ($matches[2] - $matches[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,7 +392,9 @@ class Utils{
|
|||||||
public static function getReferenceCount($value, bool $includeCurrent = true) : int{
|
public static function getReferenceCount($value, bool $includeCurrent = true) : int{
|
||||||
ob_start();
|
ob_start();
|
||||||
debug_zval_dump($value);
|
debug_zval_dump($value);
|
||||||
$ret = explode("\n", ob_get_contents());
|
$contents = ob_get_contents();
|
||||||
|
if($contents === false) throw new AssumptionFailedError("ob_get_contents() should never return false here");
|
||||||
|
$ret = explode("\n", $contents);
|
||||||
ob_end_clean();
|
ob_end_clean();
|
||||||
|
|
||||||
if(count($ret) >= 1 and preg_match('/^.* refcount\\(([0-9]+)\\)\\{$/', trim($ret[0]), $m) > 0){
|
if(count($ret) >= 1 and preg_match('/^.* refcount\\(([0-9]+)\\)\\{$/', trim($ret[0]), $m) > 0){
|
||||||
@ -462,6 +474,10 @@ class Utils{
|
|||||||
return array_combine($matches[1], $matches[2]);
|
return array_combine($matches[1], $matches[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-param class-string $className
|
||||||
|
* @phpstan-param class-string $baseName
|
||||||
|
*/
|
||||||
public static function testValidInstance(string $className, string $baseName) : void{
|
public static function testValidInstance(string $className, string $baseName) : void{
|
||||||
try{
|
try{
|
||||||
$base = new \ReflectionClass($baseName);
|
$base = new \ReflectionClass($baseName);
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\world\format\io\region;
|
namespace pocketmine\world\format\io\region;
|
||||||
|
|
||||||
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
use pocketmine\utils\Binary;
|
use pocketmine\utils\Binary;
|
||||||
use pocketmine\world\format\ChunkException;
|
use pocketmine\world\format\ChunkException;
|
||||||
use pocketmine\world\format\io\exception\CorruptedChunkException;
|
use pocketmine\world\format\io\exception\CorruptedChunkException;
|
||||||
@ -88,7 +89,9 @@ class RegionLoader{
|
|||||||
throw new CorruptedRegionException("Region file should be padded to a multiple of 4KiB");
|
throw new CorruptedRegionException("Region file should be padded to a multiple of 4KiB");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->filePointer = fopen($this->filePath, "r+b");
|
$filePointer = fopen($this->filePath, "r+b");
|
||||||
|
if($filePointer === false) throw new AssumptionFailedError("fopen() should not fail here");
|
||||||
|
$this->filePointer = $filePointer;
|
||||||
stream_set_read_buffer($this->filePointer, 1024 * 16); //16KB
|
stream_set_read_buffer($this->filePointer, 1024 * 16); //16KB
|
||||||
stream_set_write_buffer($this->filePointer, 1024 * 16); //16KB
|
stream_set_write_buffer($this->filePointer, 1024 * 16); //16KB
|
||||||
if(!$exists){
|
if(!$exists){
|
||||||
|
@ -82,6 +82,12 @@ parameters:
|
|||||||
count: 1
|
count: 1
|
||||||
path: ../../../src/network/mcpe/protocol/types/entity/EntityMetadataCollection.php
|
path: ../../../src/network/mcpe/protocol/types/entity/EntityMetadataCollection.php
|
||||||
|
|
||||||
|
-
|
||||||
|
#readlink() can return false but phpstan doesn't know this
|
||||||
|
message: "#^Strict comparison using \\!\\=\\= between string and false will always evaluate to true\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: ../../../src/pocketmine/utils/Timezone.php
|
||||||
|
|
||||||
-
|
-
|
||||||
#phpstan doesn't understand that SplFixedArray may contain null
|
#phpstan doesn't understand that SplFixedArray may contain null
|
||||||
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNotNull\\(\\) with int and string will always evaluate to true\\.$#"
|
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNotNull\\(\\) with int and string will always evaluate to true\\.$#"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user