PocketMine-MP 5.41.1 git-fcc6fb5566a921cb669160c90f56fb68f5b29123
Loading...
Searching...
No Matches
PacketShapeData.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;
16
17use pmmp\encoding\Byte;
18use pmmp\encoding\ByteBufferReader;
19use pmmp\encoding\ByteBufferWriter;
20use pmmp\encoding\LE;
21use pmmp\encoding\VarInt;
27
31final class PacketShapeData{
32
33 public function __construct(
34 private int $networkId,
35 private ?ScriptDebugShapeType $type,
36 private ?Vector3 $location,
37 private ?float $scale,
38 private ?Vector3 $rotation,
39 private ?float $totalTimeLeft,
40 private ?Color $color,
41 private ?string $text,
42 private ?Vector3 $boxBound,
43 private ?Vector3 $lineEndLocation,
44 private ?float $arrowHeadLength,
45 private ?float $arrowHeadRadius,
46 private ?int $segments,
47 private ?int $dimensionId,
48 private ?int $attachedToEntityId,
49 ){}
50
51 public static function remove(int $networkId, ?int $dimensionId = null) : self{
52 return new self($networkId, null, null, null, null, null, null, null, null, null, null, null, null, $dimensionId, null);
53 }
54
55 public static function line(int $networkId, Vector3 $location, Vector3 $lineEndLocation, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
56 return new self(
57 networkId: $networkId,
58 type: ScriptDebugShapeType::LINE,
59 location: $location,
60 scale: null,
61 rotation: null,
62 totalTimeLeft: null,
63 color: $color,
64 text: null,
65 boxBound: null,
66 lineEndLocation: $lineEndLocation,
67 arrowHeadLength: null,
68 arrowHeadRadius: null,
69 segments: null,
70 dimensionId: $dimensionId,
71 attachedToEntityId: $attachedToEntityId
72 );
73 }
74
75 public static function box(int $networkId, Vector3 $location, Vector3 $boxBound, ?float $scale = null, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
76 return new self(
77 networkId: $networkId,
78 type: ScriptDebugShapeType::BOX,
79 location: $location,
80 scale: $scale,
81 rotation: null,
82 totalTimeLeft: null,
83 color: $color,
84 text: null,
85 boxBound: $boxBound,
86 lineEndLocation: null,
87 arrowHeadLength: null,
88 arrowHeadRadius: null,
89 segments: null,
90 dimensionId: $dimensionId,
91 attachedToEntityId: $attachedToEntityId
92 );
93 }
94
95 public static function sphere(int $networkId, Vector3 $location, ?float $scale = null, ?Color $color = null, ?int $segments = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
96 return new self(
97 networkId: $networkId,
98 type: ScriptDebugShapeType::SPHERE,
99 location: $location,
100 scale: $scale,
101 rotation: null,
102 totalTimeLeft: null,
103 color: $color,
104 text: null,
105 boxBound: null,
106 lineEndLocation: null,
107 arrowHeadLength: null,
108 arrowHeadRadius: null,
109 segments: $segments,
110 dimensionId: $dimensionId,
111 attachedToEntityId: $attachedToEntityId
112 );
113 }
114
115 public static function circle(int $networkId, Vector3 $location, ?float $scale = null, ?Color $color = null, ?int $segments = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
116 return new self(
117 networkId: $networkId,
118 type: ScriptDebugShapeType::CIRCLE,
119 location: $location,
120 scale: $scale,
121 rotation: null,
122 totalTimeLeft: null,
123 color: $color,
124 text: null,
125 boxBound: null,
126 lineEndLocation: null,
127 arrowHeadLength: null,
128 arrowHeadRadius: null,
129 segments: $segments,
130 dimensionId: $dimensionId,
131 attachedToEntityId: $attachedToEntityId
132 );
133 }
134
135 public static function text(int $networkId, Vector3 $location, string $text, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
136 return new self(
137 networkId: $networkId,
138 type: ScriptDebugShapeType::TEXT,
139 location: $location,
140 scale: null,
141 rotation: null,
142 totalTimeLeft: null,
143 color: $color,
144 text: $text,
145 boxBound: null,
146 lineEndLocation: null,
147 arrowHeadLength: null,
148 arrowHeadRadius: null,
149 segments: null,
150 dimensionId: $dimensionId,
151 attachedToEntityId: $attachedToEntityId
152 );
153 }
154
155 public static function arrow(int $networkId, Vector3 $location, Vector3 $lineEndLocation, ?float $scale = null, ?Color $color = null, ?float $arrowHeadLength = null, ?float $arrowHeadRadius = null, ?int $segments = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
156 return new self(
157 networkId: $networkId,
158 type: ScriptDebugShapeType::ARROW,
159 location: $location,
160 scale: $scale,
161 rotation: null,
162 totalTimeLeft: null,
163 color: $color,
164 text: null,
165 boxBound: null,
166 lineEndLocation: $lineEndLocation,
167 arrowHeadLength: $arrowHeadLength,
168 arrowHeadRadius: $arrowHeadRadius,
169 segments: $segments,
170 dimensionId: $dimensionId,
171 attachedToEntityId: $attachedToEntityId
172 );
173 }
174
175 public function getNetworkId() : int{ return $this->networkId; }
176
177 public function getType() : ?ScriptDebugShapeType{ return $this->type; }
178
179 public function getLocation() : ?Vector3{ return $this->location; }
180
181 public function getScale() : ?float{ return $this->scale; }
182
183 public function getRotation() : ?Vector3{ return $this->rotation; }
184
185 public function getTotalTimeLeft() : ?float{ return $this->totalTimeLeft; }
186
187 public function getColor() : ?Color{ return $this->color; }
188
189 public function getDimensionId() : ?int{ return $this->dimensionId; }
190
191 public function getText() : ?string{ return $this->text; }
192
193 public function getBoxBound() : ?Vector3{ return $this->boxBound; }
194
195 public function getLineEndLocation() : ?Vector3{ return $this->lineEndLocation; }
196
197 public function getArrowHeadLength() : ?float{ return $this->arrowHeadLength; }
198
199 public function getArrowHeadRadius() : ?float{ return $this->arrowHeadRadius; }
200
201 public function getSegments() : ?int{ return $this->segments; }
202
203 public static function read(ByteBufferReader $in) : self{
204 $networkId = VarInt::readUnsignedLong($in);
205 $shapeType = CommonTypes::readOptional($in, fn() => ScriptDebugShapeType::fromPacket(Byte::readUnsigned($in)));
206 $location = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
207 $scale = CommonTypes::readOptional($in, LE::readFloat(...));
208 $rotation = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
209 $totalTimeLeft = CommonTypes::readOptional($in, LE::readFloat(...));
210 $color = CommonTypes::readOptional($in, fn() => Color::fromARGB(LE::readUnsignedInt($in)));
211 $dimensionId = CommonTypes::readOptional($in, fn() => VarInt::readSignedInt($in));
212 $attachedToEntityId = CommonTypes::readOptional($in, fn() => CommonTypes::getActorRuntimeId($in));
213
214 $payloadType = VarInt::readUnsignedInt($in);
215 //WTF IS THIS HORROR SHOW
216 if(
217 ($shapeType !== null && $payloadType !== $shapeType->getPayloadType() && $payloadType !== ScriptDebugShapeType::PAYLOAD_TYPE_NONE) ||
218 ($shapeType === null && $payloadType !== ScriptDebugShapeType::PAYLOAD_TYPE_NONE)
219 ){
220 throw new PacketDecodeException("Unexpected payload type $payloadType for provided shape type " . ($shapeType->name ?? "(not set)"));
221 }
222 $text = null;
223 $boxBound = null;
224 $lineEndLocation = null;
225 $arrowHeadLength = null;
226 $arrowHeadRadius = null;
227 $segments = null;
228 switch($payloadType){
229 case ScriptDebugShapeType::PAYLOAD_TYPE_NONE:
230 break;
231 case ScriptDebugShapeType::PAYLOAD_TYPE_ARROW:
232 $lineEndLocation = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
233 $arrowHeadLength = CommonTypes::readOptional($in, LE::readFloat(...));
234 $arrowHeadRadius = CommonTypes::readOptional($in, LE::readFloat(...));
235 $segments = CommonTypes::readOptional($in, Byte::readUnsigned(...));
236 break;
237 case ScriptDebugShapeType::PAYLOAD_TYPE_TEXT:
238 $text = CommonTypes::getString($in);
239 break;
240 case ScriptDebugShapeType::PAYLOAD_TYPE_BOX:
241 $boxBound = CommonTypes::getVector3($in);
242 break;
243 case ScriptDebugShapeType::PAYLOAD_TYPE_LINE:
244 $lineEndLocation = CommonTypes::getVector3($in);
245 break;
246 case ScriptDebugShapeType::PAYLOAD_TYPE_CIRCLE_OR_SPHERE:
247 $segments = Byte::readUnsigned($in);
248 break;
249 default:
250 throw new PacketDecodeException("Unexpected shape payload type $payloadType");
251 }
252
253 return new self(
254 $networkId,
255 $shapeType,
256 $location,
257 $scale,
258 $rotation,
259 $totalTimeLeft,
260 $color,
261 $text,
262 $boxBound,
263 $lineEndLocation,
264 $arrowHeadLength,
265 $arrowHeadRadius,
266 $segments,
267 $dimensionId,
268 $attachedToEntityId
269 );
270 }
271
272 public function write(ByteBufferWriter $out) : void{
273 VarInt::writeUnsignedLong($out, $this->networkId);
274 CommonTypes::writeOptional($out, $this->type, fn(ByteBufferWriter $out, ScriptDebugShapeType $type) => Byte::writeUnsigned($out, $type->value));
275 CommonTypes::writeOptional($out, $this->location, CommonTypes::putVector3(...));
276 CommonTypes::writeOptional($out, $this->scale, LE::writeFloat(...));
277 CommonTypes::writeOptional($out, $this->rotation, CommonTypes::putVector3(...));
278 CommonTypes::writeOptional($out, $this->totalTimeLeft, LE::writeFloat(...));
279 CommonTypes::writeOptional($out, $this->color, fn(ByteBufferWriter $out, Color $color) => LE::writeUnsignedInt($out, $color->toARGB()));
280 CommonTypes::writeOptional($out, $this->dimensionId, fn(ByteBufferWriter $out, int $dimensionId) => VarInt::writeSignedInt($out, $dimensionId));
281 CommonTypes::writeOptional($out, $this->attachedToEntityId, fn(ByteBufferWriter $out, int $entityId) => CommonTypes::putActorRuntimeId($out, $entityId));
282
283 //A godawful hack for a godawful packet
284 $payloadType = $this->type?->getPayloadType() ?? ScriptDebugShapeType::PAYLOAD_TYPE_NONE;
285 if($this->type === null){
286 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
287 }else{
288 switch($this->type){
289 case ScriptDebugShapeType::ARROW:
290 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
291 CommonTypes::writeOptional($out, $this->lineEndLocation, CommonTypes::putVector3(...));
292 CommonTypes::writeOptional($out, $this->arrowHeadLength, LE::writeFloat(...));
293 CommonTypes::writeOptional($out, $this->arrowHeadRadius, LE::writeFloat(...));
294 CommonTypes::writeOptional($out, $this->segments, Byte::writeUnsigned(...));
295 break;
296 case ScriptDebugShapeType::TEXT:
297 if($this->text !== null){
298 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
299 CommonTypes::putString($out, $this->text);
300 }else{
301 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
302 }
303 break;
304 case ScriptDebugShapeType::BOX:
305 if($this->boxBound !== null){
306 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
307 CommonTypes::putVector3($out, $this->boxBound);
308 }else{
309 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
310 }
311 break;
312 case ScriptDebugShapeType::LINE:
313 if($this->lineEndLocation !== null){
314 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
315 CommonTypes::putVector3($out, $this->lineEndLocation);
316 }else{
317 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
318 }
319 break;
320 case ScriptDebugShapeType::CIRCLE:
321 case ScriptDebugShapeType::SPHERE:
322 if($this->segments !== null){
323 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
324 Byte::writeUnsigned($out, $this->segments);
325 }else{
326 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
327 }
328 break;
329 default:
330 throw new \LogicException("Unknown payload type $payloadType");
331 }
332 }
333 }
334}