mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-06 09:56:06 +00:00
Merge commit '82d9e481d2a0a389fbbc6dfd3672fc366127febc'
This commit is contained in:
@ -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{
|
||||
|
Reference in New Issue
Block a user