134 for($i = 0, $enumValuesCount = $in->
getUnsignedVarInt(); $i < $enumValuesCount; ++$i){
139 $chainedSubcommandValueNames = [];
141 $chainedSubcommandValueNames[] = $in->
getString();
153 $enums[] = $enum = $this->getEnum($enumValues, $in);
159 if(isset(self::HARDCODED_ENUM_NAMES[$enum->getName()])){
160 $this->hardcodedEnums[] = $enum;
164 $chainedSubCommandData = [];
169 $valueName = $chainedSubcommandValueNames[$in->
getLShort()];
171 $values[] =
new ChainedSubCommandValue($valueName, $valueType);
173 $chainedSubCommandData[] =
new ChainedSubCommandData($name, $values);
177 $this->commandData[] = $this->getCommandData($enums, $postfixes, $chainedSubCommandData, $in);
181 $this->softEnums[] = $this->getSoftEnum($in);
184 $this->initSoftEnumsInCommandData();
187 $this->enumConstraints[] = $this->getEnumConstraint($enums, $enumValues, $in);
309 $valueIndex = $in->getLInt();
310 if(!isset($enumValues[$valueIndex])){
314 if(!isset($enums[$enumIndex])){
317 $enum = $enums[$enumIndex];
318 $valueOffset = array_search($enumValues[$valueIndex], $enum->getValues(),
true);
319 if($valueOffset ===
false){
320 throw new PacketDecodeException(
"Value \"" . $enumValues[$valueIndex] .
"\" does not belong to enum \"" . $enum->getName() .
"\"");
325 $constraintIds[] = $in->
getByte();
328 return new CommandEnumConstraint($enum, $valueOffset, $constraintIds);
353 $name = $in->getString();
357 $aliases = $enums[$in->
getLInt()] ??
null;
359 $chainedSubCommandData = [];
361 $index = $in->getLShort();
362 $chainedSubCommandData[] = $allChainedSubCommandData[$index] ?? throw new PacketDecodeException(
"Unknown chained subcommand data index $index");
366 for($overloadIndex = 0, $overloadCount = $in->
getUnsignedVarInt(); $overloadIndex < $overloadCount; ++$overloadIndex){
368 $isChaining = $in->getBool();
369 for($paramIndex = 0, $paramCount = $in->getUnsignedVarInt(); $paramIndex < $paramCount; ++$paramIndex){
370 $parameter = new CommandParameter();
371 $parameter->paramName = $in->getString();
372 $parameter->paramType = $in->getLInt();
373 $parameter->isOptional = $in->getBool();
374 $parameter->flags = $in->getByte();
376 if(($parameter->paramType & self::ARG_FLAG_ENUM) !== 0){
377 $index = ($parameter->paramType & 0xffff);
378 $parameter->enum = $enums[$index] ?? null;
379 if($parameter->enum === null){
380 throw new PacketDecodeException(
"deserializing $name parameter $parameter->paramName: expected enum at $index, but got none");
382 }elseif(($parameter->paramType & self::ARG_FLAG_POSTFIX) !== 0){
383 $index = ($parameter->paramType & 0xffff);
384 $parameter->postfix = $postfixes[$index] ?? null;
385 if($parameter->postfix === null){
386 throw new PacketDecodeException(
"deserializing $name parameter $parameter->paramName: expected postfix at $index, but got none");
388 }elseif(($parameter->paramType & self::ARG_FLAG_VALID) === 0){
389 throw new PacketDecodeException(
"deserializing $name parameter $parameter->paramName: Invalid parameter type 0x" . dechex($parameter->paramType));
392 $parameters[$paramIndex] = $parameter;
394 $overloads[$overloadIndex] =
new CommandOverload($isChaining, $parameters);
397 return new CommandData($name, $description, $flags, $permission, $aliases, $overloads, $chainedSubCommandData);
407 $out->putString($data->name);
408 $out->putString($data->description);
409 $out->putLShort($data->flags);
410 $out->putByte($data->permission);
412 if($data->aliases !==
null){
413 $out->putLInt($enumIndexes[$data->aliases->getName()] ?? -1);
419 foreach($data->chainedSubCommandData as $chainedSubCommandData){
420 $index = $chainedSubCommandDataIndexes[$chainedSubCommandData->getName()] ??
421 throw new \LogicException(
"Chained subcommand data {$chainedSubCommandData->getName()} does not have an index (this should be impossible)");
422 $out->putLShort($index);
426 foreach($data->overloads as $overload){
427 $out->putBool($overload->isChaining());
428 $out->putUnsignedVarInt(count($overload->getParameters()));
429 foreach($overload->getParameters() as $parameter){
430 $out->putString($parameter->paramName);
432 if($parameter->enum !== null){
433 if($parameter->enum->isSoft()){
434 $type = self::ARG_FLAG_SOFT_ENUM | self::ARG_FLAG_VALID | ($softEnumIndexes[$parameter->enum->getName()] ?? -1);
436 $type = self::ARG_FLAG_ENUM | self::ARG_FLAG_VALID | ($enumIndexes[$parameter->enum->getName()] ?? -1);
438 }elseif($parameter->postfix !== null){
439 if(!isset($postfixIndexes[$parameter->postfix])){
440 throw new \LogicException(
"Postfix '$parameter->postfix' not in postfixes array");
442 $type = self::ARG_FLAG_POSTFIX | $postfixIndexes[$parameter->postfix];
444 $type = $parameter->paramType;
447 $out->putLInt($type);
448 $out->putBool($parameter->isOptional);
449 $out->putByte($parameter->flags);
459 $enumValueIndexes = [];
464 $postfixIndexes = [];
486 $softEnumIndexes = [];
492 $allChainedSubCommandData = [];
497 $chainedSubCommandDataIndexes = [];
503 $chainedSubCommandValueNameIndexes = [];
505 $addEnumFn =
static function(
CommandEnum $enum) use (
506 &$enums, &$softEnums, &$enumIndexes, &$softEnumIndexes, &$enumValueIndexes
508 $enumName = $enum->getName();
511 if(!isset($softEnumIndexes[$enumName])){
512 $softEnums[$softEnumIndexes[$enumName] = count($softEnumIndexes)] = $enum;
515 foreach($enum->getValues() as $str){
516 $enumValueIndexes[$str] = $enumValueIndexes[$str] ?? count($enumValueIndexes);
518 if(!isset($enumIndexes[$enumName])){
519 $enums[$enumIndexes[$enumName] = count($enumIndexes)] = $enum;
523 foreach($this->hardcodedEnums as $enum){
526 foreach($this->softEnums as $enum){
529 foreach($this->commandData as $commandData){
530 if($commandData->aliases !==
null){
531 $addEnumFn($commandData->aliases);
533 foreach($commandData->overloads as $overload){
534 foreach($overload->getParameters() as $parameter){
535 if($parameter->enum !==
null){
536 $addEnumFn($parameter->enum);
539 if($parameter->postfix !==
null){
540 $postfixIndexes[$parameter->postfix] = $postfixIndexes[$parameter->postfix] ?? count($postfixIndexes);
544 foreach($commandData->chainedSubCommandData as $chainedSubCommandData){
545 if(!isset($allChainedSubCommandData[$chainedSubCommandData->getName()])){
546 $allChainedSubCommandData[$chainedSubCommandData->getName()] = $chainedSubCommandData;
547 $chainedSubCommandDataIndexes[$chainedSubCommandData->getName()] = count($chainedSubCommandDataIndexes);
549 foreach($chainedSubCommandData->getValues() as $value){
550 $chainedSubCommandValueNameIndexes[$value->getName()] ??= count($chainedSubCommandValueNameIndexes);
557 foreach($enumValueIndexes as $enumValue => $index){
558 $out->putString((
string) $enumValue);
562 foreach($chainedSubCommandValueNameIndexes as $chainedSubCommandValueName => $index){
563 $out->putString((
string) $chainedSubCommandValueName);
567 foreach($postfixIndexes as $postfix => $index){
568 $out->putString((
string) $postfix);
572 foreach($enums as $enum){
573 $this->putEnum($enum, $enumValueIndexes, $out);
577 foreach($allChainedSubCommandData as $chainedSubCommandData){
578 $out->putString($chainedSubCommandData->getName());
580 foreach($chainedSubCommandData->getValues() as $value){
581 $valueNameIndex = $chainedSubCommandValueNameIndexes[$value->getName()] ??
582 throw new \LogicException(
"Chained subcommand value name index for \"" . $value->getName() .
"\" not found (this should never happen)");
583 $out->putLShort($valueNameIndex);
584 $out->putLShort($value->getType());
589 foreach($this->commandData as $data){
590 $this->putCommandData($data, $enumIndexes, $softEnumIndexes, $postfixIndexes, $chainedSubCommandDataIndexes, $out);
594 foreach($softEnums as $enum){
595 $this->putSoftEnum($enum, $out);
599 foreach($this->enumConstraints as $constraint){
600 $this->putEnumConstraint($constraint, $enumIndexes, $enumValueIndexes, $out);