# Server-authoritative setup

Sometimes, distributing authority is not the way to go. Certain types of games require a model where the server (or, we should say, the [**Simulator**](https://docs.coherence.io/manual/simulation-server)) is in control of the simulation of the whole game, and the players only send inputs to it. The Simulator elaborates these inputs, and in response updates the Client about the new game state.

This way of doing things is usually referred to as **server-authoritative**.

## When to use a server-authoritative setup?

* **In competitive games**. Many game genres use client inputs and centralized simulation to guarantee the fairness of actions or the stability of physics simulations.
* **In situations where Clients have low processing power**. If the Clients don't have sufficient processing power to simulate the World it makes sense to send inputs and just display the replicated results on the Clients.
* **In situations where determinism is important**. RTS and fighting games can use **CoherenceInput** component and [rollback](https://docs.coherence.io/manual/advanced-topics/competitive-games/determinism-prediction-rollback) to process input events in a shared (not centralized) and deterministic way so that all Clients simulate the same conditions and produce the same results.

{% hint style="info" %}
**coherence** currently only supports using **CoherenceInput** in a centralized way, where a single Simulator is setup to process all inputs and replicate the results to all Clients.
{% endhint %}

## Setup CoherenceInput

Setting up an object for server-side simulation using [**CoherenceInput**](https://docs.coherence.io/manual/components/coherenceinput) is done in **three** steps:

### 1. Set the Simulation type

The *Simulate* property needs to be set to *Server Side with Client Input.*

<figure><img src="https://content.gitbook.com/content/CMCtKgV0bk1lwR4tWK3W/blobs/7Fs93Z7UDcckv92vOzpW/image.png" alt=""><figcaption><p>The "Server Side With Client Input" option in CoherenceSync Inspector</p></figcaption></figure>

At this point, a **CoherenceInput** component is automatically added to the object.

Setting the simulation type to this mode instructs the Client to automatically transfer **State Authority** for this object to the [Simulator](https://docs.coherence.io/manual/simulation-server) that is in charge of simulating inputs on all objects, and only retain **Input Authority**.

### 2. Declaring Inputs

Each simulated **CoherenceSync** component is able to define its own, unique set of inputs via the **CoherenceInput** interface.

An input can be of types:

* **Button**. A button input is tracked with just a binary on/off state.
* **Axis / Axis2D / Axis3D**. An axis input is tracked as one/two/three floats from -1 to 1.
* **String**. A string value representing custom input state. (max length of 63 characters)
* **Rotation**. A rotation is represented by a Quaternion.
* **Integer**. Represented as an int.

![Two inputs have been added, named Move and Shoot](https://content.gitbook.com/content/CMCtKgV0bk1lwR4tWK3W/blobs/TcPergaR15SafCO0yirE/CoherenceInput.png)

### **3. Bake the netcode**

In order for the inputs to be used, they must be [baked](https://docs.coherence.io/manual/baking-and-code-generation).

{% hint style="info" %}
If the **CoherenceInput** fields or name is changed, then the **CoherenceSync** object must be re-baked to reflect the new fields/values.
{% endhint %}

## Using CoherenceInput

When a Simulator is running it will find objects that are set up using **CoherenceInput** components and will automatically take over State Authority, and start simulating them.

During gameplay, scripts from both the Client and Simulator work with the inputs defined on the **CoherenceInput** of the replicated object: the Client uses the `Set*` methods to set input values, and the Simulator uses the `Get*` methods to access them.

In all of these methods, the `name` parameter is the same as the **Name** field defined on the **CoherenceInput** component.

{% hint style="info" %}
Check the [CoherenceInput API](https://unityapi.coherence.io/docs/v2.1.0/api/Coherence.Toolkit.CoherenceInput.html) for a complete list of the available methods.
{% endhint %}

Here's an example of a Player using CoherenceInput, reading input from Unity's legacy Input Manager:

```csharp
public class Player : MonoBehaviour
{
    public CoherenceSync coherenceSync;

    void Awake()
    {
        coherenceSync = GetComponent<CoherenceSync>();
    }

    void Update()
    {
        // This code will run on the client
        if (coherenceSync.HasInputAuthority)
        {
            SendInputs();
        }

        // This code will run on the simulator
        if (coherenceSync.HasStateAuthority)
        {
            ProcessInputs();
        }
    }

    void SendInputs()
    {
        var jump = Input.GetButton("Jump");
        coherenceSync.Input.SetButton("Jump", jump);

        var moveX = Input.GetAxis("Horizontal");
        var moveY = Input.GetAxis("Vertical");
        var move = new Vector2(moveX, moveY);
        coherenceSync.Input.SetAxis2D("Move", move);
    }

    void ProcessInputs()
    {
        var jump = coherenceSync.Input.GetButton("Jump");
        /* Apply jumping logic here */

        var move = coherenceSync.Input.GetAxis2D("Move");
        /* Apply movement logic here */
    }
}
```

## Input Authority

Each object only accepts inputs from one specific Client, called the object's **Input Authority**.

When a Client spawns an object it automatically becomes the **Input Authority** for that object. The object's creator will retain control over the object even after State Authority has been transferred to the Simulator.

If an object is spawned directly by the Simulator, you will need to assign the **Input Authority** manually. Use the `TransferAuthority` method on the **CoherenceSync** component to assign or re-assign a Client that will take control of the object:

```csharp
public void AssignNewInputAuthority(CoherenceClientConnection newInputOwner)
{
    var coherenceSync = GetComponent<CoherenceSync>();
    coherenceSync.TransferAuthority(newInputOwner.ClientId, AuthorityType.Input);
}
```

The **ClientId** used to specify Input Authority can currently only be accessed from the **ClientConnection** class. For detailed information about setting up the ClientConnection Prefab, see the [Client Connections](https://docs.coherence.io/manual/client-connections) page.

{% hint style="info" %}
Use the `OnInputAuthority` and `OnInputRemote` events on the `CoherenceSync` component to be notified whenever an object changes input authority.
{% endhint %}

{% hint style="warning" %}
Only the object's current State Authority is allowed to transfer Input Authority.
{% endhint %}

Additionally, it is possible to send a [command](https://docs.coherence.io/manual/networking-state-changes/commands) directly to the input authority using the `MessageTarget.InputAuthorityOnly` message target in the send command parameters. This allows Clients to communicate with the input "owner" of an entity even when the state "owner" is a different Client or Simulator.

The `OnInputSimulatorConnected` event can also be raised on the Simulator or host if they have both Input and State Authority over an entity. This allows the session host to use inputs just like any other client but might be undesirable if input entities are created on the host and then have their Input Authority transferred to the clients.

To solve this you can check the **CoherenceSync.IsSimulatorOrHost** flag in the callback:

```csharp
coherenceSync.OnInputSimulatorConnected.AddListener(() =>
{
    if (coherenceSync.Bridge.IsSimulatorOrHost)
    {
        // Ignore for Simulators and hosts.
        return;
    }

    // Insert your game logic here
    Debug.Log("Input ready for use!");
});
```

## Client-side prediction

Compared to Client-side simulation, server-side simulation takes a **significantly longer time** from the Client providing input until the game state is updated. That's because of the time required for the input to be sent to the Simulator, processed, and then the updates to the object returned across the network. This round-trip time results in an **input lag** that can make controls feel awkward and slow to respond.

If you want to use a server-authoritative setup without sacrificing input responsiveness, you need to use Client-side prediction.

With Client-side prediction is enabled for a binding, **incoming network data is ignored**, allowing the Client to calculate (predict) its value locally. A typical use case is to predict position and rotation for the local player, but you can toggle Client-side prediction for any binding in the *Configuration* window:

<figure><img src="https://content.gitbook.com/content/CMCtKgV0bk1lwR4tWK3W/blobs/mMHrFar5CxDE0GwBYPZT/OnlyPredictWithInputAuth.png" alt="" width="563"><figcaption><p>The position binding will be predicted only if the object has Input authority</p></figcaption></figure>

By processing inputs both on the Client and on the server, the Client can make a prediction of where the player is heading without having to wait for the authoritative server response. This provides immediate input feedback and a more responsive playing experience.

Note that inputs should not be processed for Clients that neither have **State Authority** nor **Input Authority**. That's because we can only predict the local player; remote players and other networked objects are synced just as normal.

```csharp
public void Update()
{
    if (coherenceSync.HasStateAuthority || coherenceSync.HasInputAuthority)
    {
        ProcessMousePosition();
    }

    if (coherenceSync.HasInputAuthority)
    {
        SendMousePosition();
    }
}
```

### Misprediction and Reconciliation

With Client-side prediction enabled, the predicted Client state will sometimes diverge from the server state. This is called **misprediction**.

When misprediction occurs, you will need to adjust the Client state to match the server state in one way or another. This is called **server reconciliation**.

There are many possible approaches to server reconciliation and coherence doesn't favor one over another. The simplest method is to snap the Client state to the server state once a misprediction is detected. Another method is to continuously blend from Client state to server state.

Misprediction detection and reconciliation can be implemented in a binding's `OnNetworkSampleReceived` event callback. This event is called every time new network data arrives, so we can test the incoming data to see if it matches with our local Client state.

```csharp
private void Awake()
{
    var positionBinding = GetComponent<CoherenceSync>().Bindings.FirstOrDefault(c => c.Name == "position");
    positionBinding.OnNetworkSampleReceived += DetectMisprediction;
}

private void DetectMisprediction(object sampleData, bool stopped, long simulationFrame)
{
    const float MispredictionThreshold = 3;

    var networkPosition = (Vector3)sampleData;
    var distance = (networkPosition - transform.position).magnitude;

    if (distance > MispredictionThreshold)
    {
        transform.position = networkPosition;
    }
}
```

The **misprediction threshold** is a measure of how far the prediction is allowed to drift from the server state. Its value will depend on how fast your player is moving and how much divergence is acceptable in your particular game.

Remember that incoming sample data is delayed by the round-trip time to the server, so it will trail the currently predicted state by at least a few frames, depending on network latency. The `simulationFrame` parameter tells you the exact frame at which the sample was produced on the authoritative server.

{% hint style="info" %}
For better accuracy, incoming network samples should be compared to the predicted state at the corresponding simulation frame. This requires keeping a history buffer of predicted states in memory.
{% endhint %}

## Client as a Host

{% hint style="warning" %}
This feature is in the experimental phase.
{% endhint %}

A client-hosted session is an alternative way to use **CoherenceInput** in **Server Side With Client Input** mode that doesn't require a Simulator.

A Client that created a [Room](https://docs.coherence.io/replication-server/rooms-and-worlds#rooms) can join as a Host of this Room. Just like a Simulator, the Host will take over the State Authority of the **CoherenceInput** objects while leaving the Input Authority in the hands of the Client that created those objects.

The difference between a Host and a Simulator is that the Host is still a standard client connection, which means it counts towards the Room's **client limit** and will show up as a client connection in the connection [list.](https://docs.coherence.io/client-connections#3-create-a-client-connection-prefab)

### Usage

To connect as a Host all we have to do is call `CoherenceBridge.ConnectAsHost`:

```csharp
public async Task CreateRoomAndJoinAsHost(string region)
{
    // Wait until a player account has logged in to coherence Cloud.
    PlayerAccount playerAccount = await PlayerAccount.GetMainAsync();

    var roomServiceForRegion = playerAccount.Services.Rooms.GetRoomServiceForRegion(region);

    var roomData = await roomServiceForRegion.CreateRoomAsync(RoomCreationOptions.Default);
    var (roomEndpoint, isEndpointValid, validationErrorMessage) = RoomData.GetRoomEndpointData(roomData);

    if (!isEndpointValid)
    {
        throw new Exception($"Invalid room endpoint: {validationErrorMessage}");
    }

    // Connect to the room as a host.
    if (CoherenceBridgeStore.TryGetBridge(gameObject.scene, out var bridge))
    {
        bridge.onConnected.AddListener(OnConnected);
        bridge.ConnectAsHost(roomEndpoint);

        void OnConnected(CoherenceBridge bridge) => Debug.Log($"Connected! IsHost: {bridge.IsSimulatorOrHost}");
    }
}
```

## Interaction with LiveQueries

[CoherenceLiveQuery](https://docs.coherence.io/manual/components/coherence-live-query) is a component that can be used to constrain the area of entities that are replicated on the client.

When using a LiveQuery, The [Replication Server](https://docs.coherence.io/manual/replication-server) filters out networked objects that are outside the range of the defined range. This can be useful as an optimization, and a security mechanism, to ensure clients can't exploit the system by inspecting the incoming network traffic, outside of what they are allowed to see. However the question arises: what if the player exploits by moving the position of the LiveQuery?

When a query component is part of a [CoherenceSync](https://docs.coherence.io/manual/components/coherence-sync) that is set to *Server Side With Client Inputs*, the query visibility will be applied to the client that owns Input Authority (i.e., the Client) while the component's state remains in control of the State Authority (i.e., the [Simulator](https://docs.coherence.io/manual/simulation-server))**.**

This prevents clients from viewing other parts of the world by simply manipulating the extents or the position of the LiveQuery.

{% hint style="info" %}
See [CoherenceLiveQuery](https://docs.coherence.io/manual/components/coherence-live-query) and [Area of interest](https://docs.coherence.io/manual/optimization/areas-of-interest) for more information on how to use queries.
{% endhint %}
