pmmp / PocketMine-MP

A server software for Minecraft: Bedrock Edition in PHP
https://pmmp.io
GNU Lesser General Public License v3.0
3.28k stars 1.56k forks source link

Provide a way to bypass accepted skin sizes #3141

Closed MCPE-PC closed 5 years ago

MCPE-PC commented 5 years ago

Description

I would suggest one of these

Justification

When I tried to set the skin of an entity, an exception [Server thread/CRITICAL]: InvalidArgumentException: "Invalid skin data size 32769 bytes (allowed sizes: 8192, 16384, 65536)" (EXCEPTION) occurred because the skin size changed due to the rotation of the geometry. I needed a way to pass the skin size limitation.

Alternative methods

/*

declare(strict_types=1);

namespace your\plugin;

use function implode; use function in_array; use function json_decode; use function json_encode; use function json_last_error_msg; use function strlen;

class DynamicSkin { protected static $acceptedSkinSizes = [ 64 32 4, 64 64 4, 128 128 4 ];

/** @var string */
private $skinId;
/** @var string */
private $skinData;
/** @var string */
private $capeData;
/** @var string */
private $geometryName;
/** @var string */
private $geometryData;

public function __construct(string $skinId, string $skinData, string $capeData = "", string $geometryName = "", string $geometryData = ""){
    if($skinId === ""){
        throw new \InvalidArgumentException("Skin ID must not be empty");
    }
    $len = strlen($skinData);
    if(!in_array($len, self::$acceptedSkinSizes, true)){
        throw new \InvalidArgumentException("Invalid skin data size $len bytes (allowed sizes: " . implode(", ", self::$acceptedSkinSizes) . ")");
    }
    if($capeData !== "" and strlen($capeData) !== 8192){
        throw new \InvalidArgumentException("Invalid cape data size " . strlen($capeData) . " bytes (must be exactly 8192 bytes)");
    }

    if($geometryData !== ""){
        $decodedGeometry = json_decode($geometryData);
        if($decodedGeometry === false){
            throw new \InvalidArgumentException("Invalid geometry data (" . json_last_error_msg() . ")");
        }

        /*
         * Hack to cut down on network overhead due to skins, by un-pretty-printing geometry JSON.
         *
         * Mojang, some stupid reason, send every single model for every single skin in the selected skin-pack.
         * Not only that, they are pretty-printed.
         * TODO: find out what model crap can be safely dropped from the packet (unless it gets fixed first)
         */
        $geometryData = json_encode($decodedGeometry);
    }

    $this->skinId = $skinId;
    $this->skinData = $skinData;
    $this->capeData = $capeData;
    $this->geometryName = $geometryName;
    $this->geometryData = $geometryData;
}

public static function addAcceptedSkinSize(int $byte) : bool {
    if (in_array($byte, self::$acceptedSkinSizes)) {
        return false;
    }

    self::$acceptedSkinSizes[] = $byte;
    return true;
}

/**
 * @return string
 */
public function getSkinId() : string{
    return $this->skinId;
}

/**
 * @return string
 */
public function getSkinData() : string{
    return $this->skinData;
}

/**
 * @return string
 */
public function getCapeData() : string{
    return $this->capeData;
}

/**
 * @return string
 */
public function getGeometryName() : string{
    return $this->geometryName;
}

/**
 * @return string
 */
public function getGeometryData() : string{
    return $this->geometryData;
}

}


And a problem happens when a player joins after the skin has changed
`[Server thread/CRITICAL]: TypeError: "Argument 4 passed to pocketmine\network\mcpe\protocol\types\PlayerListEntry::createAdditionEntry() must be an instance of pocketmine\entity\Skin, instance of your\plugin\DynamicSkin given...`
 - 2. Modify PMMP code directly
I would simply remove the final keyword of Skin class and extend it on the plugin
dktapps commented 5 years ago

These sizes are the only sizes accepted by the game, regardless of geometry.