PocketMine-MP 5.17.1 git-df4ada81e5d74a14046f27cf44a37dcee69d657e
EntityMetadataCollection.php
1<?php
2
3/*
4 * This file is part of BedrockProtocol.
5 * Copyright (C) 2014-2022 PocketMine Team <https://github.com/pmmp/BedrockProtocol>
6 *
7 * BedrockProtocol is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
13declare(strict_types=1);
14
15namespace pocketmine\network\mcpe\protocol\types\entity;
16
20use function get_class;
21use function get_debug_type;
22
24
29 private array $properties = [];
34 private array $dirtyProperties = [];
35
36 public function __construct(){
37
38 }
39
40 public function setByte(int $key, int $value, bool $force = false) : void{
41
42 $this->set($key, new ByteMetadataProperty($value), $force);
43 }
44
45 public function setShort(int $key, int $value, bool $force = false) : void{
46 $this->set($key, new ShortMetadataProperty($value), $force);
47 }
48
49 public function setInt(int $key, int $value, bool $force = false) : void{
50 $this->set($key, new IntMetadataProperty($value), $force);
51 }
52
53 public function setFloat(int $key, float $value, bool $force = false) : void{
54 $this->set($key, new FloatMetadataProperty($value), $force);
55 }
56
57 public function setString(int $key, string $value, bool $force = false) : void{
58 $this->set($key, new StringMetadataProperty($value), $force);
59 }
60
64 public function setCompoundTag(int $key, CacheableNbt $value, bool $force = false) : void{
65 $this->set($key, new CompoundTagMetadataProperty($value), $force);
66 }
67
68 public function setBlockPos(int $key, ?BlockPosition $value, bool $force = false) : void{
69 $this->set($key, new BlockPosMetadataProperty($value ?? new BlockPosition(0, 0, 0)), $force);
70 }
71
72 public function setLong(int $key, int $value, bool $force = false) : void{
73 $this->set($key, new LongMetadataProperty($value), $force);
74 }
75
76 public function setVector3(int $key, ?Vector3 $value, bool $force = false) : void{
77 $this->set($key, new Vec3MetadataProperty($value ?? new Vector3(0, 0, 0)), $force);
78 }
79
80 public function set(int $key, MetadataProperty $value, bool $force = false) : void{
81 if(!$force and isset($this->properties[$key]) and !($this->properties[$key] instanceof $value)){
82 throw new \InvalidArgumentException("Can't overwrite property with mismatching types (have " . get_class($this->properties[$key]) . ")");
83 }
84 if(!isset($this->properties[$key]) or !$this->properties[$key]->equals($value)){
85 $this->properties[$key] = $this->dirtyProperties[$key] = $value;
86 }
87 }
88
95 public function setAtomicBatch(array $properties, bool $force = false) : void{
96 $anyDirty = false;
97 if(!$force){
98 foreach($properties as $key => $value){
99 if(isset($this->properties[$key]) and !($this->properties[$key] instanceof $value)){
100 throw new \InvalidArgumentException("Can't overwrite " . get_class($this->properties[$key]) . " with " . get_debug_type($value));
101 }
102 }
103 }
104 foreach($properties as $key => $value){
105 if(!isset($this->properties[$key]) or !$this->properties[$key]->equals($value)){
106 $anyDirty = true;
107 break;
108 }
109 }
110 if($anyDirty){
111 foreach($properties as $key => $value){
112 $this->properties[$key] = $this->dirtyProperties[$key] = $value;
113 }
114 }
115 }
116
117 public function setGenericFlag(int $flagId, bool $value) : void{
118 $propertyId = $flagId >= 64 ? EntityMetadataProperties::FLAGS2 : EntityMetadataProperties::FLAGS;
119 $realFlagId = $flagId % 64;
120 $flagSetProp = $this->properties[$propertyId] ?? null;
121 if($flagSetProp === null){
122 $flagSet = 0;
123 }elseif($flagSetProp instanceof LongMetadataProperty){
124 $flagSet = $flagSetProp->getValue();
125 }else{
126 throw new \InvalidArgumentException("Wrong type found for flags, want long, but have " . get_class($flagSetProp));
127 }
128
129 if((($flagSet >> $realFlagId) & 1) !== ($value ? 1 : 0)){
130 $flagSet ^= (1 << $realFlagId);
131 $this->setLong($propertyId, $flagSet);
132 }
133 }
134
135 public function setPlayerFlag(int $flagId, bool $value) : void{
136 $flagSetProp = $this->properties[EntityMetadataProperties::PLAYER_FLAGS] ?? null;
137 if($flagSetProp === null){
138 $flagSet = 0;
139 }elseif($flagSetProp instanceof ByteMetadataProperty){
140 $flagSet = $flagSetProp->getValue();
141 }else{
142 throw new \InvalidArgumentException("Wrong type found for flags, want byte, but have " . get_class($flagSetProp));
143 }
144 if((($flagSet >> $flagId) & 1) !== ($value ? 1 : 0)){
145 $flagSet ^= (1 << $flagId);
146 $this->setByte(EntityMetadataProperties::PLAYER_FLAGS, $flagSet);
147 }
148 }
149
156 public function getAll() : array{
157 return $this->properties;
158 }
159
166 public function getDirty() : array{
167 return $this->dirtyProperties;
168 }
169
173 public function clearDirtyProperties() : void{
174 $this->dirtyProperties = [];
175 }
176
180 public function markDirty(int $key) : void{
181 if(isset($this->properties[$key])){
182 $this->dirtyProperties[$key] = $this->properties[$key];
183 }
184 }
185
189 public function markAllDirty() : void{
190 $this->dirtyProperties = $this->properties;
191 }
192}