> For the complete documentation index, see [llms.txt](https://kinematicsoup.gitbook.io/reactor/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kinematicsoup.gitbook.io/reactor/tutorials/public_data.md).

# Publicly-Visible Data for Rooms

## Summary

Use public tags and data to share information to users before they connect to a server. This tutorial uses public data to report the number of connected users and uses public tags to mark empty rooms. You can use this to display the number of players in each room, or any other information you want, in your UI for picking a room to connect to.

### Requirements

* [Reactor Requirements](/reactor/overview.md#requirements)
* Completion of [Tutorial 1](/reactor/tutorials/basics.md)

## Setup

### Create a Room

1. Right click in the hierarachy window and create a **'Reactor->Room'** game object.

## Scripting

### Create a Server Room Script to Manage Public Data

The server room script stores the number of connected players in the room's public data, and adds or removes a public room tag named "empty" depending on if the the room is empty (has no connections) or not. This data is publically available without having to connect to the room in the response to a `ksReactor.GetServers` call.

> 'PublicData' *is a* ksJSON *object and can store anything you could store in JSON format.* 'PublicTags' *is a* ksHashSet *of* *strings. While* 'PublicData' *is more flexible in the types of data it can store,* 'PublicTags' *can be used with the cluster* *to filter rooms by tag, though that is outside the scope of this tutorial.*

1. Select the 'Room' object.
2. In the **'Add Component'** menu, select **'Reactor->New Server Room Script'**.
3. Name the script 'ServerRoom'.

*ServerRoom.cs*

```c#
using KS.Reactor.Server;
using KS.Reactor;

public class ServerRoom : ksServerRoomScript
{
    // Called when the script is attached.
    public override void Initialize()
    {
        Room.OnPlayerJoin += PlayerJoin;
        Room.OnPlayerLeave += PlayerLeave;
        UpdateConnections();
    }

    // Called when the script is detached.
    public override void Detached()
    {
        Room.OnPlayerJoin -= PlayerJoin;
        Room.OnPlayerLeave -= PlayerLeave;
    }

    // Called when a player connects.
    private void PlayerJoin(ksIServerPlayer player)
    {
        ksLog.Info("Player " + player.Id + " joined.");
        
        // Update the number of connections if this player is not a bot.
        if (!player.IsVirtual)
        {
            UpdateConnections();
        }
    }

    // Called when a player disconnects.
    private void PlayerLeave(ksIServerPlayer player)
    {
        ksLog.Info("Player " + player.Id + " left.");
        
        // Update the number of connections if this player is not a bot.
        if (!player.IsVirtual)
        {
            UpdateConnections();
        }
    }

    private void UpdateConnections()
    {
        // Set the number of connections in the public data. This is available in the response to ksService.GetRooms()
        // as ksRoomInfo.PublicData.
        Room.Info.PublicData["connections"] = Room.ConnectedPlayerCount;
        
        // Add or remove the "empty" tag depending on if the room has any connections. Tags are available in the
        // response to ksService.GetRooms() as ksRoomInfo.PublicTags.
        if (Room.ConnectedPlayerCount == 0)
        {
            Room.Info.PublicTags.Add("empty");
        }
        else
        {
            Room.Info.PublicTags.Remove("empty");
        }
    }
}
```

### Create a ConnectHandler Script

This script handles *ksConnect* events and polls the online services for an updated list of rooms every 10 seonds. When a list of rooms is fetched it will log a summary of the rooms, including the *'PublicTags'* and the number of connections we set in the *'PublicData'*. When **space** is pressed, it connects to the first room in the list, or disconnects if there is already a room connection.

1. Create a new *MonoBehaviour* named 'ConnectHandler'.
2. Attach it to the 'Room' game object.
3. Edit the file to match the code below.
4. Select the *ksConnect* component on the room and add the 'ConnectHandler' *'OnGetRooms'* method to the *ksConnect* *'OnGetRooms'* event list.
   * Click the '+' button in *ksConnect* *'OnGetRooms'* event list.
   * Drag the Room instance into the new object field.
   * Select *'ConnectHandler->OnGetRooms'* in the function selector.
5. Set the *ksConnect* 'Connect Mode' property to 'ONLINE'.

*ConnectHandler.cs*

```c#
using KS.Reactor;
using KS.Reactor.Client;
using KS.Reactor.Client.Unity;
using UnityEngine;

public class ConnectHandler : MonoBehaviour
{
    // How often to refresh the list of servers.
    private float m_refreshTime = 0f;

    // Room info to connect to.
    private ksRoomInfo m_roomInfo;

    // Handle room polling and connecting/disconnect keyboard events.
    private void Update()
    {
        ksConnect connect = GetComponent<ksConnect>();
        if (connect != null)
        {
            // When space is pressed, disconnect if we are connected, or connect if we aren't.
            if (Input.GetKeyDown(KeyCode.Space))
            {
                if (connect.Room != null && (connect.Room.IsConnected || connect.Room.IsConnecting))
                {
                    connect.Disconnect(false);
                }
                else if (m_roomInfo != null)
                {
                    connect.Connect(m_roomInfo);
                }
                else
                {
                    ksLog.Warning("No room to connect to.");
                }
            }

            // Every 10 seconds restart the connection process which starts with a request for a list
            // of all available rooms.
            m_refreshTime += Time.deltaTime;
            if (m_refreshTime >= 10f)
            {
                m_refreshTime = 0;
                connect.BeginConnect();
            }
        }
    }

    // Handler for ksConnect.OnGetRooms events.
    public void OnGetRooms(ksConnect.GetRoomsEvent e)
    {
        if (e.Status != ksBaseRoom.ConnectStatus.SUCCESS)
        {
            ksLog.Error(this, "Error fetching rooms: " + e.Error);
        }
        else if (e.Rooms == null || e.Rooms.Count == 0)
        {
            ksLog.Warning(this, "No rooms found.");
        }
        else
        {
            foreach (ksRoomInfo roomInfo in e.Rooms)
            {
                ksLog.Info(roomInfo.ToJSON().Print(true));
            }

            // Store the first room in the list. The Update method will use this room information when a room connection is created.
            m_roomInfo = e.Rooms[0];
        }
    }

    // Convert rooms tags to a readable string.
    private string PrintTags(ksHashSet<string> tags)
    {
        string str = "[";
        bool first = true;
        foreach (string tag in tags)
        {
            if (!first)
            {
                str += ", ";
            }
            first = false;
            str += tag;
        }
        str += "]";
        return str;
    }
}
```

## Testing

You cannot query a list of local servers to view their public data, so to test this you'll need to deploy live servers.

1. Open the **'Menu Bar->Reactor->Publishing'** menu.
2. Login using your KinematicSoup account.
3. Enter an image name and version in the form and click the **'Publish'** button.
4. Open the **'Menu Bar->Reactor->Servers'** menu.
5. Select your scene from the *'Scene'* dropdown.
6. Check the *'Is Public'* property and provide a name for this instance, then click the **'Launch Server'** button.
   * After a moment your server should appear in a list of running instances.
7. Once the server is started, select the room and change the *'Connect Mode'* property of the *ksConnect* component to 'ONLINE'.
8. Enter play mode. Every 10 seconds, you should see a summary of the running rooms in the Unity logs, which will include the number of connections and the tags. Click on the log entry to see the full summary. While you are not connected, it should show 0 connections and the tag "empty".
   * If you enter play mode before the server finishes launching, you will see a warning in the logs saying "No servers found.". Leave play mode and try again once the server is started.
9. Pressing **space** should connect you to the room. Pressing **space** again should disconnect you. While you are connected, the next time the room summary prints it should show 1 connection and no tags.
10. Once you are done testing, open the *'Servers'* window and stop the server instance.
