mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-20 16:00:20 +00:00
Drop support for 32 bit systems/PHP (#984)
* Cutting out 32-bit and minor improvements to bootstrap * Byeeeeee * Removing legacy code * added note to the issue template as suggested by @xxFlare
This commit is contained in:
parent
3687b149b9
commit
4765242397
9
.github/ISSUE_TEMPLATE.md
vendored
9
.github/ISSUE_TEMPLATE.md
vendored
@ -16,9 +16,12 @@ Actual result: What actually happened?
|
||||
|
||||
### OS and versions
|
||||
<!--- use the 'version' command in PocketMine-MP
|
||||
NOTE: LATEST is not a valid version.
|
||||
PocketMine version should include Jenkins build number and/or git commit hash.
|
||||
ALSO NOTE: NO support whatsoever will be provided for forks or spoons of PocketMine. Issues relating to non-official distributions will be closed as spam. Please send such issues to whoever is responsible for the fork or spoon you are using.
|
||||
|
||||
NOTE: LATEST is not a valid version. PocketMine version should include Jenkins build number and/or git commit hash.
|
||||
|
||||
NO support whatsoever will be provided for forks or spoons of PocketMine. Issues relating to non-official distributions will be closed as spam. Please send such issues to whoever is responsible for the fork or spoon you are using.
|
||||
|
||||
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
|
||||
-->
|
||||
* PocketMine-MP:
|
||||
* PHP:
|
||||
|
@ -91,11 +91,6 @@ class MemoryManager{
|
||||
|
||||
$hardLimit = ((int) $this->server->getProperty("memory.main-hard-limit", $defaultMemory));
|
||||
|
||||
if(PHP_INT_SIZE === 4 and $hardLimit >= 4096){
|
||||
$this->server->getLogger()->warning("Cannot set memory limit higher than 4GB on 32-bit, defaulting to max 4095MB");
|
||||
$hardLimit = 4095;
|
||||
}
|
||||
|
||||
if($hardLimit <= 0){
|
||||
ini_set("memory_limit", -1);
|
||||
}else{
|
||||
|
@ -401,137 +401,135 @@ namespace pocketmine {
|
||||
return rtrim(str_replace(["\\", ".php", "phar://", rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), "/"), rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH), "/")], ["/", "", "", "", ""], $path), "/");
|
||||
}
|
||||
|
||||
$errors = 0;
|
||||
$exitCode = 0;
|
||||
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$logger->critical("You must run PocketMine-MP using the CLI.");
|
||||
++$errors;
|
||||
}
|
||||
do{
|
||||
$errors = 0;
|
||||
|
||||
$pthreads_version = phpversion("pthreads");
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.5") < 0){
|
||||
$logger->critical("pthreads >= 3.1.5 is required, while you have $pthreads_version.");
|
||||
++$errors;
|
||||
}
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$logger->critical("Running PocketMine-MP with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system or use a 64-bit PHP binary.");
|
||||
$exitCode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(extension_loaded("pocketmine")){
|
||||
if(version_compare(phpversion("pocketmine"), "0.0.1") < 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is lower than 0.0.1.");
|
||||
++$errors;
|
||||
}elseif(version_compare(phpversion("pocketmine"), "0.0.4") > 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is higher than 0.0.4.");
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$logger->critical("You must run PocketMine-MP using the CLI.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning("
|
||||
|
||||
|
||||
You are running PocketMine with xdebug enabled. This has a major impact on performance.
|
||||
|
||||
");
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"curl" => "cURL",
|
||||
"json" => "JSON",
|
||||
"mbstring" => "Multibyte String",
|
||||
"yaml" => "YAML",
|
||||
"sockets" => "Sockets",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$logger->critical("Unable to find the $name ($ext) extension.");
|
||||
$pthreads_version = phpversion("pthreads");
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.5") < 0){
|
||||
$logger->critical("pthreads >= 3.1.5 is required, while you have $pthreads_version.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if($errors > 0){
|
||||
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
exit(1); //Exit with error
|
||||
}
|
||||
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$logger->warning("Running PocketMine-MP with 32-bit systems/PHP is deprecated. Support for 32-bit may be dropped in the future.");
|
||||
}
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
if(file_exists(\pocketmine\PATH . ".git/HEAD")){ //Found Git information!
|
||||
$ref = trim(file_get_contents(\pocketmine\PATH . ".git/HEAD"));
|
||||
if(preg_match('/^[0-9a-f]{40}$/i', $ref)){
|
||||
$gitHash = strtolower($ref);
|
||||
}elseif(substr($ref, 0, 5) === "ref: "){
|
||||
$refFile = \pocketmine\PATH . ".git/" . substr($ref, 5);
|
||||
if(is_file($refFile)){
|
||||
$gitHash = strtolower(trim(file_get_contents($refFile)));
|
||||
if(extension_loaded("pocketmine")){
|
||||
if(version_compare(phpversion("pocketmine"), "0.0.1") < 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is lower than 0.0.1.");
|
||||
++$errors;
|
||||
}elseif(version_compare(phpversion("pocketmine"), "0.0.4") > 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is higher than 0.0.4.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
|
||||
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
exit(-1);
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running PocketMine with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"curl" => "cURL",
|
||||
"json" => "JSON",
|
||||
"mbstring" => "Multibyte String",
|
||||
"yaml" => "YAML",
|
||||
"sockets" => "Sockets",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
|
||||
}
|
||||
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start();
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
$erroredThreads = 0;
|
||||
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
|
||||
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
|
||||
try{
|
||||
$thread->quit();
|
||||
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
|
||||
}catch(\ThreadException $e){
|
||||
++$erroredThreads;
|
||||
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$logger->critical("Unable to find the $name ($ext) extension.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($errors > 0){
|
||||
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||
$exitCode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
if(file_exists(\pocketmine\PATH . ".git/HEAD")){ //Found Git information!
|
||||
$ref = trim(file_get_contents(\pocketmine\PATH . ".git/HEAD"));
|
||||
if(preg_match('/^[0-9a-f]{40}$/i', $ref)){
|
||||
$gitHash = strtolower($ref);
|
||||
}elseif(substr($ref, 0, 5) === "ref: "){
|
||||
$refFile = \pocketmine\PATH . ".git/" . substr($ref, 5);
|
||||
if(is_file($refFile)){
|
||||
$gitHash = strtolower(trim(file_get_contents($refFile)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
|
||||
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
|
||||
}
|
||||
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start();
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
$erroredThreads = 0;
|
||||
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
|
||||
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
|
||||
try{
|
||||
$thread->quit();
|
||||
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
|
||||
}catch(\ThreadException $e){
|
||||
++$erroredThreads;
|
||||
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if($erroredThreads > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
|
||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||
|
||||
if($erroredThreads > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
kill(getmypid());
|
||||
}else{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
exit($exitCode);
|
||||
}
|
||||
|
@ -265,24 +265,17 @@ class Level implements ChunkManager, Metadatable{
|
||||
private $closed = false;
|
||||
|
||||
public static function chunkHash(int $x, int $z){
|
||||
return PHP_INT_SIZE === 8 ? (($x & 0xFFFFFFFF) << 32) | ($z & 0xFFFFFFFF) : $x . ":" . $z;
|
||||
return (($x & 0xFFFFFFFF) << 32) | ($z & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
public static function blockHash(int $x, int $y, int $z){
|
||||
return PHP_INT_SIZE === 8 ? (($x & 0xFFFFFFF) << 36) | (($y & Level::Y_MASK) << 28) | ($z & 0xFFFFFFF) : $x . ":" . $y . ":" . $z;
|
||||
return (($x & 0xFFFFFFF) << 36) | (($y & Level::Y_MASK) << 28) | ($z & 0xFFFFFFF);
|
||||
}
|
||||
|
||||
public static function getBlockXYZ($hash, &$x, &$y, &$z){
|
||||
if(PHP_INT_SIZE === 8){
|
||||
$x = $hash >> 36;
|
||||
$y = ($hash >> 28) & Level::Y_MASK; //it's always positive
|
||||
$z = ($hash & 0xFFFFFFF) << 36 >> 36;
|
||||
}else{
|
||||
$hash = explode(":", $hash);
|
||||
$x = (int) $hash[0];
|
||||
$y = (int) $hash[1];
|
||||
$z = (int) $hash[2];
|
||||
}
|
||||
$x = $hash >> 36;
|
||||
$y = ($hash >> 28) & Level::Y_MASK; //it's always positive
|
||||
$z = ($hash & 0xFFFFFFF) << 36 >> 36;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -291,14 +284,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
* @param int|null $z
|
||||
*/
|
||||
public static function getXZ($hash, &$x, &$z){
|
||||
if(PHP_INT_SIZE === 8){
|
||||
$x = $hash >> 32;
|
||||
$z = ($hash & 0xFFFFFFFF) << 32 >> 32;
|
||||
}else{
|
||||
$hash = explode(":", $hash);
|
||||
$x = (int) $hash[0];
|
||||
$z = (int) $hash[1];
|
||||
}
|
||||
$x = $hash >> 32;
|
||||
$z = ($hash & 0xFFFFFFFF) << 32 >> 32;
|
||||
}
|
||||
|
||||
public static function generateChunkLoaderId(ChunkLoader $loader) : int{
|
||||
|
@ -73,7 +73,7 @@ class Binary{
|
||||
* @return int
|
||||
*/
|
||||
public static function readSignedByte(string $c) : int{
|
||||
return PHP_INT_SIZE === 8 ? (ord($c{0}) << 56 >> 56) : (ord($c{0}) << 24 >> 24);
|
||||
return ord($c{0}) << 56 >> 56;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,11 +106,7 @@ class Binary{
|
||||
*/
|
||||
public static function readSignedShort(string $str) : int{
|
||||
self::checkLength($str, 2);
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return unpack("n", $str)[1] << 48 >> 48;
|
||||
}else{
|
||||
return unpack("n", $str)[1] << 16 >> 16;
|
||||
}
|
||||
return unpack("n", $str)[1] << 48 >> 48;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,11 +141,7 @@ class Binary{
|
||||
*/
|
||||
public static function readSignedLShort(string $str) : int{
|
||||
self::checkLength($str, 2);
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return unpack("v", $str)[1] << 48 >> 48;
|
||||
}else{
|
||||
return unpack("v", $str)[1] << 16 >> 16;
|
||||
}
|
||||
return unpack("v", $str)[1] << 48 >> 48;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,11 +205,7 @@ class Binary{
|
||||
*/
|
||||
public static function readInt(string $str) : int{
|
||||
self::checkLength($str, 4);
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return unpack("N", $str)[1] << 32 >> 32;
|
||||
}else{
|
||||
return unpack("N", $str)[1];
|
||||
}
|
||||
return unpack("N", $str)[1] << 32 >> 32;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,11 +226,7 @@ class Binary{
|
||||
*/
|
||||
public static function readLInt(string $str) : int{
|
||||
self::checkLength($str, 4);
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return unpack("V", $str)[1] << 32 >> 32;
|
||||
}else{
|
||||
return unpack("V", $str)[1];
|
||||
}
|
||||
return unpack("V", $str)[1] << 32 >> 32;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -381,22 +365,8 @@ class Binary{
|
||||
*/
|
||||
public static function readLong(string $x){
|
||||
self::checkLength($x, 8);
|
||||
if(PHP_INT_SIZE === 8){
|
||||
$int = unpack("N*", $x);
|
||||
return ($int[1] << 32) | $int[2];
|
||||
}else{
|
||||
$value = "0";
|
||||
for($i = 0; $i < 8; $i += 2){
|
||||
$value = bcmul($value, "65536", 0);
|
||||
$value = bcadd($value, (string) self::readShort(substr($x, $i, 2)), 0);
|
||||
}
|
||||
|
||||
if(bccomp($value, "9223372036854775807") == 1){
|
||||
$value = bcadd($value, "-18446744073709551616");
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
$int = unpack("N*", $x);
|
||||
return ($int[1] << 32) | $int[2];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -406,23 +376,7 @@ class Binary{
|
||||
* @return string
|
||||
*/
|
||||
public static function writeLong($value) : string{
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return pack("NN", $value >> 32, $value & 0xFFFFFFFF);
|
||||
}else{
|
||||
$x = "";
|
||||
$value = (string) $value;
|
||||
|
||||
if(bccomp($value, "0") == -1){
|
||||
$value = bcadd($value, "18446744073709551616");
|
||||
}
|
||||
|
||||
$x .= self::writeShort((int) bcmod(bcdiv($value, "281474976710656"), "65536"));
|
||||
$x .= self::writeShort((int) bcmod(bcdiv($value, "4294967296"), "65536"));
|
||||
$x .= self::writeShort((int) bcmod(bcdiv($value, "65536"), "65536"));
|
||||
$x .= self::writeShort((int) bcmod($value, "65536"));
|
||||
|
||||
return $x;
|
||||
}
|
||||
return pack("NN", $value >> 32, $value & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -455,10 +409,9 @@ class Binary{
|
||||
* @return int
|
||||
*/
|
||||
public static function readVarInt(string $buffer, int &$offset) : int{
|
||||
$shift = PHP_INT_SIZE === 8 ? 63 : 31;
|
||||
$raw = self::readUnsignedVarInt($buffer, $offset);
|
||||
$temp = ((($raw << $shift) >> $shift) ^ $raw) >> 1;
|
||||
return $temp ^ ($raw & (1 << $shift));
|
||||
$temp = ((($raw << 63) >> 63) ^ $raw) >> 1;
|
||||
return $temp ^ ($raw & (1 << 63));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -494,9 +447,7 @@ class Binary{
|
||||
* @return string
|
||||
*/
|
||||
public static function writeVarInt(int $v) : string{
|
||||
if(PHP_INT_SIZE === 8){
|
||||
$v = ($v << 32 >> 32);
|
||||
}
|
||||
$v = ($v << 32 >> 32);
|
||||
return self::writeUnsignedVarInt(($v << 1) ^ ($v >> 31));
|
||||
}
|
||||
|
||||
@ -525,103 +476,28 @@ class Binary{
|
||||
|
||||
|
||||
/**
|
||||
* Reads a 64-bit zigzag-encoded variable-length integer from the supplied stream.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param int &$offset
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
public static function readVarLong(string $buffer, int &$offset){
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return self::readVarLong_64($buffer, $offset);
|
||||
}else{
|
||||
return self::readVarLong_32($buffer, $offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy BC Math zigzag VarLong reader. Will work on 32-bit or 64-bit, but will be slower than the regular 64-bit method.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param int &$offset
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function readVarLong_32(string $buffer, int &$offset) : string{
|
||||
/** @var string $raw */
|
||||
$raw = self::readUnsignedVarLong_32($buffer, $offset);
|
||||
$result = bcdiv($raw, "2");
|
||||
if(bcmod($raw, "2") === "1"){
|
||||
$result = bcsub(bcmul($result, "-1"), "1");
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 64-bit zizgag VarLong reader.
|
||||
* Reads a 64-bit zigzag-encoded variable-length integer.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param int &$offset
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function readVarLong_64(string $buffer, int &$offset) : int{
|
||||
$raw = self::readUnsignedVarLong_64($buffer, $offset);
|
||||
public static function readVarLong(string $buffer, int &$offset) : int{
|
||||
$raw = self::readUnsignedVarLong($buffer, $offset);
|
||||
$temp = ((($raw << 63) >> 63) ^ $raw) >> 1;
|
||||
return $temp ^ ($raw & (1 << 63));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an unsigned VarLong from the supplied stream.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param int &$offset
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
public static function readUnsignedVarLong(string $buffer, int &$offset){
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return self::readUnsignedVarLong_64($buffer, $offset);
|
||||
}else{
|
||||
return self::readUnsignedVarLong_32($buffer, $offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy BC Math unsigned VarLong reader.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param int &$offset
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function readUnsignedVarLong_32(string $buffer, int &$offset) : string{
|
||||
$value = "0";
|
||||
for($i = 0; $i <= 63; $i += 7){
|
||||
$b = ord($buffer{$offset++});
|
||||
$value = bcadd($value, bcmul((string) ($b & 0x7f), bcpow("2", "$i")));
|
||||
|
||||
if(($b & 0x80) === 0){
|
||||
return $value;
|
||||
}elseif(!isset($buffer{$offset})){
|
||||
throw new \UnexpectedValueException("Expected more bytes, none left to read");
|
||||
}
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("VarLong did not terminate after 10 bytes!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 64-bit unsigned VarLong reader.
|
||||
* Reads a 64-bit unsigned variable-length integer.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param int &$offset
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function readUnsignedVarLong_64(string $buffer, int &$offset) : int{
|
||||
public static function readUnsignedVarLong(string $buffer, int &$offset) : int{
|
||||
$value = 0;
|
||||
for($i = 0; $i <= 63; $i += 7){
|
||||
$b = ord($buffer{$offset++});
|
||||
@ -637,95 +513,23 @@ class Binary{
|
||||
throw new \InvalidArgumentException("VarLong did not terminate after 10 bytes!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Writes a 64-bit integer as a variable-length long.
|
||||
*
|
||||
* @param int|string $v
|
||||
* @return string up to 10 bytes
|
||||
*/
|
||||
public static function writeVarLong($v) : string{
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return self::writeVarLong_64($v);
|
||||
}else{
|
||||
return self::writeVarLong_32((string) $v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy BC Math zigzag VarLong encoder.
|
||||
*
|
||||
* @param string $v
|
||||
* @return string
|
||||
*/
|
||||
public static function writeVarLong_32(string $v) : string{
|
||||
$v = bcmod(bcmul($v, "2"), "18446744073709551616");
|
||||
if(bccomp($v, "0") == -1){
|
||||
$v = bcsub(bcmul($v, "-1"), "1");
|
||||
}
|
||||
|
||||
return self::writeUnsignedVarLong_32($v);
|
||||
}
|
||||
|
||||
/**
|
||||
* 64-bit VarLong encoder.
|
||||
* Writes a 64-bit integer as a zigzag-encoded variable-length long.
|
||||
*
|
||||
* @param int $v
|
||||
* @return string
|
||||
*/
|
||||
public static function writeVarLong_64(int $v) : string{
|
||||
return self::writeUnsignedVarLong_64(($v << 1) ^ ($v >> 63));
|
||||
public static function writeVarLong(int $v) : string{
|
||||
return self::writeUnsignedVarLong(($v << 1) ^ ($v >> 63));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a 64-bit integer as a variable-length long
|
||||
*
|
||||
* @param int|string $v
|
||||
* @return string up to 10 bytes
|
||||
*/
|
||||
public static function writeUnsignedVarLong($v) : string{
|
||||
if(PHP_INT_SIZE === 8){
|
||||
return self::writeUnsignedVarLong_64($v);
|
||||
}else{
|
||||
return self::writeUnsignedVarLong_32((string) $v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy BC Math unsigned VarLong encoder.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function writeUnsignedVarLong_32(string $value) : string{
|
||||
$buf = "";
|
||||
|
||||
if(bccomp($value, "0") == -1){
|
||||
$value = bcadd($value, "18446744073709551616");
|
||||
}
|
||||
|
||||
for($i = 0; $i < 10; ++$i){
|
||||
$byte = (int) bcmod($value, "128");
|
||||
$value = bcdiv($value, "128");
|
||||
if($value !== "0"){
|
||||
$buf .= chr($byte | 0x80);
|
||||
}else{
|
||||
$buf .= chr($byte);
|
||||
return $buf;
|
||||
}
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Value too large to be encoded as a VarLong");
|
||||
}
|
||||
|
||||
/**
|
||||
* 64-bit unsigned VarLong encoder.
|
||||
* Writes a 64-bit unsigned integer as a variable-length long.
|
||||
* @param int $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function writeUnsignedVarLong_64(int $value) : string{
|
||||
public static function writeUnsignedVarLong(int $value) : string{
|
||||
$buf = "";
|
||||
for($i = 0; $i < 10; ++$i){
|
||||
if(($value >> 7) !== 0){
|
||||
|
Loading…
x
Reference in New Issue
Block a user