45final class CompoundTag extends Tag implements \Countable, \IteratorAggregate{
46 use NoDynamicFieldsTrait;
51 public function __construct(){
52 self::restrictArgCount(__METHOD__, func_num_args(), 0);
58 public static function create() : self{
62 public function count() : int{
63 return count($this->value);
70 return count($this->value);
88 return $this->value[$name] ?? null;
102 $tag = $this->getTag($name);
107 $casted = $tag->cast($tagClass);
108 if($casted ===
null){
121 $tag = $this->getTag($name);
122 if($tag !==
null && !($tag instanceof
CompoundTag)){
134 if(strlen($name) >
Limits::INT16_MAX){
135 throw new \InvalidArgumentException(sprintf(
"Tag name must be at most %d bytes, but got %d bytes", Limits::INT16_MAX, strlen($name)));
137 $this->value[$name] = $tag;
146 foreach($names as $name){
147 unset($this->value[$name]);
165 private function getTagValue(
string $name,
string $expectedClass, $default =
null){
166 $tag = $this->getTag($name);
167 if($tag instanceof $expectedClass){
168 return $tag->getValue();
171 throw new UnexpectedTagTypeException(
"Expected a tag of type $expectedClass, got " . get_class($tag));
174 if($default ===
null){
175 throw new NoSuchTagException(
"Tag \"$name\" does not exist");
185 public function getByte(
string $name, ?
int $default =
null) : int{
186 return $this->getTagValue($name, ByteTag::class, $default);
189 public function getShort(
string $name, ?
int $default =
null) : int{
190 return $this->getTagValue($name, ShortTag::class, $default);
193 public function getInt(
string $name, ?
int $default =
null) : int{
194 return $this->getTagValue($name, IntTag::class, $default);
197 public function getLong(
string $name, ?
int $default =
null) : int{
198 return $this->getTagValue($name, LongTag::class, $default);
201 public function getFloat(
string $name, ?
float $default =
null) : float{
202 return $this->getTagValue($name, FloatTag::class, $default);
205 public function getDouble(
string $name, ?
float $default =
null) : float{
206 return $this->getTagValue($name, DoubleTag::class, $default);
209 public function getByteArray(
string $name, ?
string $default =
null) : string{
210 return $this->getTagValue($name, ByteArrayTag::class, $default);
213 public function getString(
string $name, ?
string $default =
null) : string{
214 return $this->getTagValue($name, StringTag::class, $default);
222 public function getIntArray(
string $name, ?array $default =
null) : array{
223 return $this->getTagValue($name,
IntArrayTag::class, $default);
233 public function setByte(
string $name,
int $value) : self{
234 return $this->setTag($name, new
ByteTag($value));
240 public function setShort(
string $name,
int $value) : self{
241 return $this->setTag($name, new
ShortTag($value));
247 public function setInt(
string $name,
int $value) : self{
248 return $this->setTag($name, new
IntTag($value));
254 public function setLong(
string $name,
int $value) : self{
255 return $this->setTag($name, new
LongTag($value));
261 public function setFloat(
string $name,
float $value) : self{
262 return $this->setTag($name, new
FloatTag($value));
268 public function setDouble(
string $name,
float $value) : self{
269 return $this->setTag($name, new
DoubleTag($value));
282 public function setString(
string $name,
string $value) : self{
283 return $this->setTag($name, new
StringTag($value));
293 return $this->setTag($name, new
IntArrayTag($value));
296 protected function getTypeName() : string{
300 public function getType() : int{
301 return
NBT::TAG_Compound;
304 public static function read(NbtStreamReader $reader, ReaderTracker $tracker) : self{
306 $tracker->protectDepth(
static function() use($reader, $tracker, $result) :
void{
307 for($type = $reader->readByte(); $type !== NBT::TAG_End; $type = $reader->readByte()){
308 $name = $reader->readString();
309 $tag = NBT::createTag($type, $reader, $tracker);
310 if($result->getTag($name) !==
null){
318 $result->setTag($name, $tag);
324 public function write(NbtStreamWriter $writer) : void{
325 foreach($this->value as $name => $tag){
329 $name = (string) $name;
331 $writer->writeByte($tag->getType());
332 $writer->writeString($name);
333 $tag->write($writer);
335 $writer->writeByte(NBT::TAG_End);
338 protected function stringifyValue(
int $indentation) : string{
340 foreach($this->value as $name => $tag){
341 $str .= str_repeat(
" ", $indentation + 1) .
"\"$name\" => " . $tag->toString($indentation + 1) .
"\n";
343 return $str . str_repeat(
" ", $indentation) .
"}";
346 public function __clone(){
347 foreach($this->value as $key => $tag){
348 $this->value[$key] = $tag->safeClone();
361 foreach($this->value as $name => $tag){
364 yield strval($name) => $tag;
369 if(!($that instanceof $this) or count($this->value) !== count($that->value)){
373 foreach($this->value as $k => $v){
374 $other = $that->value[$k] ??
null;
375 if($other ===
null or !$v->equals($other)){
392 foreach($other as $k => $namedTag){
393 $new->setTag($k, clone $namedTag);