mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-13 09:19:42 +00:00
Fixed item stack count and effect amplifier overflows, close #1072
This commit is contained in:
parent
1bae973502
commit
e3b3f60c66
@ -60,6 +60,7 @@ use pocketmine\network\mcpe\protocol\SetEntityDataPacket;
|
|||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\plugin\Plugin;
|
use pocketmine\plugin\Plugin;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
|
use pocketmine\utils\Binary;
|
||||||
|
|
||||||
abstract class Entity extends Location implements Metadatable{
|
abstract class Entity extends Location implements Metadatable{
|
||||||
|
|
||||||
@ -773,7 +774,7 @@ abstract class Entity extends Location implements Metadatable{
|
|||||||
foreach($this->effects as $effect){
|
foreach($this->effects as $effect){
|
||||||
$effects[] = new CompoundTag("", [
|
$effects[] = new CompoundTag("", [
|
||||||
"Id" => new ByteTag("Id", $effect->getId()),
|
"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()),
|
"Duration" => new IntTag("Duration", $effect->getDuration()),
|
||||||
"Ambient" => new ByteTag("Ambient", 0),
|
"Ambient" => new ByteTag("Ambient", 0),
|
||||||
"ShowParticles" => new ByteTag("ShowParticles", $effect->isVisible() ? 1 : 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)){
|
if(isset($this->namedtag->ActiveEffects)){
|
||||||
foreach($this->namedtag->ActiveEffects->getValue() as $e){
|
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"]);
|
$effect = Effect::getEffect($e["Id"]);
|
||||||
if($effect === null){
|
if($effect === null){
|
||||||
|
@ -40,6 +40,7 @@ use pocketmine\nbt\tag\StringTag;
|
|||||||
use pocketmine\nbt\tag\Tag;
|
use pocketmine\nbt\tag\Tag;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
|
use pocketmine\utils\Binary;
|
||||||
use pocketmine\utils\Config;
|
use pocketmine\utils\Config;
|
||||||
|
|
||||||
class Item implements ItemIds, \JsonSerializable{
|
class Item implements ItemIds, \JsonSerializable{
|
||||||
@ -1009,7 +1010,7 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
public function nbtSerialize(int $slot = -1, string $tagName = "") : CompoundTag{
|
public function nbtSerialize(int $slot = -1, string $tagName = "") : CompoundTag{
|
||||||
$tag = new CompoundTag($tagName, [
|
$tag = new CompoundTag($tagName, [
|
||||||
"id" => new ShortTag("id", $this->id),
|
"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),
|
"Damage" => new ShortTag("Damage", $this->meta),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -1037,12 +1038,15 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
return Item::get(0);
|
return Item::get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$count = Binary::unsignByte($tag->Count->getValue());
|
||||||
|
$meta = isset($tag->Damage) ? $tag->Damage->getValue() : 0;
|
||||||
|
|
||||||
if($tag->id instanceof ShortTag){
|
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
|
}elseif($tag->id instanceof StringTag){ //PC item save format
|
||||||
$item = Item::fromString($tag->id->getValue());
|
$item = Item::fromString($tag->id->getValue());
|
||||||
$item->setDamage(!isset($tag->Damage) ? 0 : $tag->Damage->getValue());
|
$item->setDamage($meta);
|
||||||
$item->setCount($tag->Count->getValue());
|
$item->setCount($count);
|
||||||
}else{
|
}else{
|
||||||
throw new \InvalidArgumentException("Item CompoundTag ID must be an instance of StringTag or ShortTag, " . get_class($tag->id) . " given");
|
throw new \InvalidArgumentException("Item CompoundTag ID must be an instance of StringTag or ShortTag, " . get_class($tag->id) . " given");
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,30 @@ class Binary{
|
|||||||
const BIG_ENDIAN = 0x00;
|
const BIG_ENDIAN = 0x00;
|
||||||
const LITTLE_ENDIAN = 0x01;
|
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){
|
private static function checkLength($str, $expect){
|
||||||
assert(($len = strlen($str)) === $expect, "Expected $expect bytes, got $len");
|
assert(($len = strlen($str)) === $expect, "Expected $expect bytes, got $len");
|
||||||
}
|
}
|
||||||
@ -73,7 +97,7 @@ class Binary{
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public static function readSignedByte(string $c) : 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{
|
public static function readSignedShort(string $str) : int{
|
||||||
self::checkLength($str, 2);
|
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{
|
public static function readSignedLShort(string $str) : int{
|
||||||
self::checkLength($str, 2);
|
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{
|
public static function readInt(string $str) : int{
|
||||||
self::checkLength($str, 4);
|
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{
|
public static function readLInt(string $str) : int{
|
||||||
self::checkLength($str, 4);
|
self::checkLength($str, 4);
|
||||||
return unpack("V", $str)[1] << 32 >> 32;
|
return self::signInt(unpack("V", $str)[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user