Fixed item stack count and effect amplifier overflows, close #1072

This commit is contained in:
Dylan K. Taylor 2017-06-17 12:22:38 +01:00
parent 1bae973502
commit e3b3f60c66
3 changed files with 40 additions and 11 deletions

View File

@ -60,6 +60,7 @@ use pocketmine\network\mcpe\protocol\SetEntityDataPacket;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
use pocketmine\Server;
use pocketmine\utils\Binary;
abstract class Entity extends Location implements Metadatable{
@ -773,7 +774,7 @@ abstract class Entity extends Location implements Metadatable{
foreach($this->effects as $effect){
$effects[] = new CompoundTag("", [
"Id" => new ByteTag("Id", $effect->getId()),
"Amplifier" => new ByteTag("Amplifier", $effect->getAmplifier()),
"Amplifier" => new ByteTag("Amplifier", Binary::signByte($effect->getAmplifier())),
"Duration" => new IntTag("Duration", $effect->getDuration()),
"Ambient" => new ByteTag("Ambient", 0),
"ShowParticles" => new ByteTag("ShowParticles", $effect->isVisible() ? 1 : 0)
@ -800,7 +801,7 @@ abstract class Entity extends Location implements Metadatable{
if(isset($this->namedtag->ActiveEffects)){
foreach($this->namedtag->ActiveEffects->getValue() as $e){
$amplifier = $e["Amplifier"] & 0xff; //0-255 only
$amplifier = Binary::unsignByte($e->Amplifier->getValue()); //0-255 only
$effect = Effect::getEffect($e["Id"]);
if($effect === null){

View File

@ -40,6 +40,7 @@ use pocketmine\nbt\tag\StringTag;
use pocketmine\nbt\tag\Tag;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\Binary;
use pocketmine\utils\Config;
class Item implements ItemIds, \JsonSerializable{
@ -1009,7 +1010,7 @@ class Item implements ItemIds, \JsonSerializable{
public function nbtSerialize(int $slot = -1, string $tagName = "") : CompoundTag{
$tag = new CompoundTag($tagName, [
"id" => new ShortTag("id", $this->id),
"Count" => new ByteTag("Count", $this->count),
"Count" => new ByteTag("Count", Binary::signByte($this->count)),
"Damage" => new ShortTag("Damage", $this->meta),
]);
@ -1037,12 +1038,15 @@ class Item implements ItemIds, \JsonSerializable{
return Item::get(0);
}
$count = Binary::unsignByte($tag->Count->getValue());
$meta = isset($tag->Damage) ? $tag->Damage->getValue() : 0;
if($tag->id instanceof ShortTag){
$item = Item::get($tag->id->getValue(), !isset($tag->Damage) ? 0 : $tag->Damage->getValue(), $tag->Count->getValue());
$item = Item::get($tag->id->getValue(), $meta, $count);
}elseif($tag->id instanceof StringTag){ //PC item save format
$item = Item::fromString($tag->id->getValue());
$item->setDamage(!isset($tag->Damage) ? 0 : $tag->Damage->getValue());
$item->setCount($tag->Count->getValue());
$item->setDamage($meta);
$item->setCount($count);
}else{
throw new \InvalidArgumentException("Item CompoundTag ID must be an instance of StringTag or ShortTag, " . get_class($tag->id) . " given");
}

View File

@ -31,6 +31,30 @@ class Binary{
const BIG_ENDIAN = 0x00;
const LITTLE_ENDIAN = 0x01;
public static function signByte(int $value) : int{
return $value << 56 >> 56;
}
public static function unsignByte(int $value) : int{
return $value & 0xff;
}
public static function signShort(int $value) : int{
return $value << 48 >> 48;
}
public function unsignShort(int $value) : int{
return $value & 0xffff;
}
public static function signInt(int $value) : int{
return $value << 32 >> 32;
}
public static function unsignInt(int $value) : int{
return $value & 0xffffffff;
}
private static function checkLength($str, $expect){
assert(($len = strlen($str)) === $expect, "Expected $expect bytes, got $len");
}
@ -73,7 +97,7 @@ class Binary{
* @return int
*/
public static function readSignedByte(string $c) : int{
return ord($c{0}) << 56 >> 56;
return self::signByte(ord($c{0}));
}
/**
@ -106,7 +130,7 @@ class Binary{
*/
public static function readSignedShort(string $str) : int{
self::checkLength($str, 2);
return unpack("n", $str)[1] << 48 >> 48;
return self::signShort(unpack("n", $str)[1]);
}
/**
@ -141,7 +165,7 @@ class Binary{
*/
public static function readSignedLShort(string $str) : int{
self::checkLength($str, 2);
return unpack("v", $str)[1] << 48 >> 48;
return self::signShort(unpack("v", $str)[1]);
}
/**
@ -205,7 +229,7 @@ class Binary{
*/
public static function readInt(string $str) : int{
self::checkLength($str, 4);
return unpack("N", $str)[1] << 32 >> 32;
return self::signInt(unpack("N", $str)[1]);
}
/**
@ -226,7 +250,7 @@ class Binary{
*/
public static function readLInt(string $str) : int{
self::checkLength($str, 4);
return unpack("V", $str)[1] << 32 >> 32;
return self::signInt(unpack("V", $str)[1]);
}
/**