/** * Get Nether Wart at the given stage of growth. * * @param int $note Note the block should play (0-15) * * @throws \Exception */ public function __construct($note) { $this->setBlockIDAndDataFor(Ref::NOTE_BLOCK); $this->checkValue($note, 0, 15, 'Invalid note for note block'); $this->initEntityData('Music'); $this->entityData->addChild(\Nbt\Tag::tagByte('note', $note)); }
/** * A flower pot, optionally containing a flower * * @param \MME\Block $contains The flower the block contains */ public function __construct($contains = null) { // This is going to define the plant in the tile entity data // - which is to be done... $this->setBlockIDAndDataFor(Ref::FLOWER_POT); $this->initEntityData('FlowerPot'); $this->entityData->addChild(\Nbt\Tag::tagString('Item', $contains ? Names::$list[$contains->ref] : '')); $this->entityData->addChild(\Nbt\Tag::tagInt('Data', $contains ? $contains->data : 0)); }
/** * Get a furnace facing in the given direction. * * @param int $blockRef Which furnace to use * @param int $facing The direction it faces; one of the class constants * @param \MME\Stack|null $input Data for the stack in the input slot * @param \MME\Stack|null $fuel Data for the stack in the fuel slot * @param \MME\Stack|null $output Data for the stack in the output slot * @param int $burnTime Time left for fuel to burn * @param int $cookTime Time left for item to finish cooking * @param int $cookTimeTotal Total time for item to cook * * @throws \Exception */ public function __construct($blockRef, $facing, $input = null, $fuel = null, $output = null, $burnTime = 0, $cookTime = 0, $cookTimeTotal = 0) { $this->checkBlock($blockRef, Ref::getStartsWith('FURNACE')); $this->checkDataRefValidAll($facing, 'Invalid facing reference for furnace'); $this->setBlockData($facing); $this->initEntityData('Furnace'); $this->addItemsForSlots([0 => $input, 1 => $fuel, 2 => $output]); $this->entityData->addChild(\Nbt\Tag::tagShort('BurnTime', $burnTime)); $this->entityData->addChild(\Nbt\Tag::tagShort('CookTime', $cookTime)); $this->entityData->addChild(\Nbt\Tag::tagShort('CookTimeTotal', $cookTimeTotal)); }
/** * Get a comparator with the given settings. * * @param int $facing Direction the comparator is facing; one of the FACING_ class constants * @param int $mode Which mode the comparator is in; one of the MODE_ class constants * @param int $powered Either RedstoneComparator::UNPOWERED or RedstoneComparator::POWERED# * @param int $outputSignal Strength of output signal * * @throws \Exception */ public function __construct($facing, $mode, $powered = self::UNPOWERED, $outputSignal = 0) { $this->setBlockIDFor(Ref::REDSTONE_COMPARATOR); $this->checkDataRefValidStartsWith($facing, 'FACING_', 'Invalid facing status for comparator'); $this->checkDataRefValidStartsWith($mode, 'MODE_', 'Invalid mode for comparator'); $this->checkInList($powered, [self::UNPOWERED, self::POWERED], 'Invalid powered setting for comparator'); $this->setBlockData($facing | $mode | $powered); $this->initEntityData('Comparator'); $this->checkValue($outputSignal, 0, 15, 'Invalid Output Signal Stregth for comparator'); $this->entityData->addChild(\Nbt\Tag::tagInt('OutputSignal', $outputSignal)); }
/** * Get a hopper, with the output in the given direction. * * @param int $output Output direction; one of the OUTPUT_ class constants * @param \MME\Stack[] $items Items in the dropper, with pre-set slots (0-8). * 0 is the top-left corner. * @param int $active [Optional] Either Hopper:INACTIVE or Hopper::ACTIVE * @param string $customName Custom name for the chest, appears in GUI * @param string $lock Lock the dropper so it can only be opened if the player * is holding an item whose name matches this string * @param int $transferCooldown Time to next transfer in game ticks. * * @throws \Exception */ public function __construct($output, $items = [], $active = self::ACTIVE, $customName = null, $lock = null, $transferCooldown = 0) { $this->setBlockIDFor(Ref::HOPPER); $this->checkDataRefValidStartsWith($output, 'OUTPUT_', 'Invalid output reference for hopper'); $this->checkInList($active, [self::ACTIVE, self::DISABLED], 'Invalid active reference for hopper'); $this->setBlockData($output | $active); $this->initEntityData('Hopper'); $this->addItemStacks($items); $this->setCustomName($customName); $this->setLock($lock); $this->entityData->addChild(\Nbt\Tag::tagInt('TransferCooldown', $transferCooldown)); }
/** * Add a command block. * * @param string $command Command that the block will run * @param int $trackOutput [optional] Either CommandBlock::TRACK_OUTPUT or CommandBlock::NO_TRACK_OUTPUT * @param \Nbt\Node|null $commandStats [optional] Command stats compound tag, if required. * @param string|null $customName [optional] * @param string|null $lock [optional] * * @throws \Exception */ public function __construct($command, $trackOutput = self::TRACK_OUTPUT, $commandStats = null, $customName = null, $lock = null) { $this->setBlockIDAndDataFor(Ref::COMMAND_BLOCK); $this->initEntityData('Control'); $this->entityData->addChild(\Nbt\Tag::tagString('Command', $command)); $this->entityData->addChild(\Nbt\Tag::tagByte('TrackOutput', $trackOutput)); $this->setCustomName($customName); $this->setLock($lock); if ($commandStats !== null) { $this->entityData->addChild($commandStats); } }
/** * Add a list of item stacks to the 'Items' list tag. * * @param \MME\Stack[] $items */ protected function addItemStacks($items) { if (count($items)) { $payload = \Nbt\Tag::TAG_COMPOUND; } else { $payload = \Nbt\Tag::TAG_END; } $itemsList = \Nbt\Tag::tagList('Items', $payload, []); $this->entityData->addChild($itemsList); foreach ($items as $item) { $itemsList->addChild($item->node); } }
/** * Check the orientation of the mob head based on the placement. * * @param int $placement * @param int $orientation */ protected function checkOrientation($placement, $orientation) { $rotValue = 0; switch ($placement) { case self::PLACE_WALL: $this->checkWallOrientation($orientation); break; case self::PLACE_FLOOR: $this->setBlockData(1); $rotValue = $orientation; break; } $this->entityData->addChild(\Nbt\Tag::tagByte('Rot', $rotValue)); }
/** * Set the patterns for the banner. * * @param array $patterns */ protected function bannerPatterns($patterns) { if (count($patterns)) { // Set up the pattern list $patternList = \Nbt\Tag::tagList('Patterns', \Nbt\Tag::TAG_COMPOUND, []); $this->entityData->addChild($patternList); foreach ($patterns as $pattern) { // Check the pattern details are valid $this->checkDataRefValidStartsWith($pattern['color'], 'COLOR_', 'Invalid base color for banner pattern'); $this->checkDataRefValidStartsWith($pattern['pattern'], 'PATTERN_', 'Invalid pattern reference for banner pattern'); // Add the pattern to the list $patternList->addChild(\Nbt\Tag::tagCompound('', [\Nbt\Tag::tagInt('Color', $this->bannerConvertColor($pattern['color'])), \Nbt\Tag::tagString('Pattern', $pattern['pattern'])])); } } }
/** * Create a mob spawner. There's no checking of the information passed yet. * I don't know the valid values, etc; proper error checking is still to come. * Test your creations well! * * @param \Nbt\Node|null $spawnPotentials List of potential spawns * @param string $entityID Entity name to spawn * @param \Nbt\Node|null $spawnData Data to pass to the spawned mobs * @param int $spawnCount Number of mobs to attempt to spawn * @param int $spawnRange Radius of the spawn range * @param int $delay Ticks until next spawn * @param int $minSpawnDelay Minimum random delay to the next spawn * @param int $maxSpawnDelay Maximum random delay to the next spawn * @param int $maxNearbyEntities Can override the max number of entities nearby * @param int $requiredPlayerRange Override the activation radius * * @throws \Exception */ public function __construct($spawnPotentials, $entityID, $spawnData, $spawnCount, $spawnRange, $delay, $minSpawnDelay, $maxSpawnDelay, $maxNearbyEntities, $requiredPlayerRange) { $this->setBlockIDAndDataFor(Ref::MOB_SPAWNER); $this->initEntityData('MobSpawner'); if ($spawnPotentials) { $this->entityData->addChild($spawnPotentials); } $this->entityData->addChild(\Nbt\Tag::tagString('EntityId', $entityID)); if ($spawnData) { $this->entityData->addChild($spawnData); } $this->entityData->addChild(\Nbt\Tag::tagShort('SpawnCount', $spawnCount)); $this->entityData->addChild(\Nbt\Tag::tagShort('SpawnRange', $spawnRange)); $this->entityData->addChild(\Nbt\Tag::tagShort('Delay', $delay)); $this->entityData->addChild(\Nbt\Tag::tagShort('MinSpawnDelay', $minSpawnDelay)); $this->entityData->addChild(\Nbt\Tag::tagShort('MaxSpawnDelay', $maxSpawnDelay)); $this->entityData->addChild(\Nbt\Tag::tagShort('MaxNearbyEntities', $maxNearbyEntities)); $this->entityData->addChild(\Nbt\Tag::tagShort('RequiredPlayerRange', $requiredPlayerRange)); }
/** * Get a brewing stand with the given bottles in place. * * @param \MME\Stack|null $eastItem Data for the stack in the east bottle slot * @param \MME\Stack|null $southWestItem Data for the stack in the south west bottle slot * @param \MME\Stack|null $northWestItem Data for the stack in the north west bottle slot * @param \MME\Stack|null $ingredientItem Data for the stack in the ingredient slot * @param int $brewTime The number of ticks the potions have been brewing for * @param string|null $customName Custom name for the container, shows in GUI * @param string|null $lock Lock the brewing stand so it can only be opened if the player * is holding an item whose name matches this string * * @throws \Exception */ public function __construct($eastItem, $southWestItem, $northWestItem, $ingredientItem, $brewTime, $customName = null, $lock = null) { $this->setBlockIDFor(Ref::BREWING_STAND); $data = 0; if ($eastItem) { $data |= 0b1; } if ($southWestItem) { $data |= 0b10; } if ($northWestItem) { $data |= 0b100; } $this->setBlockData($data); // Yes, this says Cauldron, it's on purpose, it's how it's coded in the game $this->initEntityData('Cauldron'); $this->entityData->addChild(\Nbt\Tag::tagInt('BrewTime', $brewTime)); $this->setCustomName($customName); $this->setLock($lock); $this->addItemsForSlots([0 => $eastItem, 1 => $northWestItem, 2 => $southWestItem, 3 => $ingredientItem]); }
/** * Get the correct section from within the Sections tag (based on Y index). * * @param int $yRef * * @return \Nbt\Node */ private function getSection($yRef) { if (isset($this->sectionsList[$yRef])) { return $this->sectionsList[$yRef]; } foreach ($this->sectionsTag->getChildren() as $childNode) { if ($childNode->findChildByName('Y')->getValue() == $yRef) { $this->prepareSection($childNode); $this->sectionsList[$yRef] = $childNode; return $childNode; } } // If we didn't find one, we must create one // Doesn't need a name, it's part of a list $newY = \Nbt\Tag::tagCompound('', [\Nbt\Tag::tagByte('Y', $yRef), \Nbt\Tag::tagByteArray('Blocks', array_fill(0, 4096, 0)), \Nbt\Tag::tagByteArray('Data', array_fill(0, 2048, 0)), \Nbt\Tag::tagByteArray('BlockLight', array_fill(0, 2048, 0)), \Nbt\Tag::tagByteArray('SkyLight', array_fill(0, 2048, 0))]); // Add it to the list $this->sectionsTag->addChild($newY); $this->sectionsList[$yRef] = $newY; return $newY; }
public function providerTestTagCompound() { return [['CompoundTag', [\Nbt\Tag::tagByte('b1', 0x1), \Nbt\Tag::tagString('s2', 'astring')]]]; }
/** * Add the 'tag' compount tag, if it doesn't already exist. */ protected function addTag() { if (!isset($this->tag)) { $this->tag = \Nbt\Tag::tagCompound('tag', []); $this->node->addChild($this->tag); } }