Skip to content

Camera API

vape edited this page Sep 23, 2026 · 1 revision

Native Camera API

Amber exposes Bedrock's native camera system to plugins through Player::getCamera(). Plugins can register custom camera presets at startup, switch a player's view, apply transitions and effects, and make a camera track or follow an entity.

Quick start

Register presets from a startup-loaded plugin's onEnable(). The preset registry freezes before the server accepts connections.

use pocketmine\camera\preset\BuiltInCameraPresets;
use pocketmine\camera\preset\CameraPresetBuilder;
use pocketmine\camera\preset\CameraPresetRegistry;
use pocketmine\math\Vector2;

$orbit = (new CameraPresetBuilder("myplugin:orbit", BuiltInCameraPresets::FOLLOW_ORBIT))
    ->setRadius(8.0)
    ->setViewOffset(new Vector2(0.0, 1.5))
    ->build();

CameraPresetRegistry::getInstance()->register($orbit);

Then apply it to a player:

use pocketmine\camera\options\CameraEaseType;
use pocketmine\camera\options\CameraSetOptions;

$camera = $player->getCamera();
$ok = $camera->set("myplugin:orbit", CameraSetOptions::create()
    ->setEase(CameraEaseType::OUT_CUBIC, 1.0));

// Later, restore the perspective selected by the player.
$camera->clear();

set() returns false if the preset or requested options are unsupported by that client's protocol. An unknown preset identifier throws InvalidArgumentException. clear() also clears camera targeting and attachment where the client supports them.

Preset registry and inheritance

CameraPresetRegistry stores custom presets for the server:

Method Behavior
register(CameraPreset $preset) Adds a custom preset. Presets must be registered before the registry freezes.
get(string $identifier) Returns a registered custom preset or null.
isRegistered(string $identifier) Checks a custom or built-in identifier.
getRegisteredIdentifiers() Returns the custom preset identifiers.
freeze() / isFrozen() Validates and locks the registry; Amber freezes it during startup.

Custom identifiers must use the namespace:name form and cannot use the reserved minecraft namespace. A preset inherits from a built-in or another custom preset; unset properties keep the parent's values. The registry validates missing parents and inheritance cycles, orders parents before children, and allows up to 64 custom presets. Registration after freeze throws LogicException.

Amber rejects custom inheritance from minecraft:control_scheme_camera. Although it is sent as a built-in preset, using it as a custom preset's parent made the Bedrock 1.26.44 client close during testing. A custom camera with a control scheme can inherit from a compatible camera such as minecraft:follow_orbit or minecraft:free instead.

Built-in presets

Use the constants in BuiltInCameraPresets rather than repeating identifier strings:

Constant Identifier Minimum Bedrock version
FIRST_PERSON minecraft:first_person 1.20.0
FREE minecraft:free 1.20.0
THIRD_PERSON minecraft:third_person 1.20.0
THIRD_PERSON_FRONT minecraft:third_person_front 1.20.0
FOLLOW_ORBIT minecraft:follow_orbit 1.21.20
FIXED_BOOM minecraft:fixed_boom 1.21.50
CONTROL_SCHEME_CAMERA minecraft:control_scheme_camera 1.21.80

getPresetsForProtocol($protocolId) returns the built-ins available to a protocol; isAvailableOn() and getMinimumProtocol() can check one identifier.

Building custom presets

CameraPresetBuilder($identifier, $parent) and CameraPresetBuilder::create($identifier, $parent) create a mutable builder. build() returns a CameraPreset value object that can be registered. Vector values are copied, and numeric inputs are checked for finite values and valid ranges.

Builder method Preset behavior Minimum version for this field
setPosition(?Vector3) Default camera position (x, y, z). 1.20.0
setRotation(?float $pitch, ?float $yaw) Default pitch and yaw in degrees. Pitch must be -90 through 90. 1.20.0
setAudioListener(?CameraAudioListener) Places audio at the camera (CAMERA) or player (PLAYER). 1.20.10
setPlayerEffects(?bool) Controls whether player effects affect camera rendering. 1.20.10
setViewOffset(?Vector2) Offsets the camera view. 1.21.20
setRadius(?float) Sets the camera radius/distance used by its parent camera. 1.21.20
setRotationSpeed(?float) Sets target tracking rotation speed; non-negative. 1.21.30
setSnapToTarget(?bool) Snaps to the target at the start of tracking. 1.21.30
setEntityOffset(?Vector3) Offsets the camera relative to its target entity. 1.21.30
setHorizontalRotationLimit(?Vector2) Sets horizontal target-camera rotation limits. 1.21.40
setVerticalRotationLimit(?Vector2) Sets vertical target-camera rotation limits. 1.21.40
setContinueTargeting(?bool) Controls whether tracking continues after the target leaves a limit. 1.21.40
setBlockListeningRadius(?float) Sets the radius for camera block listening; non-negative. 1.21.50
setYawLimits(?float $min, ?float $max) Sets minimum and maximum yaw limits; minimum cannot exceed maximum. 1.21.60
setControlScheme(?CameraControlScheme) Selects the player's movement control scheme. 1.21.80

Each custom preset has an effective minimum version: the newer requirement of its own fields and its parent chain. Amber omits it from the camera catalog sent to older clients, so runtime preset indices stay aligned with each client's catalog.

