From 0692b70cf07b577a35eefad4a3cb6b3365e97f9c Mon Sep 17 00:00:00 2001 From: IvanCraft623 Date: Tue, 13 Jun 2023 08:14:13 -0500 Subject: [PATCH 1/7] Initial camera stuff Missing camera set --- src/data/CameraEaseTypeIdMap.php | 94 ++++++++++++++++ src/network/mcpe/NetworkSession.php | 20 ++++ .../mcpe/handler/PreSpawnPacketHandler.php | 5 +- .../handler/ResourcePacksPacketHandler.php | 2 +- src/player/Player.php | 5 + src/player/camera/CameraEaseType.php | 106 ++++++++++++++++++ src/player/camera/CameraPreset.php | 77 +++++++++++++ src/player/camera/CameraPresetFactory.php | 103 +++++++++++++++++ src/player/camera/VanillaCameraPresets.php | 65 +++++++++++ .../camera/instruction/CameraInstruction.php | 37 ++++++ .../instruction/ClearCameraInstruction.php | 37 ++++++ .../instruction/FadeCameraInstruction.php | 74 ++++++++++++ 12 files changed, 623 insertions(+), 2 deletions(-) create mode 100644 src/data/CameraEaseTypeIdMap.php create mode 100644 src/player/camera/CameraEaseType.php create mode 100644 src/player/camera/CameraPreset.php create mode 100644 src/player/camera/CameraPresetFactory.php create mode 100644 src/player/camera/VanillaCameraPresets.php create mode 100644 src/player/camera/instruction/CameraInstruction.php create mode 100644 src/player/camera/instruction/ClearCameraInstruction.php create mode 100644 src/player/camera/instruction/FadeCameraInstruction.php diff --git a/src/data/CameraEaseTypeIdMap.php b/src/data/CameraEaseTypeIdMap.php new file mode 100644 index 00000000000..93f9e7c91c5 --- /dev/null +++ b/src/data/CameraEaseTypeIdMap.php @@ -0,0 +1,94 @@ + + */ + private array $idToEnum = []; + /** + * @var string[] + * @phpstan-var array + */ + private array $enumToId = []; + + public function __construct(){ + $this->register("linear", CameraEaseType::LINEAR()); + $this->register("spring", CameraEaseType::SPRING()); + $this->register("in_quad", CameraEaseType::IN_QUAD()); + $this->register("out_quad", CameraEaseType::OUT_QUAD()); + $this->register("in_out_quad", CameraEaseType::IN_OUT_QUAD()); + $this->register("in_cubic", CameraEaseType::IN_CUBIC()); + $this->register("out_cubic", CameraEaseType::OUT_CUBIC()); + $this->register("in_out_cubic", CameraEaseType::IN_OUT_CUBIC()); + $this->register("in_quart", CameraEaseType::IN_QUART()); + $this->register("out_quart", CameraEaseType::OUT_QUART()); + $this->register("in_out_quart", CameraEaseType::IN_OUT_QUART()); + $this->register("in_quint", CameraEaseType::IN_QUINT()); + $this->register("out_quint", CameraEaseType::OUT_QUINT()); + $this->register("in_out_quint", CameraEaseType::IN_OUT_QUINT()); + $this->register("in_sine", CameraEaseType::IN_SINE()); + $this->register("out_sine", CameraEaseType::OUT_SINE()); + $this->register("in_out_sine", CameraEaseType::IN_OUT_SINE()); + $this->register("in_expo", CameraEaseType::IN_EXPO()); + $this->register("out_expo", CameraEaseType::OUT_EXPO()); + $this->register("in_out_expo", CameraEaseType::IN_OUT_EXPO()); + $this->register("in_circ", CameraEaseType::IN_CIRC()); + $this->register("out_circ", CameraEaseType::OUT_CIRC()); + $this->register("in_out_circ", CameraEaseType::IN_OUT_CIRC()); + $this->register("in_bounce", CameraEaseType::IN_BOUNCE()); + $this->register("out_bounce", CameraEaseType::OUT_BOUNCE()); + $this->register("in_out_bounce", CameraEaseType::IN_OUT_BOUNCE()); + $this->register("in_back", CameraEaseType::IN_BACK()); + $this->register("out_back", CameraEaseType::OUT_BACK()); + $this->register("in_out_back", CameraEaseType::IN_OUT_BACK()); + $this->register("in_elastic", CameraEaseType::IN_ELASTIC()); + $this->register("out_elastic", CameraEaseType::OUT_ELASTIC()); + $this->register("in_out_elastic", CameraEaseType::IN_OUT_ELASTIC()); + } + + public function register(string $stringId, CameraEaseType $type) : void{ + $this->idToEnum[$stringId] = $type; + $this->enumToId[$type->id()] = $stringId; + } + + public function fromId(string $id) : ?CameraEaseType{ + return $this->idToEnum[$id] ?? null; + } + + public function toId(CameraEaseType $type) : string{ + if(!array_key_exists($type->id(), $this->enumToId)){ + throw new \InvalidArgumentException("Missing mapping for camere ease type " . $type->name()); + } + return $this->enumToId[$type->id()]; + } +} diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 9053dd6b632..56dec1878e1 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -52,6 +52,8 @@ use pocketmine\network\mcpe\handler\SessionStartPacketHandler; use pocketmine\network\mcpe\handler\SpawnResponsePacketHandler; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; +use pocketmine\network\mcpe\protocol\CameraInstructionPacket; +use pocketmine\network\mcpe\protocol\CameraPresetsPacket; use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket; use pocketmine\network\mcpe\protocol\ClientboundPacket; use pocketmine\network\mcpe\protocol\DisconnectPacket; @@ -81,6 +83,7 @@ use pocketmine\network\mcpe\protocol\types\AbilitiesData; use pocketmine\network\mcpe\protocol\types\AbilitiesLayer; use pocketmine\network\mcpe\protocol\types\BlockPosition; +use pocketmine\network\mcpe\protocol\types\CacheableNbt; use pocketmine\network\mcpe\protocol\types\command\CommandData; use pocketmine\network\mcpe\protocol\types\command\CommandEnum; use pocketmine\network\mcpe\protocol\types\command\CommandParameter; @@ -94,6 +97,8 @@ use pocketmine\network\PacketHandlingException; use pocketmine\permission\DefaultPermissionNames; use pocketmine\permission\DefaultPermissions; +use pocketmine\player\camera\CameraPresetFactory; +use pocketmine\player\camera\instruction\CameraInstruction; use pocketmine\player\GameMode; use pocketmine\player\Player; use pocketmine\player\PlayerInfo; @@ -959,6 +964,17 @@ public function syncAdventureSettings() : void{ )); } + public function sendCameraPresets() : void { + $presetsTag = new ListTag(); + foreach (CameraPresetFactory::getInstance()->getAll() as $preset) { + $presetsTag->push($preset->toCompoundTag()); + } + + $this->sendDataPacket(CameraPresetsPacket::create( + new CacheableNbt(CompoundTag::create()->setTag("presets", $presetsTag)) + )); + } + public function syncAvailableCommands() : void{ $commandData = []; foreach($this->server->getCommandMap()->getCommands() as $name => $command){ @@ -1152,6 +1168,10 @@ public function onToastNotification(string $title, string $body) : void{ $this->sendDataPacket(ToastRequestPacket::create($title, $body)); } + public function onCameraInstruction(CameraInstruction $instruction) : void{ + $this->sendDataPacket(CameraInstructionPacket::create(new CacheableNbt($instruction->writeInstructionData(CompoundTag::create())))); + } + public function onOpenSignEditor(Vector3 $signPosition, bool $frontSide) : void{ $this->sendDataPacket(OpenSignPacket::create(BlockPosition::fromVector3($signPosition), $frontSide)); } diff --git a/src/network/mcpe/handler/PreSpawnPacketHandler.php b/src/network/mcpe/handler/PreSpawnPacketHandler.php index f80bacfc181..5dff939a089 100644 --- a/src/network/mcpe/handler/PreSpawnPacketHandler.php +++ b/src/network/mcpe/handler/PreSpawnPacketHandler.php @@ -83,7 +83,7 @@ public function setUp() : void{ $levelSettings->gameRules = [ "naturalregeneration" => new BoolGameRule(false, false) //Hack for client side regeneration ]; - $levelSettings->experiments = new Experiments([], false); + $levelSettings->experiments = new Experiments(["cameras" => true], true); $this->session->sendDataPacket(StartGamePacket::create( $this->player->getId(), @@ -129,6 +129,9 @@ public function setUp() : void{ $this->session->syncAbilities($this->player); $this->session->syncAdventureSettings(); + $this->session->getLogger()->debug("Sending camera presets"); + $this->session->sendCameraPresets(); + $this->session->getLogger()->debug("Sending effects"); foreach($this->player->getEffects()->all() as $effect){ $this->session->getEntityEventBroadcaster()->onEntityEffectAdded([$this->session], $this->player, $effect, false); diff --git a/src/network/mcpe/handler/ResourcePacksPacketHandler.php b/src/network/mcpe/handler/ResourcePacksPacketHandler.php index 7438fe47c1a..cc131516d54 100644 --- a/src/network/mcpe/handler/ResourcePacksPacketHandler.php +++ b/src/network/mcpe/handler/ResourcePacksPacketHandler.php @@ -134,7 +134,7 @@ public function handleResourcePackClientResponse(ResourcePackClientResponsePacke //we don't force here, because it doesn't have user-facing effects //but it does have an annoying side-effect when true: it makes //the client remove its own non-server-supplied resource packs. - $this->session->sendDataPacket(ResourcePackStackPacket::create($stack, [], false, ProtocolInfo::MINECRAFT_VERSION_NETWORK, new Experiments([], false))); + $this->session->sendDataPacket(ResourcePackStackPacket::create($stack, [], false, ProtocolInfo::MINECRAFT_VERSION_NETWORK, new Experiments(["cameras" => true], true))); $this->session->getLogger()->debug("Applying resource pack stack"); break; case ResourcePackClientResponsePacket::STATUS_COMPLETED: diff --git a/src/player/Player.php b/src/player/Player.php index 3083538be66..033d0969c57 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -115,6 +115,7 @@ use pocketmine\permission\DefaultPermissions; use pocketmine\permission\PermissibleBase; use pocketmine\permission\PermissibleDelegateTrait; +use pocketmine\player\camera\instruction\CameraInstruction; use pocketmine\player\chat\StandardChatFormatter; use pocketmine\Server; use pocketmine\timings\Timings; @@ -2095,6 +2096,10 @@ public function sendToastNotification(string $title, string $body) : void{ $this->getNetworkSession()->onToastNotification($title, $body); } + public function sendCameraInstruction(CameraInstruction $instruction) : void{ + $this->getNetworkSession()->onCameraInstruction($instruction); + } + /** * Sends a Form to the player, or queue to send it if a form is already open. * diff --git a/src/player/camera/CameraEaseType.php b/src/player/camera/CameraEaseType.php new file mode 100644 index 00000000000..819c80f7655 --- /dev/null +++ b/src/player/camera/CameraEaseType.php @@ -0,0 +1,106 @@ +identifier; + } + + public function getInheritFrom() : string{ + return $this->inheritFrom; + } + + public function getLocation() : ?Location{ + return $this->location; + } + + public function toCompoundTag() : CompoundTag{ + $tag = CompoundTag::create() + ->setString(self::TAG_IDENTIFIER, $this->identifier) + ->setString(self::TAG_INHERIT_FROM, $this->inheritFrom); + + if ($this->location !== null) { + $tag->setFloat(self::TAG_POSITION_X, $this->location->x) + ->setFloat(self::TAG_POSITION_Y, $this->location->y) + ->setFloat(self::TAG_POSITION_Z, $this->location->z) + + ->setFloat(self::TAG_ROTATION_YAW, $this->location->yaw) + ->setFloat(self::TAG_ROTATION_PITCH, $this->location->pitch); + } + + return $tag; + } + +} diff --git a/src/player/camera/CameraPresetFactory.php b/src/player/camera/CameraPresetFactory.php new file mode 100644 index 00000000000..6bbdcbf7699 --- /dev/null +++ b/src/player/camera/CameraPresetFactory.php @@ -0,0 +1,103 @@ + + */ + private array $presets = []; + + /** + * @var int[] + * @phpstan-var array + */ + private array $runtimeIds = []; + + private int $nextRuntimeId = 0; + + public function __construct(){ + $this->register(new CameraPreset("minecraft:first_person")); + $this->register(new CameraPreset("minecraft:third_person")); + $this->register(new CameraPreset("minecraft:third_person_front")); + $this->register(new CameraPreset("minecraft:free", "", new Location(0, 0, 0, null, 0, 0))); + } + + /** + * Registers a new camera preset type into the index. + * + * @throws \InvalidArgumentException + */ + public function register(CameraPreset $preset) : void{ + $id = $preset->getIdentifier(); + if ($this->isRegistered($id)) { + throw new \InvalidArgumentException("A presset with id \"$id\" is already registered"); + } + + $inheritFrom = $preset->getInheritFrom(); + if ($inheritFrom !== "" && !$this->isRegistered($inheritFrom)) { + throw new \InvalidArgumentException("Parent \"$inheritFrom\" preset is not registered"); + } + + $this->presets[$id] = $preset; + $this->presets[$id] = $nextRuntimeId++; + } + + public function fromId(string $identifier) : CameraPreset{ + if (!$this->isRegistered()) { + throw new \InvalidArgumentException("\"$identifier\" is not registered"); + } + + return $this->presets[$identifier]; + } + + public function getRuntimeId(string $identifier) : int{ + if (!$this->isRegistered()) { + throw new \InvalidArgumentException("\"$identifier\" is not registered"); + } + + return $this->runtimeIds[$identifier]; + } + + /** + * @return CameraPreset[] + * @phpstan-return array + */ + public function getAll() : array{ + return $this->presets; + } + + public function isRegistered(string $identifier) : bool{ + return isset($this->presets[$identifier]); + } +} diff --git a/src/player/camera/VanillaCameraPresets.php b/src/player/camera/VanillaCameraPresets.php new file mode 100644 index 00000000000..c1270d896f4 --- /dev/null +++ b/src/player/camera/VanillaCameraPresets.php @@ -0,0 +1,65 @@ + + */ + public static function getAll() : array{ + //phpstan doesn't support generic traits yet :( + /** @var CameraPreset[] $result */ + $result = self::_registryGetAll(); + return $result; + } + + protected static function setup() : void{ + $factory = CameraPresetFactory::getInstance(); + + self::register("first_person", $factory->fromId("minecraft:first_person")); + self::register("third_person", $factory->fromId("minecraft:third_person")); + self::register("third_person_front", $factory->fromId("minecraft:third_person_front")); + self::register("free", $factory->fromId("minecraft:free")); + } +} diff --git a/src/player/camera/instruction/CameraInstruction.php b/src/player/camera/instruction/CameraInstruction.php new file mode 100644 index 00000000000..4784da56f0d --- /dev/null +++ b/src/player/camera/instruction/CameraInstruction.php @@ -0,0 +1,37 @@ +setByte(self::TAG_CLEAR, 1); + + return $tag; + } +} diff --git a/src/player/camera/instruction/FadeCameraInstruction.php b/src/player/camera/instruction/FadeCameraInstruction.php new file mode 100644 index 00000000000..e3cb2c30397 --- /dev/null +++ b/src/player/camera/instruction/FadeCameraInstruction.php @@ -0,0 +1,74 @@ +color !== null) { + $fadeTag->setTag(self::TAG_COLOR, CompoundTag::create() + ->setFloat(self::TAG_COLOR_R, $this->color->getR() / 255) + ->setFloat(self::TAG_COLOR_G, $this->color->getG() / 255) + ->setFloat(self::TAG_COLOR_B, $this->color->getB() / 255) + //doesn't support alpha (opacity) :( + ); + } + + + $fadeTag->setTag(self::TAG_TIME, CompoundTag::create() + ->setFloat(self::TAG_FADE_IN, $this->fadeInSeconds) + ->setFloat(self::TAG_HOLD, $this->holdSeconds) + ->setFloat(self::TAG_FADE_OUT, $this->fadeOutSeconds) + ); + + + $tag->setTag(self::TAG_FADE, $fadeTag); + + return $tag; + } +} From 769279e110ff5a3765c0ac15da75182bbcdaed46 Mon Sep 17 00:00:00 2001 From: IvanCraft623 Date: Tue, 13 Jun 2023 15:26:46 -0500 Subject: [PATCH 2/7] Implement camera set instruction --- .../{ => bedrock}/CameraEaseTypeIdMap.php | 0 src/network/mcpe/NetworkSession.php | 1 + src/player/camera/CameraPreset.php | 24 ++--- src/player/camera/CameraPresetFactory.php | 11 +-- src/player/camera/VanillaCameraPresets.php | 6 +- src/player/camera/element/CameraEase.php | 45 ++++++++++ src/player/camera/element/CameraElement.php | 32 +++++++ src/player/camera/element/CameraState.php | 82 +++++++++++++++++ .../instruction/FadeCameraInstruction.php | 1 + .../instruction/SetCameraInstruction.php | 90 +++++++++++++++++++ 10 files changed, 276 insertions(+), 16 deletions(-) rename src/data/{ => bedrock}/CameraEaseTypeIdMap.php (100%) create mode 100644 src/player/camera/element/CameraEase.php create mode 100644 src/player/camera/element/CameraElement.php create mode 100644 src/player/camera/element/CameraState.php create mode 100644 src/player/camera/instruction/SetCameraInstruction.php diff --git a/src/data/CameraEaseTypeIdMap.php b/src/data/bedrock/CameraEaseTypeIdMap.php similarity index 100% rename from src/data/CameraEaseTypeIdMap.php rename to src/data/bedrock/CameraEaseTypeIdMap.php diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 56dec1878e1..86f41a9e8bb 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -33,6 +33,7 @@ use pocketmine\lang\Translatable; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; use pocketmine\network\mcpe\cache\ChunkCache; use pocketmine\network\mcpe\compression\CompressBatchPromise; diff --git a/src/player/camera/CameraPreset.php b/src/player/camera/CameraPreset.php index e2017d7afe5..5242d788207 100644 --- a/src/player/camera/CameraPreset.php +++ b/src/player/camera/CameraPreset.php @@ -23,6 +23,7 @@ namespace pocketmine\player\camera; +use pocketmine\player\camera\element\CameraState; use pocketmine\entity\Location; use pocketmine\nbt\tag\CompoundTag; @@ -41,7 +42,7 @@ final class CameraPreset{ public function __construct( private string $identifier, private string $inheritFrom = "", - private ?Location $location = null + private ?CameraState $state = null ){ } @@ -53,8 +54,8 @@ public function getInheritFrom() : string{ return $this->inheritFrom; } - public function getLocation() : ?Location{ - return $this->location; + public function getCameraState() : ?CameraState{ + return $this->state; } public function toCompoundTag() : CompoundTag{ @@ -62,13 +63,16 @@ public function toCompoundTag() : CompoundTag{ ->setString(self::TAG_IDENTIFIER, $this->identifier) ->setString(self::TAG_INHERIT_FROM, $this->inheritFrom); - if ($this->location !== null) { - $tag->setFloat(self::TAG_POSITION_X, $this->location->x) - ->setFloat(self::TAG_POSITION_Y, $this->location->y) - ->setFloat(self::TAG_POSITION_Z, $this->location->z) - - ->setFloat(self::TAG_ROTATION_YAW, $this->location->yaw) - ->setFloat(self::TAG_ROTATION_PITCH, $this->location->pitch); + if ($this->state !== null) { + if (($position = $this->state->getPosition()) !== null) { + $tag->setFloat(self::TAG_POSITION_X, $position->x) + ->setFloat(self::TAG_POSITION_Y, $position->y) + ->setFloat(self::TAG_POSITION_Z, $position->z); + } + if (($yaw = $this->state->getYaw()) !== null && ($pitch = $this->state->getPitch()) !== null) { + $tag->setFloat(self::TAG_ROTATION_YAW, $yaw) + ->setFloat(self::TAG_ROTATION_PITCH, $pitch); + } } return $tag; diff --git a/src/player/camera/CameraPresetFactory.php b/src/player/camera/CameraPresetFactory.php index 6bbdcbf7699..331108cfbac 100644 --- a/src/player/camera/CameraPresetFactory.php +++ b/src/player/camera/CameraPresetFactory.php @@ -23,7 +23,8 @@ namespace pocketmine\player\camera; -use pocketmine\entity\Location; +use pocketmine\player\camera\element\CameraState; +use pocketmine\math\Vector3; use pocketmine\utils\SingletonTrait; /** @@ -50,7 +51,7 @@ public function __construct(){ $this->register(new CameraPreset("minecraft:first_person")); $this->register(new CameraPreset("minecraft:third_person")); $this->register(new CameraPreset("minecraft:third_person_front")); - $this->register(new CameraPreset("minecraft:free", "", new Location(0, 0, 0, null, 0, 0))); + $this->register(new CameraPreset("minecraft:free", "", new CameraState(Vector3::zero(), 0, 0))); } /** @@ -70,11 +71,11 @@ public function register(CameraPreset $preset) : void{ } $this->presets[$id] = $preset; - $this->presets[$id] = $nextRuntimeId++; + $this->runtimeIds[$id] = $this->nextRuntimeId++; } public function fromId(string $identifier) : CameraPreset{ - if (!$this->isRegistered()) { + if (!$this->isRegistered($identifier)) { throw new \InvalidArgumentException("\"$identifier\" is not registered"); } @@ -82,7 +83,7 @@ public function fromId(string $identifier) : CameraPreset{ } public function getRuntimeId(string $identifier) : int{ - if (!$this->isRegistered()) { + if (!$this->isRegistered($identifier)) { throw new \InvalidArgumentException("\"$identifier\" is not registered"); } diff --git a/src/player/camera/VanillaCameraPresets.php b/src/player/camera/VanillaCameraPresets.php index c1270d896f4..ce9ddd14cc2 100644 --- a/src/player/camera/VanillaCameraPresets.php +++ b/src/player/camera/VanillaCameraPresets.php @@ -37,12 +37,16 @@ * @method static CameraPreset THIRD_PERSON_FRONT() */ final class VanillaCameraPresets{ - use CloningRegistryTrait; + use RegistryTrait; private function __construct(){ //NOOP } + protected static function register(string $name, CameraPreset $member) : void{ + self::_registryRegister($name, $member); + } + /** * @return CameraPreset[] * @phpstan-return array diff --git a/src/player/camera/element/CameraEase.php b/src/player/camera/element/CameraEase.php new file mode 100644 index 00000000000..a26bb691c3f --- /dev/null +++ b/src/player/camera/element/CameraEase.php @@ -0,0 +1,45 @@ +type; + } + + public function getDuration() : float{ + return $this->duration; + } +} diff --git a/src/player/camera/element/CameraElement.php b/src/player/camera/element/CameraElement.php new file mode 100644 index 00000000000..7399e44f032 --- /dev/null +++ b/src/player/camera/element/CameraElement.php @@ -0,0 +1,32 @@ +asVector3(), $location->yaw, $location->pitch); + } + + public static function lookingAt(Vector3 $position, Vector3 $target) : self{ + $horizontal = sqrt(($target->x - $position->x) ** 2 + ($target->z - $position->z) ** 2); + $vertical = $target->y - $position->y; + $pitch = -atan2($vertical, $horizontal) / M_PI * 180; //negative is up, positive is down + + $xDist = $target->x - $position->x; + $zDist = $target->z - $position->z; + + $yaw = atan2($zDist, $xDist) / M_PI * 180 - 90; + if($yaw < 0){ + $yaw += 360.0; + } + + return new self($position, $yaw, $pitch); + } + + public function getPosition() : ?Vector3{ + return $this->position; + } + + public function getYaw() : ?float{ + return $this->yaw; + } + + public function getPitch() : ?float{ + return $this->pitch; + } +} diff --git a/src/player/camera/instruction/FadeCameraInstruction.php b/src/player/camera/instruction/FadeCameraInstruction.php index e3cb2c30397..914cd3368e4 100644 --- a/src/player/camera/instruction/FadeCameraInstruction.php +++ b/src/player/camera/instruction/FadeCameraInstruction.php @@ -24,6 +24,7 @@ namespace pocketmine\player\camera\instruction; use pocketmine\color\Color; +use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\ByteTag; class FadeCameraInstruction implements CameraInstruction{ diff --git a/src/player/camera/instruction/SetCameraInstruction.php b/src/player/camera/instruction/SetCameraInstruction.php new file mode 100644 index 00000000000..3df66d75a08 --- /dev/null +++ b/src/player/camera/instruction/SetCameraInstruction.php @@ -0,0 +1,90 @@ + + + private const TAG_ROTATION = "rot"; //TAG_Compound + private const TAG_ROTATION_YAW = "yaw"; //TAG_Float + private const TAG_ROTATION_PITCH = "pitch"; //TAG_Float + + private const TAG_EASE = "ease"; //TAG_Compound + private const TAG_EASE_TYPE = "type"; //TAG_String + private const TAG_EASE_DURATION = "time"; //TAG_Float + + public function __construct( + private CameraPreset $preset, + private ?CameraState $state = null, + private ?CameraEase $ease = null + ) { + } + + public function writeInstructionData(CompoundTag $tag) : CompoundTag{ + $setTag = CompoundTag::create(); + + if ($this->state !== null) { + if (($position = $this->state->getPosition()) !== null) { + $setTag->setTag(self::TAG_POSITION, CompoundTag::create() //why use double position tag? mojang... + ->setTag(self::TAG_POSITION, new ListTag([ + new FloatTag($position->x), + new FloatTag($position->y), + new FloatTag($position->z) + ])) + ); + } + if (($yaw = $this->state->getYaw()) !== null && ($pitch = $this->state->getPitch()) !== null) { + $tag->setTag(self::TAG_ROTATION, CompoundTag::create() + ->setFloat(self::TAG_ROTATION_YAW, $yaw) + ->setFloat(self::TAG_ROTATION_PITCH, $pitch) + ); + } + } + + if ($this->ease !== null) { + $setTag->setTag(self::TAG_EASE, CompoundTag::create() + ->setFloat(self::TAG_EASE_DURATION, $this->ease->getDuration()) + ->setString(self::TAG_EASE_TYPE, CameraEaseTypeIdMap::getInstance()->toId($this->ease->getType())) + ); + } + + $setTag->setInt(self::TAG_PRESET, CameraPresetFactory::getInstance()->getRuntimeId($this->preset->getIdentifier())); + + return $tag->setTag(self::TAG_SET, $setTag); + } +} From e9dd78b799aa117237b89b549e832e63eeaf44cd Mon Sep 17 00:00:00 2001 From: IvanCraft623 Date: Tue, 13 Jun 2023 18:28:24 -0500 Subject: [PATCH 3/7] Little fixes - Fix fade color not being played correctyl (blame microsoft) - Fix rotation not being encoded correctly --- src/player/camera/instruction/FadeCameraInstruction.php | 6 ++++-- src/player/camera/instruction/SetCameraInstruction.php | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/player/camera/instruction/FadeCameraInstruction.php b/src/player/camera/instruction/FadeCameraInstruction.php index 914cd3368e4..1b08c4b283a 100644 --- a/src/player/camera/instruction/FadeCameraInstruction.php +++ b/src/player/camera/instruction/FadeCameraInstruction.php @@ -33,8 +33,10 @@ class FadeCameraInstruction implements CameraInstruction{ private const TAG_COLOR = "color"; //TAG_Compound private const TAG_COLOR_R = "r"; //TAG_Float - private const TAG_COLOR_G = "g"; //TAG_Float - private const TAG_COLOR_B = "b"; //TAG_Float + + /** TODO: Blue and green are swapped... */ + private const TAG_COLOR_G = "b"; //TAG_Float + private const TAG_COLOR_B = "g"; //TAG_Float private const TAG_TIME = "time"; //TAG_Compound private const TAG_FADE_IN = "fadeIn"; //TAG_Float diff --git a/src/player/camera/instruction/SetCameraInstruction.php b/src/player/camera/instruction/SetCameraInstruction.php index 3df66d75a08..917c5ead604 100644 --- a/src/player/camera/instruction/SetCameraInstruction.php +++ b/src/player/camera/instruction/SetCameraInstruction.php @@ -41,8 +41,8 @@ class SetCameraInstruction implements CameraInstruction{ private const TAG_POSITION = "pos"; //TAG_Compound & TAG_List private const TAG_ROTATION = "rot"; //TAG_Compound - private const TAG_ROTATION_YAW = "yaw"; //TAG_Float - private const TAG_ROTATION_PITCH = "pitch"; //TAG_Float + private const TAG_ROTATION_YAW = "y"; //TAG_Float + private const TAG_ROTATION_PITCH = "x"; //TAG_Float private const TAG_EASE = "ease"; //TAG_Compound private const TAG_EASE_TYPE = "type"; //TAG_String @@ -69,7 +69,7 @@ public function writeInstructionData(CompoundTag $tag) : CompoundTag{ ); } if (($yaw = $this->state->getYaw()) !== null && ($pitch = $this->state->getPitch()) !== null) { - $tag->setTag(self::TAG_ROTATION, CompoundTag::create() + $setTag->setTag(self::TAG_ROTATION, CompoundTag::create() ->setFloat(self::TAG_ROTATION_YAW, $yaw) ->setFloat(self::TAG_ROTATION_PITCH, $pitch) ); From c5493ef8101e3c82bd66563db41062b6dae99b73 Mon Sep 17 00:00:00 2001 From: IvanCraft623 Date: Tue, 13 Jun 2023 18:45:52 -0500 Subject: [PATCH 4/7] Allow multiple instructions in a single packet --- src/network/mcpe/NetworkSession.php | 9 +++++++-- src/player/Player.php | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 86f41a9e8bb..662dcbfc962 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -1169,8 +1169,13 @@ public function onToastNotification(string $title, string $body) : void{ $this->sendDataPacket(ToastRequestPacket::create($title, $body)); } - public function onCameraInstruction(CameraInstruction $instruction) : void{ - $this->sendDataPacket(CameraInstructionPacket::create(new CacheableNbt($instruction->writeInstructionData(CompoundTag::create())))); + public function onCameraInstruction(CameraInstruction ...$instructions) : void{ + $instructionsData = CompoundTag::create(); + foreach ($instructions as $instruction) { + $instruction->writeInstructionData($instructionsData); + } + + $this->sendDataPacket(CameraInstructionPacket::create(new CacheableNbt($instructionsData))); } public function onOpenSignEditor(Vector3 $signPosition, bool $frontSide) : void{ diff --git a/src/player/Player.php b/src/player/Player.php index 033d0969c57..06d2fcda885 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -2096,8 +2096,8 @@ public function sendToastNotification(string $title, string $body) : void{ $this->getNetworkSession()->onToastNotification($title, $body); } - public function sendCameraInstruction(CameraInstruction $instruction) : void{ - $this->getNetworkSession()->onCameraInstruction($instruction); + public function sendCameraInstruction(CameraInstruction ...$instructions) : void{ + $this->getNetworkSession()->onCameraInstruction(...$instructions); } /** From 43086f2771ce7767b6ff7a0cdcb972211887a29e Mon Sep 17 00:00:00 2001 From: IvanCraft623 Date: Tue, 13 Jun 2023 18:49:41 -0500 Subject: [PATCH 5/7] CS fix --- src/player/camera/CameraPreset.php | 3 +-- src/player/camera/CameraPresetFactory.php | 4 ++-- src/player/camera/element/CameraEase.php | 2 -- src/player/camera/element/CameraElement.php | 2 -- src/player/camera/element/CameraState.php | 3 --- src/player/camera/instruction/FadeCameraInstruction.php | 3 --- src/player/camera/instruction/SetCameraInstruction.php | 6 +++--- 7 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/player/camera/CameraPreset.php b/src/player/camera/CameraPreset.php index 5242d788207..d503a380a62 100644 --- a/src/player/camera/CameraPreset.php +++ b/src/player/camera/CameraPreset.php @@ -23,9 +23,8 @@ namespace pocketmine\player\camera; -use pocketmine\player\camera\element\CameraState; -use pocketmine\entity\Location; use pocketmine\nbt\tag\CompoundTag; +use pocketmine\player\camera\element\CameraState; final class CameraPreset{ diff --git a/src/player/camera/CameraPresetFactory.php b/src/player/camera/CameraPresetFactory.php index 331108cfbac..fb3b49efa15 100644 --- a/src/player/camera/CameraPresetFactory.php +++ b/src/player/camera/CameraPresetFactory.php @@ -23,8 +23,8 @@ namespace pocketmine\player\camera; -use pocketmine\player\camera\element\CameraState; use pocketmine\math\Vector3; +use pocketmine\player\camera\element\CameraState; use pocketmine\utils\SingletonTrait; /** @@ -46,7 +46,7 @@ final class CameraPresetFactory{ private array $runtimeIds = []; private int $nextRuntimeId = 0; - + public function __construct(){ $this->register(new CameraPreset("minecraft:first_person")); $this->register(new CameraPreset("minecraft:third_person")); diff --git a/src/player/camera/element/CameraEase.php b/src/player/camera/element/CameraEase.php index a26bb691c3f..fd506b8a612 100644 --- a/src/player/camera/element/CameraEase.php +++ b/src/player/camera/element/CameraEase.php @@ -23,9 +23,7 @@ namespace pocketmine\player\camera\element; -use pocketmine\data\bedrock\CameraEaseTypeIdMap; use pocketmine\player\camera\CameraEaseType; -use pocketmine\nbt\tag\CompoundTag; class CameraEase implements CameraElement{ diff --git a/src/player/camera/element/CameraElement.php b/src/player/camera/element/CameraElement.php index 7399e44f032..a195b7dcec0 100644 --- a/src/player/camera/element/CameraElement.php +++ b/src/player/camera/element/CameraElement.php @@ -23,8 +23,6 @@ namespace pocketmine\player\camera\element; -use pocketmine\nbt\tag\CompoundTag; - /** * Interface implemented by camera elements. */ diff --git a/src/player/camera/element/CameraState.php b/src/player/camera/element/CameraState.php index d7339699f6c..f6232a6bea5 100644 --- a/src/player/camera/element/CameraState.php +++ b/src/player/camera/element/CameraState.php @@ -23,11 +23,8 @@ namespace pocketmine\player\camera\element; -use pocketmine\data\bedrock\CameraEaseTypeIdMap; use pocketmine\entity\Location; -use pocketmine\player\camera\CameraEaseType; use pocketmine\math\Vector3; -use pocketmine\nbt\tag\CompoundTag; use function atan2; use function sqrt; use const M_PI; diff --git a/src/player/camera/instruction/FadeCameraInstruction.php b/src/player/camera/instruction/FadeCameraInstruction.php index 1b08c4b283a..40bfc94a51b 100644 --- a/src/player/camera/instruction/FadeCameraInstruction.php +++ b/src/player/camera/instruction/FadeCameraInstruction.php @@ -25,7 +25,6 @@ use pocketmine\color\Color; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\nbt\tag\ByteTag; class FadeCameraInstruction implements CameraInstruction{ @@ -61,7 +60,6 @@ public function writeInstructionData(CompoundTag $tag) : CompoundTag{ //doesn't support alpha (opacity) :( ); } - $fadeTag->setTag(self::TAG_TIME, CompoundTag::create() ->setFloat(self::TAG_FADE_IN, $this->fadeInSeconds) @@ -69,7 +67,6 @@ public function writeInstructionData(CompoundTag $tag) : CompoundTag{ ->setFloat(self::TAG_FADE_OUT, $this->fadeOutSeconds) ); - $tag->setTag(self::TAG_FADE, $fadeTag); return $tag; diff --git a/src/player/camera/instruction/SetCameraInstruction.php b/src/player/camera/instruction/SetCameraInstruction.php index 917c5ead604..cf37e0ee8d5 100644 --- a/src/player/camera/instruction/SetCameraInstruction.php +++ b/src/player/camera/instruction/SetCameraInstruction.php @@ -24,13 +24,13 @@ namespace pocketmine\player\camera\instruction; use pocketmine\data\bedrock\CameraEaseTypeIdMap; +use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\FloatTag; +use pocketmine\nbt\tag\ListTag; use pocketmine\player\camera\CameraPreset; use pocketmine\player\camera\CameraPresetFactory; use pocketmine\player\camera\element\CameraEase; use pocketmine\player\camera\element\CameraState; -use pocketmine\nbt\tag\CompoundTag; -use pocketmine\nbt\tag\FloatTag; -use pocketmine\nbt\tag\ListTag; class SetCameraInstruction implements CameraInstruction{ From 1041478a38576c3cb10bf01493fe8e6ab9f6ee3d Mon Sep 17 00:00:00 2001 From: IvanCraft623 Date: Tue, 13 Jun 2023 21:15:14 -0500 Subject: [PATCH 6/7] Fix code consistency --- src/player/camera/CameraEaseType.php | 50 ++++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/player/camera/CameraEaseType.php b/src/player/camera/CameraEaseType.php index 819c80f7655..cb2ccfbea11 100644 --- a/src/player/camera/CameraEaseType.php +++ b/src/player/camera/CameraEaseType.php @@ -31,38 +31,38 @@ * @see build/generate-registry-annotations.php * @generate-registry-docblock * - * @method static CameraEaseType LINEAR() - * @method static CameraEaseType SPRING() - * @method static CameraEaseType IN_QUAD() - * @method static CameraEaseType OUT_QUAD() - * @method static CameraEaseType IN_OUT_QUAD() + * @method static CameraEaseType IN_BACK() + * @method static CameraEaseType IN_BOUNCE() + * @method static CameraEaseType IN_CIRC() * @method static CameraEaseType IN_CUBIC() - * @method static CameraEaseType OUT_CUBIC() + * @method static CameraEaseType IN_ELASTIC() + * @method static CameraEaseType IN_EXPO() + * @method static CameraEaseType IN_OUT_BACK() + * @method static CameraEaseType IN_OUT_BOUNCE() + * @method static CameraEaseType IN_OUT_CIRC() * @method static CameraEaseType IN_OUT_CUBIC() - * @method static CameraEaseType IN_QUART() - * @method static CameraEaseType OUT_QUART() + * @method static CameraEaseType IN_OUT_ELASTIC() + * @method static CameraEaseType IN_OUT_EXPO() + * @method static CameraEaseType IN_OUT_QUAD() * @method static CameraEaseType IN_OUT_QUART() - * @method static CameraEaseType IN_QUINT() - * @method static CameraEaseType OUT_QUINT() * @method static CameraEaseType IN_OUT_QUINT() - * @method static CameraEaseType IN_SINE() - * @method static CameraEaseType OUT_SINE() * @method static CameraEaseType IN_OUT_SINE() - * @method static CameraEaseType IN_EXPO() - * @method static CameraEaseType OUT_EXPO() - * @method static CameraEaseType IN_OUT_EXPO() - * @method static CameraEaseType IN_CIRC() - * @method static CameraEaseType OUT_CIRC() - * @method static CameraEaseType IN_OUT_CIRC() - * @method static CameraEaseType IN_BOUNCE() - * @method static CameraEaseType OUT_BOUNCE() - * @method static CameraEaseType IN_OUT_BOUNCE() - * @method static CameraEaseType IN_BACK() + * @method static CameraEaseType IN_QUAD() + * @method static CameraEaseType IN_QUART() + * @method static CameraEaseType IN_QUINT() + * @method static CameraEaseType IN_SINE() + * @method static CameraEaseType LINEAR() * @method static CameraEaseType OUT_BACK() - * @method static CameraEaseType IN_OUT_BACK() - * @method static CameraEaseType IN_ELASTIC() + * @method static CameraEaseType OUT_BOUNCE() + * @method static CameraEaseType OUT_CIRC() + * @method static CameraEaseType OUT_CUBIC() * @method static CameraEaseType OUT_ELASTIC() - * @method static CameraEaseType IN_OUT_ELASTIC() + * @method static CameraEaseType OUT_EXPO() + * @method static CameraEaseType OUT_QUAD() + * @method static CameraEaseType OUT_QUART() + * @method static CameraEaseType OUT_QUINT() + * @method static CameraEaseType OUT_SINE() + * @method static CameraEaseType SPRING() */ final class CameraEaseType{ use EnumTrait; From a726c19784af9264b1e9d9954a8d4e698776eb5a Mon Sep 17 00:00:00 2001 From: IvanCraft623 Date: Tue, 13 Jun 2023 21:17:24 -0500 Subject: [PATCH 7/7] Remove useless return value --- src/player/camera/instruction/CameraInstruction.php | 2 +- src/player/camera/instruction/ClearCameraInstruction.php | 4 +--- src/player/camera/instruction/FadeCameraInstruction.php | 4 +--- src/player/camera/instruction/SetCameraInstruction.php | 4 ++-- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/player/camera/instruction/CameraInstruction.php b/src/player/camera/instruction/CameraInstruction.php index 4784da56f0d..e793c66e3d3 100644 --- a/src/player/camera/instruction/CameraInstruction.php +++ b/src/player/camera/instruction/CameraInstruction.php @@ -33,5 +33,5 @@ interface CameraInstruction{ /** * Writes this instriction in a CompoundTag in order to be sent to the client. */ - public function writeInstructionData(CompoundTag $tag) : CompoundTag; + public function writeInstructionData(CompoundTag $tag) : void; } diff --git a/src/player/camera/instruction/ClearCameraInstruction.php b/src/player/camera/instruction/ClearCameraInstruction.php index 52db9edac75..7889e6bcadf 100644 --- a/src/player/camera/instruction/ClearCameraInstruction.php +++ b/src/player/camera/instruction/ClearCameraInstruction.php @@ -29,9 +29,7 @@ class ClearCameraInstruction implements CameraInstruction{ private const TAG_CLEAR = "clear"; //TAG_Byte - public function writeInstructionData(CompoundTag $tag) : CompoundTag{ + public function writeInstructionData(CompoundTag $tag) : void{ $tag->setByte(self::TAG_CLEAR, 1); - - return $tag; } } diff --git a/src/player/camera/instruction/FadeCameraInstruction.php b/src/player/camera/instruction/FadeCameraInstruction.php index 40bfc94a51b..19a8816ba23 100644 --- a/src/player/camera/instruction/FadeCameraInstruction.php +++ b/src/player/camera/instruction/FadeCameraInstruction.php @@ -50,7 +50,7 @@ public function __construct( ) { } - public function writeInstructionData(CompoundTag $tag) : CompoundTag{ + public function writeInstructionData(CompoundTag $tag) : void{ $fadeTag = CompoundTag::create(); if ($this->color !== null) { $fadeTag->setTag(self::TAG_COLOR, CompoundTag::create() @@ -68,7 +68,5 @@ public function writeInstructionData(CompoundTag $tag) : CompoundTag{ ); $tag->setTag(self::TAG_FADE, $fadeTag); - - return $tag; } } diff --git a/src/player/camera/instruction/SetCameraInstruction.php b/src/player/camera/instruction/SetCameraInstruction.php index cf37e0ee8d5..260932211e4 100644 --- a/src/player/camera/instruction/SetCameraInstruction.php +++ b/src/player/camera/instruction/SetCameraInstruction.php @@ -55,7 +55,7 @@ public function __construct( ) { } - public function writeInstructionData(CompoundTag $tag) : CompoundTag{ + public function writeInstructionData(CompoundTag $tag) : void{ $setTag = CompoundTag::create(); if ($this->state !== null) { @@ -85,6 +85,6 @@ public function writeInstructionData(CompoundTag $tag) : CompoundTag{ $setTag->setInt(self::TAG_PRESET, CameraPresetFactory::getInstance()->getRuntimeId($this->preset->getIdentifier())); - return $tag->setTag(self::TAG_SET, $setTag); + $tag->setTag(self::TAG_SET, $setTag); } }