Skip to content

Latest commit

 

History

History
658 lines (391 loc) · 20.4 KB

File metadata and controls

658 lines (391 loc) · 20.4 KB
source

Extends DisposableObject

The core class for creating new types of components and attaching functionality to entities in a world.

export declare abstract class Component<TComponent = ComponentWithConstructor<Record<string, unknown>>, TSerializableState extends SerializableState = SerializableState> implements DisposableObject 

In the following example, the NpcItem class extends the Component class to define a new type of component. The new component type is then registered so new instances of the NpcItem can be created in the world.

import * as hz from 'horizon/core';

class NpcItem extends hz.Component<typeof NpcItem> {
  static propsDefinition = {};

  start() {}
}
hz.Component.register(NpcItem);

The Component class is an abstract class that you can extend to create new types of components that add properties and functionality to entities in your world. It provides properties and methods that manage the lifecycle of components, their relationship with attached entities, internal component data, and access to events including code block events.
When you create a new component in Desktop Editor, the editor generates a script that includes the following elements:
Component.propsDefinition - Defines internal properties for the class, which are also added to the Properties panel in Desktop Editor.
Component.start() - The method that executes when the class initially loads. This is where you can add event listeners that need to run when the script starts running.
Component.register() - The method that registers the new component class as a component definition that can be used to generate instances of the component in your world.
For more information about using components, see the Intro to Scripting tutorial, and the TypeScript Components, Properties, and Variables guide.

A set of asynchronous helper functions that are scoped to the component for automatic cleanup on dispose.

Signature

async: {
        setTimeout: (callback: TimerHandler, timeout?: number, ...args: unknown[]) => number;
        clearTimeout: (id: number) => void;
        setInterval: (callback: TimerHandler, timeout?: number, ...args: unknown[]) => number;
        clearInterval: (id: number) => void;
    };

Remarks

setTimeout - Sets a timer that executes a function or specified piece of code once the timer expires.clearTimeout - Cancels a timeout previously established by calling setTimeout().setInterval - Repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.clearInterval - Cancels a timed-repeating action that was previously established by a call to setInterval.

The entity the component is attached to.

Signature

readonly entity: Entity;

The ID of the entity the component is attached to.

Signature

readonly entityId: number;

The properties that modify the component.

Signature

readonly props: GetPropsFromComponentOrPropsDefinition<TComponent>;

The set of properties that define the available input and default values of the component.

Signature

static propsDefinition: {};

The World instance that contains the component.

Signature

readonly world: World;

Called when receiving the specified CodeBlockEvent instance from the Player or Entity object.

Signature

connectCodeBlockEvent<TEventArgs extends BuiltInVariableType[], TCallbackArgs extends TEventArgs>(target: Entity | Player, event: CodeBlockEvent<TEventArgs>, callback: (...payload: TCallbackArgs) => void): EventSubscription;

Parameters

target: Entity | Player

The entity or player to listen to.

event: CodeBlockEvent<TEventArgs>

The incoming CodeBlockEvent object.

callback: (...payload: TCallbackArgs) => void

Called when the event is received with any data as arguments.

Returns

EventSubscription

Examples

This example demonstrates how to receive a built-in CodeBlock event using the connectCodeBlockEvent method.

// Import CodeBlockEvents to access Built-in Events.
import { Component, CodeBlockEvents, Player } from 'horizon/core';

class BuiltInEventExample extends Component {
  start() {
    this.connectCodeBlockEvent(
     this.entity,
     CodeBlockEvents.OnIndexTriggerDown,
     (player: Player) => {
       // Perform an action when the Index Trigger is pressed.
     }
   );
     this.connectCodeBlockEvent (
       this.entity,
       CodeBlockEvents.OnGrabEnd,
       (player: Player) => {
       // Perform another action when the Grab Action ends.
     }
   );
 }
}

Component.register(BuiltInEventExample);

Remarks

This method is used to listen for a given code block event sent from the player or an entity.

Adds a listener to the specified local event. The listener is called when the event is received.

Signature

connectLocalBroadcastEvent<TPayload extends LocalEventData>(event: LocalEvent<TPayload>, listener: (payload: TPayload) => void): EventSubscription;

Parameters

event: LocalEvent<TPayload>

The local event to listen to.

listener: (payload: TPayload) => void

Called when the event is received with any data as arguments.

Returns

EventSubscription

Adds a listener to the local event on the given entity. The listener is called when the event is received.

Signature

connectLocalEvent<TPayload extends LocalEventData>(target: Entity | Player, event: LocalEvent<TPayload>, callback: (payload: TPayload) => void): EventSubscription;

Parameters

