Friendly BC skins (persona not supported)

This commit is contained in:
Stephen 2019-11-10 21:04:38 -05:00
parent 635bb08fb9
commit e2fc7cdf88
5 changed files with 42 additions and 135 deletions

View File

@ -1917,22 +1917,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->uuid = UUID::fromString($packet->clientUUID);
$this->rawUUID = $this->uuid->toBinary();
$animations = [];
foreach($packet->clientData["AnimatedImageData"] as $animatedData){
$animations[] = new SkinAnimation(new SerializedImage($animatedData["ImageHeight"], $animatedData["ImageWidth"], base64_decode($animatedData["Image"])), $animatedData["Type"], $animatedData["Frames"]);
}
$skin = new Skin(
$packet->clientData["SkinId"],
base64_decode($packet->clientData["SkinData"] ?? ""),
base64_decode($packet->clientData["CapeData"] ?? ""),
base64_decode($packet->clientData["SkinResourcePatch"] ?? ""),
new SerializedImage($packet->clientData["SkinImageHeight"], $packet->clientData["SkinImageWidth"], base64_decode($packet->clientData["SkinData"] ?? "")),
$animations,
new SerializedImage($packet->clientData["CapeImageHeight"], $packet->clientData["CapeImageWidth"], base64_decode($packet->clientData["CapeData"] ?? "")),
base64_decode($packet->clientData["SkinGeometryData"] ?? ""),
base64_decode($packet->clientData["AnimationData"] ?? ""),
$packet->clientData["PremiumSkin"] ?? false,
$packet->clientData["PersonaSkin"] ?? false,
$packet->clientData["CapeOnClassicSkin"] ?? false,
$packet->clientData["CapeId"] ?? ""
base64_decode($packet->clientData["SkinGeometryData"] ?? "")
);
if(!$skin->isValid()){

View File

@ -120,16 +120,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
protected static function deserializeSkinNBT(CompoundTag $skinTag) : Skin{
$skin = new Skin(
$skinTag->getString("Name"),
$skinTag->getString("SkinResourcePatch", ""),
new SerializedImage($skinTag->getInt("SkinImageHeight"), $skinTag->getInt("SkinImageWidth"), $skinTag->getByteArray("Data")),
"", //TODO: animations
new SerializedImage($skinTag->getInt("CapeImageHeight"), $skinTag->getInt("CapeImageWidth"), $skinTag->getByteArray("CapeData")),
$skinTag->getByteArray("GeometryData", ""),
$skinTag->getByteArray("AnimationData", ""),
$skinTag->getByte("PremiumSkin") === 1,
$skinTag->getByte("PersonaSkin") === 1,
$skinTag->getByte("CapeOnClassic") === 1,
$skinTag->getString("CapeId", "")
$skinTag->hasTag("Data", StringTag::class) ? $skinTag->getString("Data") : $skinTag->getByteArray("Data"), //old data (this used to be saved as a StringTag in older versions of PM)
$skinTag->getByteArray("CapeData", ""),
$skinTag->getString("GeometryName", ""),
$skinTag->getByteArray("GeometryData", "")
);
$skin->validate();
return $skin;
@ -839,19 +833,10 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
if($this->skin !== null){
$this->namedtag->setTag(new CompoundTag("Skin", [
new StringTag("Name", $this->skin->getSkinId()),
new StringTag("SkinResourcePatch", $this->skin->getSkinResourcePatch()),
new ByteArrayTag("Data", $this->skin->getSkinData()->getData()),
new IntTag("SkinImageHeight", $this->skin->getSkinData()->getHeight()),
new IntTag("SkinImageWidth", $this->skin->getSkinData()->getWidth()),
new ByteArrayTag("CapeData", $this->skin->getCapeData()->getData()),
new IntTag("CapeImageHeight", $this->skin->getCapeData()->getHeight()),
new IntTag("CapeImageWidth", $this->skin->getCapeData()->getWidth()),
new ByteArrayTag("GeometryData", $this->skin->getGeometryData()),
new ByteArrayTag("AnimationData", $this->skin->getAnimationData()),
new ByteTag("PremiumSkin", $this->skin->getPremium() ? 1 : 0),
new ByteTag("PersonaSkin", $this->skin->getPersona() ? 1 : 0),
new ByteTag("CapeOnClassic", $this->skin->getCapeOnClassic() ? 1 : 0),
new StringTag("CapeId", $this->skin->getCapeId())
new ByteArrayTag("Data", $this->skin->getSkinData()),
new ByteArrayTag("CapeData", $this->skin->getCapeData()),
new StringTag("GeometryName", $this->skin->getGeometryName()),
new ByteArrayTag("GeometryData", $this->skin->getGeometryData())
]));
}
}

View File

@ -41,38 +41,20 @@ class Skin{
/** @var string */
private $skinId;
/** @var string */
private $skinResourcePatch;
/** @var SerializedImage */
private $skinData;
/** @var SkinAnimation[] */
private $animations = [];
/** @var SerializedImage */
/** @var string */
private $capeData;
/** @var string */
private $geometryName;
/** @var string */
private $geometryData;
/** @var string */
private $animationData;
/** @var bool */
private $premium;
/** @var bool */
private $persona;
/** @var bool */
private $capeOnClassic;
/** @var string */
private $capeId;
public function __construct(string $skinId, string $skinResourcePatch, SerializedImage $skinData, array $animations = [], SerializedImage $capeData = null, string $geometryData = "", string $animationData = "", bool $premium = false, bool $persona = false, bool $capeOnClassic = false, string $capeId = ""){
public function __construct(string $skinId, string $skinData, string $capeData = "", string $geometryName = "", string $geometryData = ""){
$this->skinId = $skinId;
$this->skinResourcePatch = $skinResourcePatch;
$this->skinData = $skinData;
$this->animations = $animations;
$this->capeData = $capeData;
$this->geometryName = $geometryName;
$this->geometryData = $geometryData;
$this->animationData = $animationData;
$this->premium = $premium;
$this->persona = $persona;
$this->capeOnClassic = $capeOnClassic;
$this->capeId = $capeId;
}
public static function convertToLegacyName(string $name) : string{
@ -99,14 +81,13 @@ class Skin{
if($this->skinId === ""){
throw new \InvalidArgumentException("Skin ID must not be empty");
}
//Broken with Persona skins
/*$len = strlen($this->skinData->getData());
$len = strlen($this->skinData);
if(!in_array($len, self::ACCEPTED_SKIN_SIZES, true)){
throw new \InvalidArgumentException("Invalid skin data size $len bytes (allowed sizes: " . implode(", ", self::ACCEPTED_SKIN_SIZES) . ")");
}
if($this->capeData->getData() !== "" and strlen($this->capeData->getData()) !== 8192){
throw new \InvalidArgumentException("Invalid cape data size " . strlen($this->capeData->getData()) . " bytes (must be exactly 8192 bytes)");
}*/
if($this->capeData !== "" and strlen($this->capeData) !== 8192){
throw new \InvalidArgumentException("Invalid cape data size " . strlen($this->capeData) . " bytes (must be exactly 8192 bytes)");
}
//TODO: validate geometry
}
@ -120,29 +101,22 @@ class Skin{
/**
* @return string
*/
public function getSkinResourcePatch() : string{
return $this->skinResourcePatch;
}
/**
* @return SerializedImage
*/
public function getSkinData() : SerializedImage{
public function getSkinData() : string{
return $this->skinData;
}
/**
* @return SkinAnimation[]
* @return string
*/
public function getAnimations() : array{
return $this->animations;
public function getCapeData() : string{
return $this->capeData;
}
/**
* @return SerializedImage
* @return string
*/
public function getCapeData() : SerializedImage{
return $this->capeData ?? new SerializedImage(0, 0, "");
public function getGeometryName() : string{
return $this->geometryName;
}
/**
@ -152,48 +126,6 @@ class Skin{
return $this->geometryData;
}
/**
* @return string
*/
public function getAnimationData() : string{
return $this->animationData;
}
/**
* @return bool
*/
public function getPremium() : bool{
return $this->premium;
}
/**
* @return bool
*/
public function getPersona() : bool{
return $this->persona;
}
/**
* @return bool
*/
public function getCapeOnClassic() : bool{
return $this->capeOnClassic;
}
/**
* @return string
*/
public function getCapeId() : string{
return $this->capeId;
}
/**
* @return string
*/
public function getFullSkinId() : string{
return $this->skinId . "_" . $this->capeId;
}
/**
* Hack to cut down on network overhead due to skins, by un-pretty-printing geometry JSON.
*

View File

@ -97,7 +97,7 @@ class FloatingTextParticle extends Particle{
$add = new PlayerListPacket();
$add->type = PlayerListPacket::TYPE_ADD;
$add->entries = [PlayerListEntry::createAdditionEntry($uuid, $this->entityId, $name, new Skin("Standard_Custom", Skin::convertToLegacyName("geometry.humanoid.custom"), SerializedImage::fromLegacy(str_repeat("\x00", 8192))))];
$add->entries = [PlayerListEntry::createAdditionEntry($uuid, $this->entityId, $name, new Skin("Standard_Custom", str_repeat("\x00", 8192), "", Skin::convertToLegacyName("geometry.humanoid.custom"), ""))];
$p[] = $add;
$pk = new AddPlayerPacket();

View File

@ -95,29 +95,29 @@ class NetworkBinaryStream extends BinaryStream{
$capeId = $this->getString();
$fullSkinId = $this->getString();
return new Skin(
$skinId, $skinResourcePatch, $skinData, $animations, $capeData, $geometryData, $animationData, $premium, $persona, $capeOnClassic, $capeId
);
return new Skin($skinId, $skinData->getData(), $capeData->getData(), $skinResourcePatch, $geometryData);
}
public function putSkin(Skin $skin){
$this->putString($skin->getSkinId());
$this->putString($skin->getSkinResourcePatch());
$this->putImage($skin->getSkinData());
$this->putLInt(count($skin->getAnimations()));
foreach($skin->getAnimations() as $animation){
$this->putString($skin->getGeometryName()); //resource patch
$this->putImage(SerializedImage::fromLegacy($skin->getSkinData()));
/** @var SkinAnimation[] $animations */
$animations = [];
$this->putLInt(count($animations));
foreach($animations as $animation){
$this->putImage($animation->getImage());
$this->putLInt($animation->getType());
$this->putLFloat($animation->getFrames());
}
$this->putImage($skin->getCapeData());
$this->putImage(new SerializedImage(0, 0, $skin->getCapeData()));
$this->putString($skin->getGeometryData());
$this->putString($skin->getAnimationData());
$this->putBool($skin->getPremium());
$this->putBool($skin->getPersona());
$this->putBool($skin->getCapeOnClassic());
$this->putString($skin->getCapeId());
$this->putString($skin->getFullSkinId());
$this->putString(""); //animation data
$this->putBool(false); //isPremium
$this->putBool(false); //isPersona
$this->putBool(false); //isCapeOnClassic
$this->putString(""); //capeId
$this->putString(""); //fullskinId
}
public function getImage() : SerializedImage{