# How It Works

## The Canisters

**There are three types of canisters in the World Engine:**

1. **World canister:** The game server canister
2. **World Hub canister:** The indexing canister
3. **User Node canisters:** The user data canisters

<details>

<summary>World canister</summary>

A World canister is essentially your **game server** written as a canister smart contract. You can deploy your own through our website. Your game client communicates exclusively with this canister. Its main purpose is:

* Act as the game server for your game
* Manage the Configs of your game
* Validate the actions that players are doing in your game
* Ensure players aren’t cheating

</details>

<details>

<summary>World Hub</summary>

The World Hub indexes **World canisters** and **User Node canisters**. It tells the World canisters which User Node canister they need to call.

</details>

<details>

<summary>User Node</summary>

UserNode canisters store the data of all users. User data is stored as pieces of data called **Entities**.

</details>

***

## The Data

**There are four types of data stored across the World, World Hub, and User Nodes:**

1. **Action:** Actions enforce what players can do in your World
2. **Config:** Configs define metadata, usually about Entities
3. **Entity:** Entities are data representing the objects or things in a World
4. **Permissions:** Defines which Worlds have permission to alter Entities in your World

<details>

<summary>Action</summary>

An **Action** is something a player can do in your game that gets saved to the database.

***Example: If a player spends 100 Gold they receive 1 Sword***

### Action

This is what an Action looks like in code:

```motoko
    public type Action = 
    {
        aid : Text;
        callerAction : ?SubAction;
        targetAction : ?SubAction;
        worldAction : ?SubAction;
    };
```

* **aid:** The action id that identifies this specific Action
* **callerAction:** The SubAction to apply to the user calling the Action
* **targetAction:** The SubAction to apply to the user being targeted by the Action
* **worldAction:** The SubAction to apply to the World executing the Action<br>

### SubAction

This is what a SubAction looks like in code:

```motoko
    public type SubAction =
    {
        actionConstraint : ?ActionConstraint;
        actionResult : ActionResult;
    };
```

* **actionConstraint:** The requirements for a player to do this Action
* **actionResult:** The result of this Action

</details>

<details>

<summary>Config</summary>

A **Config** defines static metadata for your game. **Configs** are stored in the **World** canister, and are fetched by the Unity game client when the game starts. They can be changed in the canister without requiring a new game build. They look like this:

```motoko
public type Config = {
    cid : Text;
    fields : Map.Map<Text, Text>;
};
```

* **cid:** The config id for this Config
* **fields:** A hashmap of "fields" and values. This allows for flexibility to define whatever fields you want to store in this Config.

</details>

<details>

<summary>Entity</summary>

In its simplest definition, an **Entity** is a piece of data in the database. They look like this:

```motoko
    public type Entity = {
        wid : TGlobal.worldId;
        eid : TGlobal.entityId;
        fields : Map.Map<Text, Text>;
    };
```

* **wid:** The world id in which this entity exists (aka the canister id of the World canister)
* **eid:** The entity id that uniquely identifies this Entity (eg. awesome\_item\_01)
* **fields:** A hashmap of fields and values contained in the Entity

This standardized data format for Entities can represent almost any data type imaginable.

The most common use cases for **Entities** include **Items**, **Buffs**, and **Stats**. But they can be used for more complex data like **Characters, User Profiles, Purchases, Tech Tree** etc. &#x20;

Entities are the building blocks of your game economy.&#x20;

Here are some example implementations:

**Item Entity:**

```
{
 eid="item_01"                       //entity id
 wid="awcae-maaaa-aaaam-abmyq-cai"   //world id (aka the canister id of your world)
 fields = [
  ("quantity", "420"),             //quantity of item user holds
 ];
};
```

**Buff Entity:**

```
{
 eid="buff_01"
 wid="awcae-maaaa-aaaam-abmyq-cai"
 fields = [
  ("expiration", "1695954265797"),            // expiration timestamp
 ];
};
```

**Stat Entity:**

```
{
 eid="stat_01"
 wid="awcae-maaaa-aaaam-abmyq-cai"
 fields = [
  ("games_played", "420"),            
 ];
};
```

**Character Entity**:

```
{
 eid="warrior_01"
 wid="awcae-maaaa-aaaam-abmyq-cai"
 fields = [
  ("attack", "420"),
  ("defense", "69"),
  ("health", "9000"),            
 ];
};
```

</details>

<details>

<summary>Permissions</summary>

Permissions allow other games to alter your game's database.

There are two types of permissions:

**GlobalPermission** allows another game World to change all the Entities in your World.

```motoko
public type GlobalPermission = {
    wid : Text; // The World Id of the World that you're giving permission to
};
```

**EntityPermission** allows another game World to change a specific Entity in your World.

```motoko
public type EntityPermission = {
    wid : Text; // World Id of the World that you're giving permission to
    gid : Text; // Group Id of the Entity
    eid : Text; // Entity Id of the Entity
};
```

These are the functions in your World canister that allow you to add and remove permissions:

```motoko
public shared ({ caller }) func grantEntityPermission(permission : EntityPermission) : async () {
    assert (isAdmin_(caller));
    await worldHub.grantEntityPermission(permission);
};

public shared ({ caller }) func removeEntityPermission(permission : EntityPermission) : async () {
    assert (isAdmin_(caller));
    await worldHub.removeEntityPermission(permission);
};

public shared ({ caller }) func grantGlobalPermission(permission : GlobalPermission) : async () {
    assert (isAdmin_(caller));
    await worldHub.grantGlobalPermission(permission);
};

public shared ({ caller }) func removeGlobalPermission(permission : GlobalPermission) : async () {
    assert (isAdmin_(caller));
    await worldHub.removeGlobalPermission(permission);
};
```

</details>

***

**Below is a diagram of how game World canisters interact with the World Hub and User Node canisters:**

<img src="/files/Gglz55vGj3xl5ZsxLYpz" alt="" class="gitbook-drawing">

<figure><img src="/files/NOn9m6XXbpqhIxqiXmjX" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.boomdao.xyz/world-engine/how-it-works.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