target: Entity | Player

The entity to listen to.

event: LocalEvent<TPayload>

The local event.

callback: (payload: TPayload) => void

Called when the event is received with any data as arguments.

Returns

EventSubscription

Adds a listener to the specified network event. The listener is called when the event is received from the network.

Signature

connectNetworkBroadcastEvent<TPayload extends NetworkEventData>(event: NetworkEvent<TPayload>, callback: (payload: TPayload) => void): EventSubscription;

Parameters

event: NetworkEvent<TPayload>

The network event to listen to.

callback: (payload: TPayload) => void

Called when the event is received with any data as arguments.

Returns

EventSubscription

Adds a listener to the specified network event on the given entity. The listener is called when the event is received from network.

Signature

connectNetworkEvent<TPayload extends NetworkEventData>(target: Entity | Player, event: NetworkEvent<TPayload>, callback: (payload: TPayload) => void): EventSubscription;

Parameters

target: Entity | Player

The entity or player to listen to.

event: NetworkEvent<TPayload>

The network event.

callback: (payload: TPayload) => void

Called when the event is received with any data as arguments.

Returns

EventSubscription

Called when the component is cleaned up.

Signature

dispose(): void;

Returns

void

Remarks

Subscriptions registered using , , , and are cleaned up automatically.

Returns a list of all script component instances of the specified type in the world. Only returns script component instances if they're executing in the same context (i.e. On the server or on a particular client). This method should not be used in prestart() as other script component instances may not yet be instantiated.

Signature

static getComponents<T extends Component<unknown, SerializableState> = Component>(type: new () => T): T[];

Parameters

type: new () => T

The specified type of Component.

Returns

T[]

A list of all active instances of the specified component type in the current execution context (i.e., on the server or on a particular client).

Performs initialization tasks before the method is called.

Signature

preStart(): void;

Returns

void

Remarks

This method runs in these scenarios as follows:World start: preStart runs for all components before the start method of any component is called. Asset spawn: preStart runs before any start methods are called for any components that are spawning. Ownership transfer: preStart is called directly before the start method is called.

Called when the script's ownership is being transferred to a new player. This method allows the new owner to receive the serializable state from the previous owner during ownership transfer.

Signature

receiveOwnership(_serializableState: TSerializableState | null, _oldOwner: Player, _newOwner: Player): void;

Parameters

_serializableState: TSerializableState | null

The serializable state from prior owner, or null if that state is invalid.

_oldOwner: Player

The prior owner.

_newOwner: Player

The current owner.

Returns

void

Examples

type State = {ammo: number};
class WeaponWithAmmo extends Component<typeof WeaponWithAmmo, State> {
  static propsDefinition = {
    initialAmmo: {type: PropTypes.Number, default: 20},
  };
  private ammo: number = 0;
  start() {
    this.ammo = this.props.initialAmmo;
  }
  receiveOwnership(state: State | null, fromPlayer: Player, toPlayer: Player) {
    this.ammo = state?.ammo ?? this.ammo;
  }
  transferOwnership(fromPlayer: Player, toPlayer: Player): State {
    return {ammo: this.ammo};
  }
}

Remarks

When changing entity ownership to a new player, you must transfer the state of the entity as well or the state will be lost. You can use the Component.transferOwnership() and Component.receiveOwnership() methods to transfer an entity's state to a new owner. For more information, see Maintaining local state on ownership change.If ownership for a parent entity changes, the ownership change doesn't automatically apply to any child entities.You must handle the edge case when the local state isn't transferred, such as the previous owner disconnecting from Horizon during a power or connectivity outage. In these cases, there's no guarantee that the entity's local state is transferred.The maximum size of state information that can be transferred is capped at 63kB. Transfers that are larger generate an error.

Registers a component class as a component definition that is used to instantiate components of the given type, which also allows them to be attached to entities.

Signature

static register<TComponentPropsDefinition>(componentClass: // this needs to be typed with the interface type so we know it can be instantiated (is not abstract)
    ComponentWithConstructor<TComponentPropsDefinition> & typeof Component<ComponentWithConstructor<TComponentPropsDefinition>>, componentName?: string): void;

Parameters

componentClass: ComponentWithConstructor<TComponentPropsDefinition> & typeof Component<ComponentWithConstructor<TComponentPropsDefinition>>

The component class to register.

componentName: string

(Optional) The name of component to display in the UI.

Returns

void

Examples

In this example, the NpcItem class is registered as a component definition.

hz.Component.register(NpcItem);

Remarks

Component registry is required when you create new classes that extend the abstract Component class.

Called to register a single operation. The operation runs automatically when the component is disposed unless it is manually run or canceled before the component is disposed.

