Add new metadata type vector3f and correct metadata encoding. Result = client crash. TODO: new data values and flags.

This commit is contained in:
Dylan K. Taylor 2016-10-13 13:16:19 +01:00
parent 694c9b151f
commit b6e1a21566
2 changed files with 49 additions and 57 deletions

View File

@ -74,6 +74,7 @@ abstract class Entity extends Location implements Metadatable{
const DATA_TYPE_SLOT = 5; const DATA_TYPE_SLOT = 5;
const DATA_TYPE_POS = 6; const DATA_TYPE_POS = 6;
const DATA_TYPE_LONG = 7; const DATA_TYPE_LONG = 7;
const DATA_TYPE_VECTOR3F = 8;
const DATA_FLAGS = 0; const DATA_FLAGS = 0;
const DATA_AIR = 1; const DATA_AIR = 1;

View File

@ -88,43 +88,45 @@ class Binary{
* @return string * @return string
*/ */
public static function writeMetadata(array $data){ public static function writeMetadata(array $data){
$m = ""; $stream = new BinaryStream();
foreach($data as $bottom => $d){ $stream->putUnsignedVarInt(count($data));
$m .= chr(($d[0] << 5) | ($bottom & 0x1F)); foreach($data as $key => $d){
$stream->putUnsignedVarInt($key); //data key
$stream->putUnsignedVarInt($d[0]); //data type
switch($d[0]){ switch($d[0]){
case Entity::DATA_TYPE_BYTE: case Entity::DATA_TYPE_BYTE:
$m .= self::writeByte($d[1]); $stream->putByte($d[1]);
break; break;
case Entity::DATA_TYPE_SHORT: case Entity::DATA_TYPE_SHORT:
$m .= self::writeLShort($d[1]); $stream->putLShort($d[1]); //SIGNED short!
break; break;
case Entity::DATA_TYPE_INT: case Entity::DATA_TYPE_INT:
$m .= self::writeLInt($d[1]); $stream->putVarInt($d[1]);
break; break;
case Entity::DATA_TYPE_FLOAT: case Entity::DATA_TYPE_FLOAT:
$m .= self::writeLFloat($d[1]); $stream->putLFloat($d[1]);
break; break;
case Entity::DATA_TYPE_STRING: case Entity::DATA_TYPE_STRING:
$m .= self::writeLShort(strlen($d[1])) . $d[1]; $stream->putString($d[1]);
break; break;
case Entity::DATA_TYPE_SLOT: case Entity::DATA_TYPE_SLOT:
$m .= self::writeLShort($d[1][0]); //TODO: change this implementation (use objects)
$m .= self::writeByte($d[1][1]); $stream->putSlot(Item::get($d[1][0], $d[1][2], $d[1][1])); //ID, damage, count
$m .= self::writeLShort($d[1][2]);
break; break;
case Entity::DATA_TYPE_POS: case Entity::DATA_TYPE_POS:
$m .= self::writeLInt($d[1][0]); //TODO: change this implementation (use objects)
$m .= self::writeLInt($d[1][1]); $stream->putBlockCoords($d[1][0], $d[1][1], $d[1][2]); //x, y, z
$m .= self::writeLInt($d[1][2]);
break; break;
case Entity::DATA_TYPE_LONG: case Entity::DATA_TYPE_LONG:
$m .= self::writeLLong($d[1]); $stream->putVarInt($d[1]); //TODO: varint64 support
break; break;
case Entity::DATA_TYPE_VECTOR3F:
//TODO: change this implementation (use objects)
$stream->putVector3f($d[1][0], $d[1][1], $d[1][2]); //x, y, z
} }
} }
$m .= "\x7f";
return $m; return $stream->getBuffer();
} }
/** /**
@ -136,70 +138,59 @@ class Binary{
* @return array * @return array
*/ */
public static function readMetadata($value, $types = false){ public static function readMetadata($value, $types = false){
$offset = 0; $stream = new BinaryStream();
$m = []; $stream->setBuffer($value);
$b = ord($value{$offset}); $count = $stream->getUnsignedVarInt();
++$offset; $data = [];
while($b !== 127 and isset($value{$offset})){ for($i = 0; $i < $count; ++$i){
$bottom = $b & 0x1F; $key = $stream->getUnsignedVarInt();
$type = $b >> 5; $type = $stream->getUnsignedVarInt();
$value = null;
switch($type){ switch($type){
case Entity::DATA_TYPE_BYTE: case Entity::DATA_TYPE_BYTE:
$r = self::readByte($value{$offset}); $value = $stream->getByte();
++$offset;
break; break;
case Entity::DATA_TYPE_SHORT: case Entity::DATA_TYPE_SHORT:
$r = self::readLShort(substr($value, $offset, 2)); $value = $stream->getLShort(true); //signed
$offset += 2;
break; break;
case Entity::DATA_TYPE_INT: case Entity::DATA_TYPE_INT:
$r = self::readLInt(substr($value, $offset, 4)); $value = $stream->getVarInt();
$offset += 4;
break; break;
case Entity::DATA_TYPE_FLOAT: case Entity::DATA_TYPE_FLOAT:
$r = self::readLFloat(substr($value, $offset, 4)); $value = $stream->getLFloat();
$offset += 4;
break; break;
case Entity::DATA_TYPE_STRING: case Entity::DATA_TYPE_STRING:
$len = self::readLShort(substr($value, $offset, 2)); $value = $stream->getString();
$offset += 2;
$r = substr($value, $offset, $len);
$offset += $len;
break; break;
case Entity::DATA_TYPE_SLOT: case Entity::DATA_TYPE_SLOT:
$r = []; //TODO: use objects directly
$r[] = self::readLShort(substr($value, $offset, 2)); $item = $stream->getSlot();
$offset += 2; $value[0] = $item->getId();
$r[] = ord($value{$offset}); $value[1] = $item->getCount();
++$offset; $value[2] = $item->getDamage();
$r[] = self::readLShort(substr($value, $offset, 2));
$offset += 2;
break; break;
case Entity::DATA_TYPE_POS: case Entity::DATA_TYPE_POS:
$r = []; $value = [0, 0, 0];
for($i = 0; $i < 3; ++$i){ $stream->getBlockCoords($value[0], $value[1], $value[2]);
$r[] = self::readLInt(substr($value, $offset, 4));
$offset += 4;
}
break; break;
case Entity::DATA_TYPE_LONG: case Entity::DATA_TYPE_LONG:
$r = self::readLLong(substr($value, $offset, 4)); $value = $stream->getVarInt(); //TODO: varint64 proper support
$offset += 8; break;
case Entity::DATA_TYPE_VECTOR3F:
$value = [0.0, 0.0, 0.0];
$stream->getVector3f($value[0], $value[1], $value[2]);
break; break;
default: default:
return []; $value = [];
} }
if($types === true){ if($types === true){
$m[$bottom] = [$r, $type]; $data[$key] = [$value, $type];
}else{ }else{
$m[$bottom] = $r; $data[$key] = $value;
} }
$b = ord($value{$offset});
++$offset;
} }
return $m; return $data;
} }
/** /**