48final class ListTag extends Tag implements \Countable, \IteratorAggregate{
49 use NoDynamicFieldsTrait;
63 public function __construct(array $value = [],
int $tagType = NBT::TAG_End){
64 self::restrictArgCount(__METHOD__, func_num_args(), 2);
65 $this->tagType = $tagType;
66 foreach($value as $tag){
85 return array_map(fn(
Tag $t) => $t->getValue(), $this->value);
93 private function checkTagClass(
string $tagClass) : bool{
94 return count($this->value) === 0 || $this->first() instanceof $tagClass;
109 public function cast(
string $tagClass) : ?self{
110 return $this->checkTagClass($tagClass) ? $this : null;
113 public function count() : int{
114 return count($this->value);
117 public function getCount() : int{
118 return count($this->value);
129 $this->checkTagType($tag);
130 $this->value[] = $tag;
138 if(count($this->value) === 0){
139 throw new \LogicException(
"List is empty");
141 return array_pop($this->value);
152 $this->checkTagType($tag);
153 array_unshift($this->value, $tag);
161 if(count($this->value) === 0){
162 throw new \LogicException(
"List is empty");
164 return array_shift($this->value);
179 $this->checkTagType($tag);
180 if($offset < 0 || $offset > count($this->value)){
181 throw new \OutOfRangeException(
"Offset cannot be negative or larger than the list's current size");
183 $newValue = array_slice($this->value, 0, $offset);
185 array_push($newValue, ...array_slice($this->value, $offset));
186 $this->value = $newValue;
192 public function remove(
int $offset) : void{
194 $newValue = $this->value;
195 unset($newValue[$offset]);
196 $this->value = array_values($newValue);
206 public function get(
int $offset) :
Tag{
207 if(!isset($this->value[$offset])){
208 throw new \OutOfRangeException(
"No such tag at offset $offset");
210 return $this->value[$offset];
218 if(count($this->value) === 0){
219 throw new \LogicException(
"List is empty");
221 return $this->value[0];
229 if(count($this->value) === 0){
230 throw new \LogicException(
"List is empty");
232 return $this->value[array_key_last($this->value)];
244 public function set(
int $offset,
Tag $tag) : void{
245 $this->checkTagType($tag);
246 if($offset < 0 || $offset > count($this->value)){
247 throw new \OutOfRangeException(
"Offset cannot be negative or larger than the list's current size");
249 $this->value[$offset] = $tag;
255 public function isset(
int $offset) : bool{
256 return isset($this->value[$offset]);
263 return count($this->value) === 0;
266 protected function getTypeName() : string{
270 public function getType() : int{
271 return
NBT::TAG_List;
278 return $this->tagType;
293 if(count($this->value) > 0){
294 throw new \LogicException(
"Cannot change tag type of non-empty ListTag");
296 $this->tagType = $type;
304 private function checkTagType(
Tag $tag) : void{
305 $type = $tag->getType();
306 if($type !== $this->tagType){
307 if(count($this->value) === 0){
308 $this->tagType = $type;
310 throw new \TypeError(
"Invalid tag of type " . get_class($tag) .
" assigned to ListTag, expected " . get_class($this->value[0]));
315 public static function read(NbtStreamReader $reader, ReaderTracker $tracker) : self{
317 $tagType = $reader->readByte();
318 $size = $reader->readInt();
321 if($tagType === NBT::TAG_End){
322 throw new NbtDataException(
"Unexpected non-empty list of TAG_End");
325 $tracker->protectDepth(
static function() use($size, $tagType, $reader, $tracker, &$value) :
void{
326 for($i = 0; $i < $size; ++$i){
327 $value[] = NBT::createTag($tagType, $reader, $tracker);
331 return new self($value, $tagType);
334 public function write(NbtStreamWriter $writer) : void{
335 $writer->writeByte($this->tagType);
336 $writer->writeInt(count($this->value));
337 foreach($this->value as $tag){
338 $tag->write($writer);
342 protected function stringifyValue(
int $indentation) : string{
344 foreach($this->value as $tag){
345 $str .= str_repeat(
" ", $indentation + 1) . $tag->toString($indentation + 1) .
"\n";
347 return $str . str_repeat(
" ", $indentation) .
"}";
350 public function __clone(){
351 $this->value = array_map(fn(Tag $t) => $t->safeClone(), $this->value);
363 yield from $this->value;
367 if(!($that instanceof $this) or count($this->value) !== count($that->value)){
371 foreach($this->value as $k => $v){
372 if(!$v->equals($that->value[$k])){