Sending Messages - Silverfeelin/Starbound-MessageHandling-Demo GitHub Wiki

To send messages to yourself or other entities, use world.sendEntityMessage.
Remote messages are asynchronous, meaning the result of the message will be available at a later time. Local messages are synchronous, for more information see RpcPromise.

As per the documentation, messages shouldn't be sent on init as things are still being initialized at that point.

The function takes 2 up to an indefinite amount of arguments:

world.sendEntityMessage(entityId, messageType, ...)
  • entityId

The entity id. For example, entity.id() or player.id() for your own entity. You should have a look at the world.entityQuery documentation if you don't know how to find other entities.

You can also use the UUID of the entity.

  • messageType

The message to send. This message should match the one set up in Receiving Messages.

  • args

Zero or more arguments can be added to pass to the message handler.

This can be any serializable data, such as strings and numbers. Tables are also supported as long as they don't contain any non-serializable data such as functions.

world.sendEntityMessage(entityId, messageType, "foo")
world.sendEntityMessage(entityId, messageType, "foo", "bar")
world.sendEntityMessage(entityId, messageType, { foo = "bar" })
  • return value

The function returns an RpcPromise object that can be used to receive the response at a later time. If the message is handled asynchronously, simply checking the result after sending the message won't work.

You can use a PromiseKeeper, or keep track of the promises yourself.

Never busy-wait for a response if you're not absolutely certain the message is only handled locally (i.e. while not promise:finished() do end! This will freeze up your script (and possibly your entire game) until the promise finishes.

If your message doesn't expect a response, you may still want to use the promise to ensure the message has been handled. If you don't care about this, you can ignore the return value.

Example

When sendMessage is called, it will send the message "multiply" to the player. The promise is stored and checked each frame in the update function. Once finished, the result will be used to log a message and the promise is discarded.

local promise

function update()
  -- Wait for promise to finish without freezing this script up by busy-waiting.
  if promise and promise:finished() then
    if promise:succeeded() then
      sb.logInfo("5 * 10 = %s", promise:result())
    else
      sb.logWarn("Couldn't multiply 5 by 10")
    end
    promise = nil
  end
end

-- You'd have to call this at some point (not on init!)
function sendMessage()
  local id = entity.id()
  promise = world.sendEntityMessage(id, "multiply", 5, 10)
end

We now have a problem; if we want to multiply various values, it's hard to keep track of which response belongs to which message. You can figure out how to solve this on your own, but the PromiseKeeper offers a solution out of the box.