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;
96 $tag = $this->getTag($name);
97 if($tag !==
null && !($tag instanceof
ListTag)){
108 $tag = $this->getTag($name);
109 if($tag !==
null && !($tag instanceof
CompoundTag)){
121 if(strlen($name) >
Limits::INT16_MAX){
122 throw new \InvalidArgumentException(sprintf(
"Tag name must be at most %d bytes, but got %d bytes", Limits::INT16_MAX, strlen($name)));
124 $this->value[$name] = $tag;
133 foreach($names as $name){
134 unset($this->value[$name]);
152 private function getTagValue(
string $name,
string $expectedClass, $default =
null){
153 $tag = $this->getTag($name);
154 if($tag instanceof $expectedClass){
155 return $tag->getValue();
158 throw new UnexpectedTagTypeException(
"Expected a tag of type $expectedClass, got " . get_class($tag));
161 if($default ===
null){
162 throw new NoSuchTagException(
"Tag \"$name\" does not exist");
172 public function getByte(
string $name, ?
int $default =
null) : int{
173 return $this->getTagValue($name, ByteTag::class, $default);
176 public function getShort(
string $name, ?
int $default =
null) : int{
177 return $this->getTagValue($name, ShortTag::class, $default);
180 public function getInt(
string $name, ?
int $default =
null) : int{
181 return $this->getTagValue($name, IntTag::class, $default);
184 public function getLong(
string $name, ?
int $default =
null) : int{
185 return $this->getTagValue($name, LongTag::class, $default);
188 public function getFloat(
string $name, ?
float $default =
null) : float{
189 return $this->getTagValue($name, FloatTag::class, $default);
192 public function getDouble(
string $name, ?
float $default =
null) : float{
193 return $this->getTagValue($name, DoubleTag::class, $default);
196 public function getByteArray(
string $name, ?
string $default =
null) : string{
197 return $this->getTagValue($name, ByteArrayTag::class, $default);
200 public function getString(
string $name, ?
string $default =
null) : string{
201 return $this->getTagValue($name, StringTag::class, $default);
209 public function getIntArray(
string $name, ?array $default =
null) : array{
210 return $this->getTagValue($name,
IntArrayTag::class, $default);
220 public function setByte(
string $name,
int $value) : self{
221 return $this->setTag($name, new
ByteTag($value));
227 public function setShort(
string $name,
int $value) : self{
228 return $this->setTag($name, new
ShortTag($value));
234 public function setInt(
string $name,
int $value) : self{
235 return $this->setTag($name, new
IntTag($value));
241 public function setLong(
string $name,
int $value) : self{
242 return $this->setTag($name, new
LongTag($value));
248 public function setFloat(
string $name,
float $value) : self{
249 return $this->setTag($name, new
FloatTag($value));
255 public function setDouble(
string $name,
float $value) : self{
256 return $this->setTag($name, new
DoubleTag($value));
269 public function setString(
string $name,
string $value) : self{
270 return $this->setTag($name, new
StringTag($value));
280 return $this->setTag($name, new
IntArrayTag($value));
283 protected function getTypeName() : string{
287 public function getType() : int{
288 return
NBT::TAG_Compound;
291 public static function read(NbtStreamReader $reader, ReaderTracker $tracker) : self{
293 $tracker->protectDepth(
static function() use($reader, $tracker, $result) :
void{
294 for($type = $reader->readByte(); $type !== NBT::TAG_End; $type = $reader->readByte()){
295 $name = $reader->readString();
296 $tag = NBT::createTag($type, $reader, $tracker);
297 if($result->getTag($name) !==
null){
305 $result->setTag($name, $tag);
311 public function write(NbtStreamWriter $writer) : void{
312 foreach($this->value as $name => $tag){
316 $name = (string) $name;
318 $writer->writeByte($tag->getType());
319 $writer->writeString($name);
320 $tag->write($writer);
322 $writer->writeByte(NBT::TAG_End);
325 protected function stringifyValue(
int $indentation) : string{
327 foreach($this->value as $name => $tag){
328 $str .= str_repeat(
" ", $indentation + 1) .
"\"$name\" => " . $tag->toString($indentation + 1) .
"\n";
330 return $str . str_repeat(
" ", $indentation) .
"}";
333 public function __clone(){
334 foreach($this->value as $key => $tag){
335 $this->value[$key] = $tag->safeClone();
348 foreach($this->value as $name => $tag){
351 yield strval($name) => $tag;
356 if(!($that instanceof $this) or count($this->value) !== count($that->value)){
360 foreach($this->value as $k => $v){
361 $other = $that->value[$k] ??
null;
362 if($other ===
null or !$v->equals($other)){
379 foreach($other as $k => $namedTag){
380 $new->setTag($k, clone $namedTag);