Last updated: January 30th, 2019. Latest version here.

Services

You can find the files of the existing services under stonehearth/services.

About server and client

The server renders the logic of the game and is the source of truth regarding all things that happen in the world of Stonehearth: data about the hearthlings, the entities in the world around them, and functions that manipulate this information. The server is written primarily in C++ and Lua.

The client renders things that only matter to an individual player: the renderer, the on-screen UI, music and sounds, and the in-game UI used for things like item placement.

This structure is useful when you're playing multiplayer: the server runs on one computer, and clients run on each player's computer, and the clients update themselves with the state on the server, and send commands to the server when the player wants to do something. If 2 commands from 2 players conflict, the server handles the issue and tells all clients what the new state of the world is. When playing Stonehearth's singleplayer, you're essentially running both the server and client on one computer.

As a modder, when you're working on the UI, you're clearly working in the client. When you're working on AI or components, you're clearly working on the server. The place it gets tricky is when you're:

a.) trying to get data from the server into the UI. To do this you want to create a Handlebars template that will absorb the data and render it, and then create an object that will extract the relevant data for you from the server. See workshop or citizens view for examples.

b.) trying to render a ghost or other client-only game object into the world to help the player select where something will be. For more data on this read this page.

Adding a new service to the game

See stonehearth_tests_server.lua and stonehearth_tests_client.lua in the stonehearth_tests mod (comes bundled with the game) for an example of adding a new service.

If your service is a client service, create a client init script (you can see an example here. If it's a server service, a server init script.

For that, in your manifest you need to add one of this (or both if you have both a client and a server service):

  "server_init_script" : "file(my_server_init_script)",
  "client_init_script" : "file(my_client_init_script)"

They're at the same level than "aliases" or "mixintos".

icon Notice that for these we don't include the ".lua" extension when pointing to them. Please follow this syntax.

For example, in our server init script we have this:

  ui_mod = {}

  local service_creation_order = {
     { example = 'ui_mod.services.server.example.example_service' },
  }

  radiant.events.listen(ui_mod, 'radiant:init', function()
        radiant.service_creator.create_services(ui_mod, 'ui_mod', service_creation_order)
  end)

  return ui_mod

You want to add a listener that listens for the radiant:init event on your mod (ui_mod in the example above). This event is triggered right when your mod is created by the game.

Inside the callback function, you can call radiant.service_creator.create_services and pass in your mod, your mod namespace, and the list of services you want to create.

Once you've created your mod, you can access your service through the mod namespace, just like the stonehearth services. In the example above, we would call it like this:

  ui_mod.example:function_from_the_example_service()

It's the namespace of the mod, a dot, and the key we defined for the service in the service_creation_order variable. You can find the list of existing client / server services in stonehearth/data/constants.json.

Overriding existing services

To override an existing service, just add an override in the manifest that overrides the existing service's Lua file.