PocketMine-MP 5.43.2 git-c9e7b3ab9bd2149f206392522e8eb7e9d8d68cfa
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 ?float $maximumRenderDistance,
41 private ?Color $color,
42 private ?string $text,
43 private ?bool $useRotation,
44 private ?Color $backgroundColor,
45 private ?bool $depthTest,
46 private ?bool $showBackface,
47 private ?bool $showTextBackface,
48 private ?Vector3 $boxBound,
49 private ?Vector3 $lineEndLocation,
50 private ?float $arrowHeadLength,
51 private ?float $arrowHeadRadius,
52 private ?int $segments,
53 private ?int $dimensionId,
54 private ?int $attachedToEntityId,
55 ){}
56
57 public static function remove(int $networkId, ?int $dimensionId = null) : self{
58 return new self($networkId, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, $dimensionId, null);
59 }
60
61 public static function line(int $networkId, Vector3 $location, Vector3 $lineEndLocation, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
62 return new self(
63 networkId: $networkId,
64 type: ScriptDebugShapeType::LINE,
65 location: $location,
66 scale: null,
67 rotation: null,
68 totalTimeLeft: null,
69 maximumRenderDistance: null,
70 color: $color,
71 text: null,
72 useRotation: null,
73 backgroundColor: null,
74 depthTest: null,
75 showBackface: null,
76 showTextBackface: null,
77 boxBound: null,
78 lineEndLocation: $lineEndLocation,
79 arrowHeadLength: null,
80 arrowHeadRadius: null,
81 segments: null,
82 dimensionId: $dimensionId,
83 attachedToEntityId: $attachedToEntityId
84 );
85 }
86
87 public static function box(int $networkId, Vector3 $location, Vector3 $boxBound, ?float $scale = null, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
88 return new self(
89 networkId: $networkId,
90 type: ScriptDebugShapeType::BOX,
91 location: $location,
92 scale: $scale,
93 rotation: null,
94 totalTimeLeft: null,
95 maximumRenderDistance: null,
96 color: $color,
97 text: null,
98 useRotation: null,
99 backgroundColor: null,
100 depthTest: null,
101 showBackface: null,
102 showTextBackface: null,
103 boxBound: $boxBound,
104 lineEndLocation: null,
105 arrowHeadLength: null,
106 arrowHeadRadius: null,
107 segments: null,
108 dimensionId: $dimensionId,
109 attachedToEntityId: $attachedToEntityId
110 );
111 }
112
113 public static function sphere(int $networkId, Vector3 $location, ?float $scale = null, ?Color $color = null, ?int $segments = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
114 return new self(
115 networkId: $networkId,
116 type: ScriptDebugShapeType::SPHERE,
117 location: $location,
118 scale: $scale,
119 rotation: null,
120 totalTimeLeft: null,
121 maximumRenderDistance: null,
122 color: $color,
123 text: null,
124 useRotation: null,
125 backgroundColor: null,
126 depthTest: null,
127 showBackface: null,
128 showTextBackface: null,
129 boxBound: null,
130 lineEndLocation: null,
131 arrowHeadLength: null,
132 arrowHeadRadius: null,
133 segments: $segments,
134 dimensionId: $dimensionId,
135 attachedToEntityId: $attachedToEntityId
136 );
137 }
138
139 public static function circle(int $networkId, Vector3 $location, ?float $scale = null, ?Color $color = null, ?int $segments = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
140 return new self(
141 networkId: $networkId,
142 type: ScriptDebugShapeType::CIRCLE,
143 location: $location,
144 scale: $scale,
145 rotation: null,
146 totalTimeLeft: null,
147 maximumRenderDistance: null,
148 color: $color,
149 text: null,
150 useRotation: null,
151 backgroundColor: null,
152 depthTest: null,
153 showBackface: null,
154 showTextBackface: null,
155 boxBound: null,
156 lineEndLocation: null,
157 arrowHeadLength: null,
158 arrowHeadRadius: null,
159 segments: $segments,
160 dimensionId: $dimensionId,
161 attachedToEntityId: $attachedToEntityId
162 );
163 }
164
165 public static function text(int $networkId, Vector3 $location, string $text, bool $useRotation = false, ?Color $backgroundColor = null, bool $depthTest = true, bool $showBackface = true, bool $showTextBackface = true, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
166 return new self(
167 networkId: $networkId,
168 type: ScriptDebugShapeType::TEXT,
169 location: $location,
170 scale: null,
171 rotation: null,
172 totalTimeLeft: null,
173 maximumRenderDistance: null,
174 color: $color,
175 text: $text,
176 useRotation: $useRotation,
177 backgroundColor: $backgroundColor,
178 depthTest: $depthTest,
179 showBackface: $showBackface,
180 showTextBackface: $showTextBackface,
181 boxBound: null,
182 lineEndLocation: null,
183 arrowHeadLength: null,
184 arrowHeadRadius: null,
185 segments: null,
186 dimensionId: $dimensionId,
187 attachedToEntityId: $attachedToEntityId
188 );
189 }
190
191 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{
192 return new self(
193 networkId: $networkId,
194 type: ScriptDebugShapeType::ARROW,
195 location: $location,
196 scale: $scale,
197 rotation: null,
198 totalTimeLeft: null,
199 maximumRenderDistance: null,
200 color: $color,
201 text: null,
202 useRotation: null,
203 backgroundColor: null,
204 depthTest: null,
205 showBackface: null,
206 showTextBackface: null,
207 boxBound: null,
208 lineEndLocation: $lineEndLocation,
209 arrowHeadLength: $arrowHeadLength,
210 arrowHeadRadius: $arrowHeadRadius,
211 segments: $segments,
212 dimensionId: $dimensionId,
213 attachedToEntityId: $attachedToEntityId
214 );
215 }
216
217 public function getNetworkId() : int{ return $this->networkId; }
218
219 public function getType() : ?ScriptDebugShapeType{ return $this->type; }
220
221 public function getLocation() : ?Vector3{ return $this->location; }
222
223 public function getScale() : ?float{ return $this->scale; }
224
225 public function getRotation() : ?Vector3{ return $this->rotation; }
226
227 public function getTotalTimeLeft() : ?float{ return $this->totalTimeLeft; }
228
229 public function getMaximumRenderDistance() : ?float{ return $this->maximumRenderDistance; }
230
231 public function getColor() : ?Color{ return $this->color; }
232
233 public function getDimensionId() : ?int{ return $this->dimensionId; }
234
235 public function getAttachedToEntityId() : ?int{ return $this->attachedToEntityId; }
236
237 public function getText() : ?string{ return $this->text; }
238
239 public function getUseRotation() : ?bool{ return $this->useRotation; }
240
241 public function getBackgroundColor() : ?Color{ return $this->backgroundColor; }
242
243 public function getDepthTest() : ?bool{ return $this->depthTest; }
244
245 public function getShowBackface() : ?bool{ return $this->showBackface; }
246
247 public function getShowTextBackface() : ?bool{ return $this->showTextBackface; }
248
249 public function getBoxBound() : ?Vector3{ return $this->boxBound; }
250
251 public function getLineEndLocation() : ?Vector3{ return $this->lineEndLocation; }
252
253 public function getArrowHeadLength() : ?float{ return $this->arrowHeadLength; }
254
255 public function getArrowHeadRadius() : ?float{ return $this->arrowHeadRadius; }
256
257 public function getSegments() : ?int{ return $this->segments; }
258
259 public static function read(ByteBufferReader $in) : self{
260 $networkId = VarInt::readUnsignedLong($in);
261 $shapeType = CommonTypes::readOptional($in, fn() => ScriptDebugShapeType::fromPacket(Byte::readUnsigned($in)));
262 $location = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
263 $scale = CommonTypes::readOptional($in, LE::readFloat(...));
264 $rotation = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
265 $totalTimeLeft = CommonTypes::readOptional($in, LE::readFloat(...));
266 $maximumRenderDistance = CommonTypes::readOptional($in, LE::readFloat(...));
267 $color = CommonTypes::readOptional($in, fn() => Color::fromARGB(LE::readUnsignedInt($in)));
268 $dimensionId = CommonTypes::readOptional($in, fn() => VarInt::readSignedInt($in));
269 $attachedToEntityId = CommonTypes::readOptional($in, fn() => CommonTypes::getActorRuntimeId($in));
270
271 $payloadType = VarInt::readUnsignedInt($in);
272 //WTF IS THIS HORROR SHOW
273 if(
274 ($shapeType !== null && $payloadType !== $shapeType->getPayloadType() && $payloadType !== ScriptDebugShapeType::PAYLOAD_TYPE_NONE) ||
275 ($shapeType === null && $payloadType !== ScriptDebugShapeType::PAYLOAD_TYPE_NONE)
276 ){
277 throw new PacketDecodeException("Unexpected payload type $payloadType for provided shape type " . ($shapeType->name ?? "(not set)"));
278 }
279 $text = null;
280 $useRotation = null;
281 $backgroundColor = null;
282 $depthTest = null;
283 $showBackface = null;
284 $showTextBackface = null;
285 $boxBound = null;
286 $lineEndLocation = null;
287 $arrowHeadLength = null;
288 $arrowHeadRadius = null;
289 $segments = null;
290 switch($payloadType){
291 case ScriptDebugShapeType::PAYLOAD_TYPE_NONE:
292 break;
293 case ScriptDebugShapeType::PAYLOAD_TYPE_ARROW:
294 $lineEndLocation = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
295 $arrowHeadLength = CommonTypes::readOptional($in, LE::readFloat(...));
296 $arrowHeadRadius = CommonTypes::readOptional($in, LE::readFloat(...));
297 $segments = CommonTypes::readOptional($in, Byte::readUnsigned(...));
298 break;
299 case ScriptDebugShapeType::PAYLOAD_TYPE_TEXT:
300 $text = CommonTypes::getString($in);
301 $useRotation = CommonTypes::getBool($in);
302 $backgroundColor = CommonTypes::readOptional($in, fn() => Color::fromARGB(LE::readUnsignedInt($in)));
303 $depthTest = CommonTypes::getBool($in);
304 $showBackface = CommonTypes::getBool($in);
305 $showTextBackface = CommonTypes::getBool($in);
306 break;
307 case ScriptDebugShapeType::PAYLOAD_TYPE_BOX:
308 $boxBound = CommonTypes::getVector3($in);
309 break;
310 case ScriptDebugShapeType::PAYLOAD_TYPE_LINE:
311 $lineEndLocation = CommonTypes::getVector3($in);
312 break;
313 case ScriptDebugShapeType::PAYLOAD_TYPE_CIRCLE_OR_SPHERE:
314 $segments = Byte::readUnsigned($in);
315 break;
316 default:
317 throw new PacketDecodeException("Unexpected shape payload type $payloadType");
318 }
319
320 return new self(
321 $networkId,
322 $shapeType,
323 $location,
324 $scale,
325 $rotation,
326 $totalTimeLeft,
327 $maximumRenderDistance,
328 $color,
329 $text,
330 $useRotation,
331 $backgroundColor,
332 $depthTest,
333 $showBackface,
334 $showTextBackface,
335 $boxBound,
336 $lineEndLocation,
337 $arrowHeadLength,
338 $arrowHeadRadius,
339 $segments,
340 $dimensionId,
341 $attachedToEntityId
342 );
343 }
344
345 public function write(ByteBufferWriter $out) : void{
346 VarInt::writeUnsignedLong($out, $this->networkId);
347 CommonTypes::writeOptional($out, $this->type, fn(ByteBufferWriter $out, ScriptDebugShapeType $type) => Byte::writeUnsigned($out, $type->value));
348 CommonTypes::writeOptional($out, $this->location, CommonTypes::putVector3(...));
349 CommonTypes::writeOptional($out, $this->scale, LE::writeFloat(...));
350 CommonTypes::writeOptional($out, $this->rotation, CommonTypes::putVector3(...));
351 CommonTypes::writeOptional($out, $this->totalTimeLeft, LE::writeFloat(...));
352 CommonTypes::writeOptional($out, $this->maximumRenderDistance, LE::writeFloat(...));
353 CommonTypes::writeOptional($out, $this->color, fn(ByteBufferWriter $out, Color $color) => LE::writeUnsignedInt($out, $color->toARGB()));
354 CommonTypes::writeOptional($out, $this->dimensionId, fn(ByteBufferWriter $out, int $dimensionId) => VarInt::writeSignedInt($out, $dimensionId));
355 CommonTypes::writeOptional($out, $this->attachedToEntityId, fn(ByteBufferWriter $out, int $entityId) => CommonTypes::putActorRuntimeId($out, $entityId));
356
357 //A godawful hack for a godawful packet
358 $payloadType = $this->type?->getPayloadType() ?? ScriptDebugShapeType::PAYLOAD_TYPE_NONE;
359 if($this->type === null){
360 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
361 }else{
362 switch($this->type){
363 case ScriptDebugShapeType::ARROW:
364 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
365 CommonTypes::writeOptional($out, $this->lineEndLocation, CommonTypes::putVector3(...));
366 CommonTypes::writeOptional($out, $this->arrowHeadLength, LE::writeFloat(...));
367 CommonTypes::writeOptional($out, $this->arrowHeadRadius, LE::writeFloat(...));
368 CommonTypes::writeOptional($out, $this->segments, Byte::writeUnsigned(...));
369 break;
370 case ScriptDebugShapeType::TEXT:
371 if($this->text !== null){
372 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
373 CommonTypes::putString($out, $this->text);
374 CommonTypes::putBool($out, $this->useRotation ?? false);
375 CommonTypes::writeOptional($out, $this->backgroundColor, fn(ByteBufferWriter $out, Color $color) => LE::writeUnsignedInt($out, $color->toARGB()));
376 CommonTypes::putBool($out, $this->depthTest ?? true);
377 CommonTypes::putBool($out, $this->showBackface ?? true);
378 CommonTypes::putBool($out, $this->showTextBackface ?? true);
379 }else{
380 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
381 }
382 break;
383 case ScriptDebugShapeType::BOX:
384 if($this->boxBound !== null){
385 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
386 CommonTypes::putVector3($out, $this->boxBound);
387 }else{
388 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
389 }
390 break;
391 case ScriptDebugShapeType::LINE:
392 if($this->lineEndLocation !== null){
393 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
394 CommonTypes::putVector3($out, $this->lineEndLocation);
395 }else{
396 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
397 }
398 break;
399 case ScriptDebugShapeType::CIRCLE:
400 case ScriptDebugShapeType::SPHERE:
401 if($this->segments !== null){
402 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
403 Byte::writeUnsigned($out, $this->segments);
404 }else{
405 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
406 }
407 break;
408 default:
409 throw new \LogicException("Unknown payload type $payloadType");
410 }
411 }
412 }
413}