Preset enums

  • CameraAudioListener: CAMERA, PLAYER.
  • CameraControlScheme: LOCKED_PLAYER_RELATIVE_STRAFE, CAMERA_RELATIVE, CAMERA_RELATIVE_STRAFE, PLAYER_RELATIVE, PLAYER_RELATIVE_STRAFE.

Applying a camera preset

PlayerCamera::set($presetIdentifier, ?CameraSetOptions) sends a preset instruction to one player. CameraSetOptions::create() supports:

Method Effect
setPosition(?Vector3) Overrides the preset's default position.
setRotation(float $pitch, float $yaw) Overrides rotation. Pitch is -90 through 90; yaw is normalized.
clearRotation() Removes the rotation override from these options.
setFacingPosition(?Vector3) Faces a world position instead of using an explicit rotation.
setViewOffset(?Vector2) Adds a view offset; requires Bedrock 1.21.20+.
setEntityOffset(?Vector3) Adds an entity offset; requires Bedrock 1.21.40+.
setEase(?CameraEaseType, float $durationSeconds) Eases the transition. A non-null type requires a positive duration; null removes easing.
setDefault(bool) When true, asks the client to use the preset's own default values.

Vectors must contain finite coordinates. For a smooth move to a location near the player:

use pocketmine\camera\preset\BuiltInCameraPresets;
use pocketmine\camera\options\CameraEaseType;
use pocketmine\camera\options\CameraSetOptions;

$position = $player->getPosition()->add(0, 5, -8);
$camera->set(BuiltInCameraPresets::FREE, CameraSetOptions::create()
    ->setPosition($position)
    ->setFacingPosition($player->getPosition())
    ->setEase(CameraEaseType::IN_OUT_CUBIC, 1.5));

CameraEaseType supports LINEAR, SPRING, and the IN_, OUT_, and IN_OUT_ variants of QUAD, CUBIC, QUART, QUINT, SINE, EXPO, CIRC, BOUNCE, BACK, and ELASTIC.

Tracking and attaching to entities

These are separate behaviors:

  • Targeting keeps the camera where it is and rotates it toward an entity. It is intended for a minecraft:free based camera.
  • Attachment moves the camera with an entity.

Both require an alive, open entity in the same world that is visible to the player. setTarget() also accepts an optional Vector3 center offset. Unsupported client versions or invisible entities return false; invalid entities and invalid offsets throw InvalidArgumentException.

use pocketmine\camera\preset\BuiltInCameraPresets;
use pocketmine\camera\options\CameraSetOptions;
use pocketmine\math\Vector3;

$camera->set(BuiltInCameraPresets::FREE, CameraSetOptions::create()
    ->setPosition($player->getPosition()->add(0, 4, -6))
    ->setFacingPosition($player->getPosition()));

if($camera->supportsTargeting() && $camera->setTarget($mob, new Vector3(0, 1, 0))){
    // Camera tracks the mob's position as its focus.
    $camera->clearTarget();
}

if($camera->supportsAttachment() && $camera->attachToEntity($mob)){
    // Camera now follows the mob's movement.
    $camera->detachFromEntity();
}

clearTarget() removes only the target; detachFromEntity() removes only the attachment. clear() resets the whole camera state supported by that client.

Fades, shake, and field of view

Fade

fade(CameraFadeOptions) fades the screen to a color and back. Defaults are black with 0.5 seconds fade-in, 1.0 second hold, and 0.5 seconds fade-out. Durations must be finite and non-negative.

use pocketmine\camera\options\CameraFadeOptions;
use pocketmine\color\Color;

$camera->fade(new CameraFadeOptions(new Color(0, 0, 0), 0.4, 0.8, 0.4));

Shake

shake($intensity, $durationSeconds, CameraShakeType) applies positional or rotational camera shake. Both numbers must be finite and non-negative. stopShake($type) stops that type; its default is POSITIONAL.

use pocketmine\camera\options\CameraShakeType;

$camera->shake(0.5, 1.2, CameraShakeType::POSITIONAL);
// Later:
$camera->stopShake(CameraShakeType::POSITIONAL);

Field of view

FOV instructions require Bedrock 1.21.100+. Check supportsFov() first. setFov() accepts 1 through 170 degrees, an optional non-negative duration, and an easing type. clearFov() restores 70 degrees; it accepts an optional CameraEase for the reset transition.

use pocketmine\camera\options\CameraEase;
use pocketmine\camera\options\CameraEaseType;

if($camera->supportsFov()){
    $camera->setFov(50.0, 0.6, CameraEaseType::OUT_CUBIC);
    // Later:
    $camera->clearFov(new CameraEase(CameraEaseType::LINEAR, 0.5));
}

PlayerCamera reference

Method Description
getPlayer() Returns the player controlled by this camera object.
getLastSetPreset() Returns the last preset successfully set through this object, or null.
supportsTargeting() True at Bedrock 1.21.20+.
supportsFov() True at Bedrock 1.21.100+.
supportsAttachment() True at Bedrock 1.21.120+.
set(...), clear() Set a preset or clear camera instructions.
fade(...), shake(...), stopShake(...) Apply and stop camera effects.
setFov(...), clearFov(...) Set or reset FOV when supported.
setTarget(...), clearTarget() Add or remove entity focus when supported.
attachToEntity(...), detachFromEntity() Add or remove entity attachment when supported.

Camera action methods return bool: true means Amber dispatched the packet, not that the client visibly applied it. The supports…() methods report protocol support, and getters return their documented values. Entity actions also require the entity to have been spawned to that player.

Clone this wiki locally