PocketMine-MP 5.44.4 git-6a7cc02e9dff59b69241aa0bcffdb9903ce86beb
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\shape;
16
17use pmmp\encoding\Byte;
18use pmmp\encoding\ByteBufferReader;
19use pmmp\encoding\ByteBufferWriter;
20use pmmp\encoding\LE;
21use pmmp\encoding\VarInt;
28
32final class PacketShapeData{
33
34 public function __construct(
35 private int $networkId,
36 private ?PrimitiveShapeType $type,
37 private ?Vector3 $location,
38 private ?float $scale,
39 private ?Vector3 $rotation,
40 private ?float $totalTimeLeft,
41 private ?float $maximumRenderDistance,
42 private ?Color $color,
43 private ?int $dimensionId,
44 private ?int $attachedToEntityId,
45 private ?PrimitiveShapePayload $payload,
46 ){}
47
48 public static function remove(int $networkId, ?int $dimensionId = null) : self{
49 return new self($networkId, null, null, null, null, null, null, null, $dimensionId, null, null);
50 }
51
52 public static function line(int $networkId, Vector3 $location, Vector3 $lineEndLocation, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
53 return new self(
54 networkId: $networkId,
55 type: PrimitiveShapeType::LINE,
56 location: $location,
57 scale: null,
58 rotation: null,
59 totalTimeLeft: null,
60 maximumRenderDistance: null,
61 color: $color,
62 dimensionId: $dimensionId,
63 attachedToEntityId: $attachedToEntityId,
64 payload: new PrimitiveShapeLinePayload($lineEndLocation)
65 );
66 }
67
68 public static function box(int $networkId, Vector3 $location, Vector3 $boxBound, ?float $scale = null, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
69 return new self(
70 networkId: $networkId,
71 type: PrimitiveShapeType::BOX,
72 location: $location,
73 scale: $scale,
74 rotation: null,
75 totalTimeLeft: null,
76 maximumRenderDistance: null,
77 color: $color,
78 dimensionId: $dimensionId,
79 attachedToEntityId: $attachedToEntityId,
80 payload: new PrimitiveShapeBoxPayload($boxBound)
81 );
82 }
83
84 public static function sphere(int $networkId, Vector3 $location, int $segments, ?float $scale = null, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
85 return new self(
86 networkId: $networkId,
87 type: PrimitiveShapeType::SPHERE,
88 location: $location,
89 scale: $scale,
90 rotation: null,
91 totalTimeLeft: null,
92 maximumRenderDistance: null,
93 color: $color,
94 dimensionId: $dimensionId,
95 attachedToEntityId: $attachedToEntityId,
96 payload: new PrimitiveShapeCircleOrSpherePayload($segments)
97 );
98 }
99
100 public static function circle(int $networkId, Vector3 $location, int $segments, ?float $scale = null, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
101 return new self(
102 networkId: $networkId,
103 type: PrimitiveShapeType::CIRCLE,
104 location: $location,
105 scale: $scale,
106 rotation: null,
107 totalTimeLeft: null,
108 maximumRenderDistance: null,
109 color: $color,
110 dimensionId: $dimensionId,
111 attachedToEntityId: $attachedToEntityId,
112 payload: new PrimitiveShapeCircleOrSpherePayload($segments)
113 );
114 }
115
116 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{
117 return new self(
118 networkId: $networkId,
119 type: PrimitiveShapeType::TEXT,
120 location: $location,
121 scale: null,
122 rotation: null,
123 totalTimeLeft: null,
124 maximumRenderDistance: null,
125 color: $color,
126 dimensionId: $dimensionId,
127 attachedToEntityId: $attachedToEntityId,
128 payload: new PrimitiveShapeTextPayload($text, $useRotation, $backgroundColor, $depthTest, $showBackface, $showTextBackface)
129 );
130 }
131
132 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{
133 return new self(
134 networkId: $networkId,
135 type: PrimitiveShapeType::ARROW,
136 location: $location,
137 scale: $scale,
138 rotation: null,
139 totalTimeLeft: null,
140 maximumRenderDistance: null,
141 color: $color,
142 dimensionId: $dimensionId,
143 attachedToEntityId: $attachedToEntityId,
144 payload: new PrimitiveShapeArrowPayload($lineEndLocation, $arrowHeadLength, $arrowHeadRadius, $segments)
145 );
146 }
147
148 public static function cylinder(int $networkId, Vector3 $location, Vector2 $radiusX, Vector2 $radiusZ, float $height, int $segments, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
149 return new self(
150 networkId: $networkId,
151 type: PrimitiveShapeType::CYLINDER,
152 location: $location,
153 scale: null,
154 rotation: null,
155 totalTimeLeft: null,
156 maximumRenderDistance: null,
157 color: $color,
158 dimensionId: $dimensionId,
159 attachedToEntityId: $attachedToEntityId,
160 payload: new PrimitiveShapeCylinderPayload($radiusX, $radiusZ, $height, $segments)
161 );
162 }
163
164 public static function pyramid(int $networkId, Vector3 $location, float $width, float $height, ?float $depth = null, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
165 return new self(
166 networkId: $networkId,
167 type: PrimitiveShapeType::PYRAMID,
168 location: $location,
169 scale: null,
170 rotation: null,
171 totalTimeLeft: null,
172 maximumRenderDistance: null,
173 color: $color,
174 dimensionId: $dimensionId,
175 attachedToEntityId: $attachedToEntityId,
176 payload: new PrimitiveShapePyramidPayload($width, $depth, $height)
177 );
178 }
179
180 public static function ellipsoid(int $networkId, Vector3 $location, Vector3 $radii, int $segmentsPerAxis, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
181 return new self(
182 networkId: $networkId,
183 type: PrimitiveShapeType::ELLIPSOID,
184 location: $location,
185 scale: null,
186 rotation: null,
187 totalTimeLeft: null,
188 maximumRenderDistance: null,
189 color: $color,
190 dimensionId: $dimensionId,
191 attachedToEntityId: $attachedToEntityId,
192 payload: new PrimitiveShapeEllipsoidPayload($radii, $segmentsPerAxis)
193 );
194 }
195
196 public static function cone(int $networkId, Vector3 $location, Vector2 $radii, float $height, int $segments, ?Color $color = null, ?int $dimensionId = null, ?int $attachedToEntityId = null) : self{
197 return new self(
198 networkId: $networkId,
199 type: PrimitiveShapeType::CONE,
200 location: $location,
201 scale: null,
202 rotation: null,
203 totalTimeLeft: null,
204 maximumRenderDistance: null,
205 color: $color,
206 dimensionId: $dimensionId,
207 attachedToEntityId: $attachedToEntityId,
208 payload: new PrimitiveShapeConePayload($radii, $height, $segments)
209 );
210 }
211
212 public function getNetworkId() : int{ return $this->networkId; }
213
214 public function getType() : ?PrimitiveShapeType{ return $this->type; }
215
216 public function getLocation() : ?Vector3{ return $this->location; }
217
218 public function getScale() : ?float{ return $this->scale; }
219
220 public function getRotation() : ?Vector3{ return $this->rotation; }
221
222 public function getTotalTimeLeft() : ?float{ return $this->totalTimeLeft; }
223
224 public function getMaximumRenderDistance() : ?float{ return $this->maximumRenderDistance; }
225
226 public function getColor() : ?Color{ return $this->color; }
227
228 public function getDimensionId() : ?int{ return $this->dimensionId; }
229
230 public function getAttachedToEntityId() : ?int{ return $this->attachedToEntityId; }
231
232 public function getPayload() : ?PrimitiveShapePayload{ return $this->payload; }
233
234 public static function read(ByteBufferReader $in) : self{
235 $networkId = VarInt::readUnsignedLong($in);
236 $shapeType = CommonTypes::readOptional($in, fn() => PrimitiveShapeType::fromPacket(Byte::readUnsigned($in)));
237 $location = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
238 $scale = CommonTypes::readOptional($in, LE::readFloat(...));
239 $rotation = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
240 $totalTimeLeft = CommonTypes::readOptional($in, LE::readFloat(...));
241 $maximumRenderDistance = CommonTypes::readOptional($in, LE::readFloat(...));
242 $color = CommonTypes::readOptional($in, fn() => Color::fromARGB(LE::readUnsignedInt($in)));
243 $dimensionId = CommonTypes::readOptional($in, fn() => VarInt::readSignedInt($in));
244 $attachedToEntityId = CommonTypes::readOptional($in, fn() => CommonTypes::getActorRuntimeId($in));
245
246 $payloadType = VarInt::readUnsignedInt($in);
247 //WTF IS THIS HORROR SHOW
248 if(
249 ($shapeType !== null && $payloadType !== $shapeType->getPayloadType() && $payloadType !== PrimitiveShapeType::PAYLOAD_TYPE_NONE) ||
250 ($shapeType === null && $payloadType !== PrimitiveShapeType::PAYLOAD_TYPE_NONE)
251 ){
252 throw new PacketDecodeException("Unexpected payload type $payloadType for provided shape type " . ($shapeType->name ?? "(not set)"));
253 }
254
255 $payload = match($payloadType){
256 PrimitiveShapeType::PAYLOAD_TYPE_NONE => null,
257 PrimitiveShapeType::PAYLOAD_TYPE_ARROW => PrimitiveShapeArrowPayload::read($in),
258 PrimitiveShapeType::PAYLOAD_TYPE_TEXT => PrimitiveShapeTextPayload::read($in),
259 PrimitiveShapeType::PAYLOAD_TYPE_BOX => PrimitiveShapeBoxPayload::read($in),
260 PrimitiveShapeType::PAYLOAD_TYPE_LINE => PrimitiveShapeLinePayload::read($in),
261 PrimitiveShapeType::PAYLOAD_TYPE_CIRCLE_OR_SPHERE => PrimitiveShapeCircleOrSpherePayload::read($in),
262 PrimitiveShapeType::PAYLOAD_TYPE_CYLINDER => PrimitiveShapeCylinderPayload::read($in),
263 PrimitiveShapeType::PAYLOAD_TYPE_PYRAMID => PrimitiveShapePyramidPayload::read($in),
264 PrimitiveShapeType::PAYLOAD_TYPE_ELLIPSOID => PrimitiveShapeEllipsoidPayload::read($in),
265 PrimitiveShapeType::PAYLOAD_TYPE_CONE => PrimitiveShapeConePayload::read($in),
266 default => throw new PacketDecodeException("Unknown payload type $payloadType")
267 };
268
269 return new self(
270 $networkId,
271 $shapeType,
272 $location,
273 $scale,
274 $rotation,
275 $totalTimeLeft,
276 $maximumRenderDistance,
277 $color,
278 $dimensionId,
279 $attachedToEntityId,
280 $payload
281 );
282 }
283
284 public function write(ByteBufferWriter $out) : void{
285 VarInt::writeUnsignedLong($out, $this->networkId);
286 CommonTypes::writeOptional($out, $this->type, fn(ByteBufferWriter $out, PrimitiveShapeType $type) => Byte::writeUnsigned($out, $type->value));
287 CommonTypes::writeOptional($out, $this->location, CommonTypes::putVector3(...));
288 CommonTypes::writeOptional($out, $this->scale, LE::writeFloat(...));
289 CommonTypes::writeOptional($out, $this->rotation, CommonTypes::putVector3(...));
290 CommonTypes::writeOptional($out, $this->totalTimeLeft, LE::writeFloat(...));
291 CommonTypes::writeOptional($out, $this->maximumRenderDistance, LE::writeFloat(...));
292 CommonTypes::writeOptional($out, $this->color, fn(ByteBufferWriter $out, Color $color) => LE::writeUnsignedInt($out, $color->toARGB()));
293 CommonTypes::writeOptional($out, $this->dimensionId, fn(ByteBufferWriter $out, int $dimensionId) => VarInt::writeSignedInt($out, $dimensionId));
294 CommonTypes::writeOptional($out, $this->attachedToEntityId, fn(ByteBufferWriter $out, int $entityId) => CommonTypes::putActorRuntimeId($out, $entityId));
295
296 VarInt::writeUnsignedInt($out, $this->payload?->getTypeId() ?? PrimitiveShapeType::PAYLOAD_TYPE_NONE);
297 $this->payload?->write($out);
298 }
299}