Signature

registerDisposeOperation(operation: DisposeOperation): DisposeOperationRegistration;

Parameters

operation: DisposeOperation

A function called to perform a single dispose operation.

Returns

DisposeOperationRegistration

A registration object that can be used to manually run or cancel the operation before dispose.

Sends a code block event to the specified player or entity. These events are networked automatically, and sent and handled asynchronously.

Signature

sendCodeBlockEvent<TPayload extends BuiltInVariableType[]>(target: Entity | Player, event: CodeBlockEvent<TPayload>, ...args: TPayload): void;

Parameters

target: Entity | Player

The entity or player that receives the event.

event: CodeBlockEvent<TPayload>

The CodeBlockEvent that represents the event.

args: TPayload

The data to send with the event.

Returns

void

Sends a local event to all listeners.If a local event is sent, it is sent immediately. This function does not return until delivery completes.

Signature

sendLocalBroadcastEvent<TPayload extends LocalEventData, TData extends TPayload>(event: LocalEvent<TPayload>, data: TData): void;

Parameters

event: LocalEvent<TPayload>

The local event to send.

data: TData

Returns

void

Sends a local event to a specific entity from the owner of the entity.

Signature

sendLocalEvent<TPayload extends LocalEventData, TData extends TPayload>(target: Entity | Player, event: LocalEvent<TPayload>, data: TData): void;

Parameters

target: Entity | Player

The entity that receives the event.

event: LocalEvent<TPayload>

The local event to send.

data: TData

Returns

void

Remarks

The event is sent immediately and this function does not return until delivery completes.

Broadcasts a network event. The event is only handled if the host listens to the event.

Signature

sendNetworkBroadcastEvent<TPayload extends NetworkEventData>(event: NetworkEvent<TPayload>, data: TPayload, players?: Array<Player>): void;

Parameters

event: NetworkEvent<TPayload>

The network event to broadcast.

data: TPayload

The data to send with the event. the maximum amount data supported after serialization is 63kB.

players: Array<Player>

(Optional) The list of players devices to send the event to. If you do not specify this parameter, the event is sent to all devices owned by the player. You should only use this parameter if you are familiar with how it works.

Returns

void

Sends a network event to the player that owns the given entity.

Signature

sendNetworkEvent<TPayload extends NetworkEventData>(target: Entity | Player, event: NetworkEvent<TPayload>, data: TPayload, players?: Array<Player>): void;

Parameters

target: Entity | Player

The player or entity that recieves the event.

event: NetworkEvent<TPayload>

The network event.

data: TPayload

The data to send with the event. the maximum amount data after serialization is 63kB.

players: Array<Player>

(Optional) The list of player devices to send the event to. If you don't specify this parameter, the event is sent to all devices owned by the player. You should only use specify this parameter if you understand it well.

Returns

void

Remarks

The event is only handled if is called on the same entity on the owner client.

Called when the component starts running. This is where you can add event listeners that need to run when the script starts running.

Signature

abstract start(): void;

Returns

void

Called when transferring the script's ownership to a new player. During the transer, this method can condense the previous owner's state into a serializable format and pass it to the new owner.

Signature

transferOwnership(_oldOwner: Player, _newOwner: Player): TSerializableState;

Parameters

_oldOwner: Player

The original owner.

_newOwner: Player

The new owner.

Returns

TSerializableState

The serializable state to transfer to the new owner.

Examples

type State = {ammo: number};
class WeaponWithAmmo extends Component<typeof WeaponWithAmmo, State> {
  static propsDefinition = {
    initialAmmo: {type: PropTypes.Number, default: 20},
  };
  private ammo: number = 0;
  start() {
    this.ammo = this.props.initialAmmo;
  }
  receiveOwnership(state: State | null, fromPlayer: Player, toPlayer: Player) {
    this.ammo = state?.ammo ?? this.ammo;
  }
  transferOwnership(fromPlayer: Player, toPlayer: Player): State {
    return {ammo: this.ammo};
  }
}

Remarks

When changing entity ownership to a new player, you must transfer the state of the entity as well or the state will be lost. You can use the Component.transferOwnership() and Component.receiveOwnership() methods to transfer an entity's state to a new owner. For more information, see Maintaining local state on ownership change.If ownership for a parent entity changes, the ownership change doesn't automatically apply to any child entities.You must handle the edge case when the local state isn't transferred, such as the previous owner disconnecting from Horizon during a power or connectivity outage. In these cases, there's no guarantee that the entity's local state is transferred.The maximum size of state information that can be transferred is capped at 63kB. Transfers that are larger generate an error.