SDK Release 4.0.0

4.0.4

  • Adds Ethereum provider support. It uses the same provider as your browser. This is an experimental API, the behavior may change in the future.

    For the moment, we are only allowing a whitelisted set of RPC calls:

    • eth_sendTransaction
    • eth_getTransactionReceipt
    • eth_estimateGas
    • eth_call
    • eth_getBalance
    • eth_getStorageAt
    • eth_blockNumber
    • eth_gasPrice
    • eth_protocolVersion
    • net_version
    • eth_getTransactionCount
    • eth_getBlockByNumber

    In Future releases, we’ll be adding more limitations and verifications on top of this API

    import { createElement, ScriptableScene } from "decentraland-api-api"
    import Web3 = require("web3")
    
    export default class EthereumProvider extends ScriptableScene {
      async sceneDidMount() {
        const provider = await this.getEthereumProvider()
        const web3 = new Web3(provider)
    
        web3.eth.getBlock(48, function (error: Error, result: any) {
          console.log("Eth block 48 (from scene)", result)
        })
      }
    
      async render() {
        return <scene />
      }
    }
    

    IMPORTANT: The SDK works with version 0.20.6 of the Web3 library. It doesn’t currently support newer versions.

4.0.3

  • Fixes pointerEvents in preview scenes
  • Fixes transitions in scale component
  • Fixes the camera inertia, it was causing problems with Firefox
  • Adds it is now possible to toggle the colliders and bounding boxes in the preview using the key C and B
  • Adds a MessageBus between parcels, you can now send messages between users in the same scene

    import {
      createElement,
      ScriptableScene,
      MessageBusClient,
    } from "decentraland-api"
    
    export default class BoxFollower extends ScriptableScene {
      state = { elements: [] }
    
      async sceneDidMount() {
        // get an instance of a MessageBus for this scene
        const messageBus = await MessageBusClient.acquireEstateChannel(this)
    
        this.subscribeTo("pointerDown", (e) => {
          // every time we receive a pointerDown, we send that message thru the MessageBus,
          // in this case we are senging an event named `customPointerDown`
          messageBus.emit("customPointerDown", e)
        })
    
        messageBus.on("customPointerDown", (e) => {
          // everybody in the same parcel, even this MessageBus instance, receives the event
          const position = {
            x: e.from.x + e.direction.x,
            y: e.from.y + e.direction.y,
            z: e.from.z + e.direction.z,
          }
    
          const newBox = (
            <box
              position={position}
              scale={0.1}
              id={this.state.elements.length}
            />
          )
    
          this.setState({
            elements: this.state.elements.concat(newBox),
          })
        })
      }
    
      async render() {
        return <scene>{this.state.elements}</scene>
      }
    }
    
  • Adds a shadeless material, it is not affected by the light. It is useful to create pixel art scenes or user interfaces.

    <base-material
      id="test"
      texture="something.png"
      samplingMode={TextureSamplingMode.NEAREST}
      alphaTest={0.5}
    />
    
  • Adds lookAt component, allows you to handle the rotation of the entities without angles, instead, it is possible to specify a point in the space and the entity will be rotated to point in that direction.

    <box lookAt={{ x: 1, y: 10, z: 10 }} />
    

Breaking changes

  • Removed ignoreCollisions component. It is now required to manually specify the entities that will have collisions with the new component withCollisions
  • Material entity no longer sets up alpha automatically. If you want to create a transparent material you need to add the hasAlpha component.
    <material albedoTexture="semiTransparentTexture.png" hasAlpha />
    // or
    <material albedoTexture="semiTransparentTexture.png" alphaTexture="semiTransparentTexture.png" />
    

4.0.2

This release improves internals of the P2P communications and fix a critical rotation bug.

  • Fixes an important bug in rotations, now rotations behave exactly as they should, they mimic the behavior of Unity
  • Fixes transparency in albedo PNGs
  • Adds the axis in every <scene> in debug mode
  • Adds several properties to the <material> entity

4.0.1

This release contains several bugfixes and removes the spherical gaze from the center of the screen, instead, it introduces a clean white circle.

