46    private array $upgradeSchemas = [];
 
   48    private int $outputVersion = 0;
 
   55        foreach($upgradeSchemas as $schema){
 
   56            $this->addSchema($schema);
 
 
   61        $schemaId = $schema->getSchemaId();
 
   63        if(isset($this->upgradeSchemas[$versionId][$schemaId])){
 
   64            throw new \InvalidArgumentException(
"Cannot add two schemas with the same schema ID and version ID");
 
   68        $this->upgradeSchemas[$versionId][$schemaId] = $schema;
 
   70        ksort($this->upgradeSchemas, SORT_NUMERIC);
 
   71        ksort($this->upgradeSchemas[$versionId], SORT_NUMERIC);
 
   73        $this->outputVersion = max($this->outputVersion, $schema->
getVersionId());
 
   76    public function upgrade(BlockStateData $blockStateData) : BlockStateData{
 
   77        $version = $blockStateData->getVersion();
 
   78        $name = $blockStateData->getName();
 
   79        $states = $blockStateData->getStates();
 
   80        foreach($this->upgradeSchemas as $resultVersion => $schemaList){
 
   91            if($version > $resultVersion || (count($schemaList) === 1 && $version === $resultVersion)){
 
   95            foreach($schemaList as $schema){
 
   96                [$name, $states] = $this->applySchema($schema, $name, $states);
 
  100        return new BlockStateData($name, $states, $this->outputVersion);
 
  110    private function applySchema(BlockStateUpgradeSchema $schema, 
string $oldName, array $states) : array{
 
  111        $remapped = $this->applyStateRemapped($schema, $oldName, $states);
 
  112        if($remapped !== 
null){
 
  116        if(isset($schema->renamedIds[$oldName]) && isset($schema->flattenedProperties[$oldName])){
 
  118            throw new AssumptionFailedError(
"Both renamedIds and flattenedProperties are set for the same block ID \"$oldName\" - don't know what to do");
 
  120        if(isset($schema->renamedIds[$oldName])){
 
  121            $newName = $schema->renamedIds[$oldName];
 
  122        }elseif(isset($schema->flattenedProperties[$oldName])){
 
  123            [$newName, $states] = $this->applyPropertyFlattened($schema->flattenedProperties[$oldName], $oldName, $states);
 
  128        $states = $this->applyPropertyAdded($schema, $oldName, $states);
 
  129        $states = $this->applyPropertyRemoved($schema, $oldName, $states);
 
  130        $states = $this->applyPropertyRenamedOrValueChanged($schema, $oldName, $states);
 
  131        $states = $this->applyPropertyValueChanged($schema, $oldName, $states);
 
  133        return [$newName, $states];
 
  143    private function applyStateRemapped(BlockStateUpgradeSchema $schema, 
string $oldName, array $oldState) : ?array{
 
  144        if(isset($schema->remappedStates[$oldName])){
 
  145            foreach($schema->remappedStates[$oldName] as $remap){
 
  146                if(count($remap->oldState) > count($oldState)){
 
  150                foreach(Utils::stringifyKeys($remap->oldState) as $k => $v){
 
  151                    if(!isset($oldState[$k]) || !$oldState[$k]->equals($v)){
 
  156                if(is_string($remap->newName)){
 
  157                    $newName = $remap->newName;
 
  160                    [$newName, ] = $this->applyPropertyFlattened($remap->newName, $oldName, $oldState);
 
  163                $newState = $remap->newState;
 
  164                foreach($remap->copiedState as $stateName){
 
  165                    if(isset($oldState[$stateName])){
 
  166                        $newState[$stateName] = $oldState[$stateName];
 
  170                return [$newName, $newState];
 
  184    private function applyPropertyAdded(BlockStateUpgradeSchema $schema, 
string $oldName, array $states) : array{
 
  185        if(isset($schema->addedProperties[$oldName])){
 
  186            foreach(Utils::stringifyKeys($schema->addedProperties[$oldName]) as $propertyName => $value){
 
  187                if(!isset($states[$propertyName])){
 
  188                    $states[$propertyName] = $value;
 
  203    private function applyPropertyRemoved(BlockStateUpgradeSchema $schema, 
string $oldName, array $states) : array{
 
  204        if(isset($schema->removedProperties[$oldName])){
 
  205            foreach($schema->removedProperties[$oldName] as $propertyName){
 
  206                unset($states[$propertyName]);
 
  213    private function locateNewPropertyValue(BlockStateUpgradeSchema $schema, 
string $oldName, 
string $oldPropertyName, Tag $oldValue) : Tag{
 
  214        if(isset($schema->remappedPropertyValues[$oldName][$oldPropertyName])){
 
  215            foreach($schema->remappedPropertyValues[$oldName][$oldPropertyName] as $mappedPair){
 
  216                if($mappedPair->old->equals($oldValue)){
 
  217                    return $mappedPair->new;
 
  232    private function applyPropertyRenamedOrValueChanged(BlockStateUpgradeSchema $schema, 
string $oldName, array $states) : array{
 
  233        if(isset($schema->renamedProperties[$oldName])){
 
  234            foreach(Utils::stringifyKeys($schema->renamedProperties[$oldName]) as $oldPropertyName => $newPropertyName){
 
  235                $oldValue = $states[$oldPropertyName] ?? null;
 
  236                if($oldValue !== null){
 
  237                    unset($states[$oldPropertyName]);
 
  242                    $states[$newPropertyName] = $this->locateNewPropertyValue($schema, $oldName, $oldPropertyName, $oldValue);
 
  257    private function applyPropertyValueChanged(BlockStateUpgradeSchema $schema, 
string $oldName, array $states) : array{
 
  258        if(isset($schema->remappedPropertyValues[$oldName])){
 
  259            foreach(Utils::stringifyKeys($schema->remappedPropertyValues[$oldName]) as $oldPropertyName => $remappedValues){
 
  260                $oldValue = $states[$oldPropertyName] ?? null;
 
  261                if($oldValue !== null){
 
  262                    $newValue = $this->locateNewPropertyValue($schema, $oldName, $oldPropertyName, $oldValue);
 
  263                    $states[$oldPropertyName] = $newValue;
 
  278    private function applyPropertyFlattened(BlockStateUpgradeSchemaFlattenInfo $flattenInfo, 
string $oldName, array $states) : array{
 
  279        $flattenedValue = $states[$flattenInfo->flattenedProperty] ?? null;
 
  280        $expectedType = $flattenInfo->flattenedPropertyType;
 
  281        if($expectedType === 
null){
 
  283            throw new AssumptionFailedError(
"We never give this null");
 
  285        if(!$flattenedValue instanceof $expectedType){
 
  287            return [$oldName, $states];
 
  289        $embedKey = match(get_class($flattenedValue)){
 
  290            StringTag::class => $flattenedValue->getValue(),
 
  291            ByteTag::class => (string) $flattenedValue->getValue(),
 
  292            IntTag::class => (string) $flattenedValue->getValue(),
 
  294            default => 
throw new AssumptionFailedError(
"flattenedPropertyType should be one of these three types, but have " . get_class($flattenedValue)),
 
  296        $embedValue = $flattenInfo->flattenedValueRemaps[$embedKey] ?? $embedKey;
 
  297        $newName = sprintf(
"%s%s%s", $flattenInfo->prefix, $embedValue, $flattenInfo->suffix);
 
  298        unset($states[$flattenInfo->flattenedProperty]);
 
  300        return [$newName, $states];