Pocketmine-mp: Provide a way to bypass accepted skin sizes

Created on 6 Oct 2019  路  1Comment  路  Source: pmmp/PocketMine-MP

Description

I would suggest one of these

  • Making Skin class not final
  • Changing ACCEPTED_SKIN_SIZES into a variable
  • Provide a way to bypass accepted skin sizes

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


    1. Define a hacky class

      I tried to make a clone of Skin class like:

<?php

/*
 * @author PocketMine Team
 * @link http://www.pocketmine.net/
 */

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...


    1. Modify PMMP code directly

      I would simply remove the final keyword of Skin class and extend it on the plugin

Invalid

Most helpful comment

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

>All comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JoshuaACasey picture JoshuaACasey  路  3Comments

Hugheth picture Hugheth  路  3Comments

beetree picture beetree  路  3Comments

dktapps picture dktapps  路  3Comments

SuperAdam47 picture SuperAdam47  路  3Comments