4.0.0

The version 4.0.0 introduces several major changes, those are breaking changes:

Migrated from Three.js to Babylon.js

Three.js was no powerful nor optimized enough to support the amount of elements and materials we wanted to handle. This migration also proves the idea behind the decoupling of the SDK, we managed to change the entire rendering engine without affecting the user scenes.

New material entity

Previously when you wanted to create and modify a material, you needed to specify it as a component of a entity like this:

import { createElement, ScriptableScene } from "decentraland-api"

export default class BoxFollower extends ScriptableScene {
  render() {
    return (
      <scene id="old_scene">
        <sphere material="map: some/url.png; alphaTest: 0.5" />
      </scene>
    )
  }
}

That leads to material duplications and special care with garbage collection in the engine; and to a super verbosic and not well decoupled code in the scene’s code.

We converted the material into an entity itself, now, the materials are using a PBR pipeline by default.

Here is how it looks now:

import { createElement, ScriptableScene } from "decentraland-api"

export default class BoxFollower extends ScriptableScene {
  async render() {
    return (
      <scene id="new_scene">
        <material
          id="reusable_material"
          albedoColor="some/url.png"
          roughness="0.5"
        />
        <sphere material="#reusable_material" />
      </scene>
    )
  }
}

Fixed the coordinate system

Previous to this release, we had a patch for the reference system. The Z axis was inverted inside the parcel in relation to the world-grid.

It means if an object was standing in the world position 55,55, it was in the parcel 5,-4. It is now in the parcel 5,5.

You need to be careful with this change since it inverts an entire axis, you might have to change the position of your entities.

Changes in the way to receive the users position

Previous to this version, you needed to execute await getMyPositionInEstate() to obtain the position of the user in the screen. Now you can subscribe to the positionChanged event.

import { createElement, ScriptableScene } from "decentraland-api"

export default class BoxFollower extends ScriptableScene {
  state = { position: { x: 0, y: 0, z: 0 } }

  async sceneDidMount() {
    this.subscribeTo("positionChanged", (e) => {
      this.setState({ position: e.position })
    })
  }

  async render() {
    return (
      <scene>
        <box position={this.state.position} ignoreCollisions />
      </scene>
    )
  }
}

In addition, we added the following events to the SDK

export type PointerEvent = {
  /** Origin of the ray */
  from: Vector3Component
  /** Direction vector of the ray (normalized) */
  direction: Vector3Component
  /** Length of the ray */
  length: number
  /** ID of the pointer that triggered the event */
  pointerId: number
}

export interface IEvents {
  /**
   * `positionChanged` is triggered when the position of the camera changes
   * This event is throttled to 10 times per second.
   */
  positionChanged: {
    /** Position relative to the base parcel of the scene */
    position: Vector3Component

    /** Camera position, this is a absolute world position */
    cameraPosition: Vector3Component

    /** Eye height, in meters. */
    playerHeight: number
  }

  /**
   * `rotationChanged` is triggered when the rotation of the camera changes.
   * This event is throttled to 10 times per second.
   */
  rotationChanged: {
    /** {X,Y,Z} Degree vector. Same as entities */
    rotation: Vector3Component
    /** Rotation quaternion, useful in some scenarios. */
    quaternion: Quaternion
  }

  /**
   * `setAttributes` is triggered after the system receives new properties.
   */
  setAttributes: {
    [key: string]: any
  }

  /**
   * `click` is triggered when a user points and the ray (from mouse or controller) hits the entity.
   * Notice: Only entities with ID will be listening for click events.
   */
  click: {
    /** ID of the entity of the event */
    elementId: string

    /** ID of the pointer that triggered the event */
    pointerId: number
  }

  /**
   * `pointerUp` is triggered when the user releases an input pointer.
   * It could be a VR controller, a touch screen or the mouse.
   */
  pointerUp: PointerEvent

  /**
   * `pointerDown` is triggered when the user press an input pointer.
   * It could be a VR controller, a touch screen or the mouse.
   */
  pointerDown: PointerEvent
}