Merge commit '82d9e481d2a0a389fbbc6dfd3672fc366127febc'

This commit is contained in:
Dylan K. Taylor
2019-12-11 23:06:35 +00:00
58 changed files with 2030 additions and 296 deletions

View File

@ -29,6 +29,7 @@ use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\handler\PacketHandler;
use pocketmine\network\mcpe\protocol\types\command\CommandData;
use pocketmine\network\mcpe\protocol\types\command\CommandEnum;
use pocketmine\network\mcpe\protocol\types\command\CommandEnumConstraint;
use pocketmine\network\mcpe\protocol\types\command\CommandParameter;
use pocketmine\utils\BinaryDataException;
use function count;
@ -57,17 +58,17 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
public const ARG_TYPE_FILEPATH = 0x0e;
public const ARG_TYPE_STRING = 0x1b;
public const ARG_TYPE_STRING = 0x1d;
public const ARG_TYPE_POSITION = 0x1d;
public const ARG_TYPE_POSITION = 0x25;
public const ARG_TYPE_MESSAGE = 0x20;
public const ARG_TYPE_MESSAGE = 0x29;
public const ARG_TYPE_RAWTEXT = 0x22;
public const ARG_TYPE_RAWTEXT = 0x2b;
public const ARG_TYPE_JSON = 0x25;
public const ARG_TYPE_JSON = 0x2f;
public const ARG_TYPE_COMMAND = 0x2c;
public const ARG_TYPE_COMMAND = 0x36;
/**
* Enums are a little different: they are composed as follows:
@ -80,12 +81,23 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
*/
public const ARG_FLAG_POSTFIX = 0x1000000;
public const HARDCODED_ENUM_NAMES = [
"CommandName" => true
];
/**
* @var CommandData[]
* List of command data, including name, description, alias indexes and parameters.
*/
public $commandData = [];
/**
* @var CommandEnum[]
* List of enums which aren't directly referenced by any vanilla command.
* This is used for the `CommandName` enum, which is a magic enum used by the `command` argument type.
*/
public $hardcodedEnums = [];
/**
* @var CommandEnum[]
* List of dynamic command enums, also referred to as "soft" enums. These can by dynamically updated mid-game
@ -93,6 +105,12 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
*/
public $softEnums = [];
/**
* @var CommandEnumConstraint[]
* List of constraints for enum members. Used to constrain gamerules that can bechanged in nocheats mode and more.
*/
public $enumConstraints = [];
protected function decodePayload() : void{
/** @var string[] $enumValues */
$enumValues = [];
@ -109,7 +127,10 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
/** @var CommandEnum[] $enums */
$enums = [];
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$enums[] = $this->getEnum($enumValues);
$enums[] = $enum = $this->getEnum($enumValues);
if(isset(self::HARDCODED_ENUM_NAMES[$enum->getName()])){
$this->hardcodedEnums[] = $enum;
}
}
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
@ -119,6 +140,10 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$this->softEnums[] = $this->getSoftEnum();
}
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$this->enumConstraints[] = $this->getEnumConstraint($enums, $enumValues);
}
}
/**
@ -217,6 +242,52 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
}
}
/**
* @param CommandEnum[] $enums
* @param string[] $enumValues
*
* @return CommandEnumConstraint
* @throws BadPacketException
* @throws BinaryDataException
*/
protected function getEnumConstraint(array $enums, array $enumValues) : CommandEnumConstraint{
//wtf, what was wrong with an offset inside the enum? :(
$valueIndex = $this->getLInt();
if(!isset($enumValues[$valueIndex])){
throw new BadPacketException("Enum constraint refers to unknown enum value index $valueIndex");
}
$enumIndex = $this->getLInt();
if(!isset($enums[$enumIndex])){
throw new BadPacketException("Enum constraint refers to unknown enum index $enumIndex");
}
$enum = $enums[$enumIndex];
$valueOffset = array_search($enumValues[$valueIndex], $enum->getValues(), true);
if($valueOffset === false){
throw new BadPacketException("Value \"" . $enumValues[$valueIndex] . "\" does not belong to enum \"" . $enum->getName() . "\"");
}
$constraintIds = [];
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$constraintIds[] = $this->getByte();
}
return new CommandEnumConstraint($enum, $valueOffset, $constraintIds);
}
/**
* @param CommandEnumConstraint $constraint
* @param int[] $enumIndexes string enum name -> int index
* @param int[] $enumValueIndexes string value -> int index
*/
protected function putEnumConstraint(CommandEnumConstraint $constraint, array $enumIndexes, array $enumValueIndexes) : void{
$this->putLInt($enumValueIndexes[$constraint->getAffectedValue()]);
$this->putLInt($enumIndexes[$constraint->getEnum()->getName()]);
$this->putUnsignedVarInt(count($constraint->getConstraints()));
foreach($constraint->getConstraints() as $v){
$this->putByte($v);
}
}
/**
* @param CommandEnum[] $enums
* @param string[] $postfixes
@ -365,6 +436,9 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
$enumValueIndexes[$str] = $enumValueIndexes[$str] ?? count($enumValueIndexes); //latest index
}
};
foreach($this->hardcodedEnums as $enum){
$addEnumFn($enum);
}
foreach($this->commandData as $commandData){
if($commandData->aliases !== null){
$addEnumFn($commandData->aliases);
@ -408,6 +482,11 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
foreach($this->softEnums as $enum){
$this->putSoftEnum($enum);
}
$this->putUnsignedVarInt(count($this->enumConstraints));
foreach($this->enumConstraints as $constraint){
$this->putEnumConstraint($constraint, $enumIndexes, $enumValueIndexes);
}
}
public function handle(PacketHandler $handler) : bool{