# The ClientAPI (custom content)

{% hint style="danger" %}
**THIS PAGE IS A WORK IN PROGRESS.**
{% endhint %}

Since sending dll's mod to clients would represent a security risk we've made a small client api that allows you to interact with the clients and load custom content.\
\
It is pretty basic but it can already allow for a TON of stuff. Only your imagination is your limit.\
\
The ClientAPI works by using paths from the hierarchy for non-networked objects.\
It is not 100% safe as if a client hierarchy get out of sync it could stop working.\
However things like buildings, map, ATM's etc.. that are static should not be impacted by this if you follow the general rules.<br>

The ClientAPI offers mostly extension methods to GameObjects ending by Clientside.\
Most of the methods sends a network message to the client to tell him to move an object, rotate it, disable it, call a method on it etc.\
\
For most things it is saved for new players such as position, rotation, destroying, disabling etc.\
Which means that if when your plugin starts you remove the police office, new players will get that removal action when they connect.&#x20;

{% hint style="warning" %}
Warning, the only 2 methods not saved upon reconnect are `InvokeMethodClientside` and `SetVariableClientside` . So if you use them for changing something permanently you might want to listen when a new player joins and call it again for this player.
{% endhint %}

The ClientAPI also works with NetworkObjects (Players, Vehicles etc) And is more stable than the hierarchy path approach (It'll internally detect when its a NetworkObject or child of one).

{% tabs %}
{% tab title="SetPositionClientside" %}
This sets the position of the object you pass.\
There is also `SetLocalPositionClientside` for changing the position relative to the gameobject parent.

<pre class="language-csharp"><code class="lang-csharp"><strong>void SetPositionClientside(this GameObject gameObject, Vector3 position, bool local = false)
</strong></code></pre>

<pre class="language-csharp"><code class="lang-csharp"><strong>void SetLocalPositionClientside(this GameObject gameObject, Vector3 position)
</strong></code></pre>

{% endtab %}

{% tab title="Example" %}

```csharp
GameObject.Find("Fire Hydrants").SetLocalPositionClientside(new Vector3(0,2,0));
```

This simple line will move all the fire hydrants up (Totally pointless i'll agree on that).\
![](https://1009565841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdPzK9hYNRS2OIoKsRn5%2Fuploads%2FFqlTHmCrWZ0eSJQSATbB%2Fimage.png?alt=media\&token=2407f48e-f949-40d7-9120-3067357c71a1)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="SetRotationClientside" %}
This sets the rotation of the object you pass.\
There is also `SetLocalRotationClientside` for changing the rotation relative to the gameobject parent.

```csharp
void SetRotationClientside(this GameObject gameObject, Quaternion rotation, bool local = false)
```

```csharp
void SetLocalRotationClientside(this GameObject gameObject, Quaternion rotation)
```

{% endtab %}

{% tab title="Example" %}

```csharp
HAPI.FindGameObjectByPath("Map/Container/Shitbox").SetRotationClientside(Quaternion.Euler(0,0,180));
```

This simple line rotates the broken car near the motel upside down. (Also pointless)\
![](https://1009565841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdPzK9hYNRS2OIoKsRn5%2Fuploads%2FhdjJGQBsdyW5qB9d6Srm%2Fimage.png?alt=media\&token=0743f47d-b19a-44e8-88ef-b2aa03a323b0)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="SetActiveClientside" %}
This allows you to disable objects, simple call it with either true or false to set the object as active (true) or inactive (false).

```csharp
void SetActiveClientside(this GameObject gameObject, bool active)
```

{% endtab %}

{% tab title="Example" %}

```csharp
HAPI.FindGameObjectByPath("Map/Container/Pawn shop").SetActiveClientside(false);
```

This disables the pawn shop (it is just an example and should probably not do it this way unless verifying nothing depends on it).\
![](https://1009565841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdPzK9hYNRS2OIoKsRn5%2Fuploads%2FHX9LPpReFyH9LxhPWK8M%2Fimage.png?alt=media\&token=44d33688-a871-4ef2-a784-f37a7cdddfed)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="SetParentClientside" %}
This allows you to set a gameobject parent.

```csharp
void SetParentClientside(this GameObject gameObject, GameObject parent)
```

{% endtab %}

{% tab title="Example" %}
TODO
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="CloneClientside" %}
This allows you to create a copy of a gameobject. (Not working with network objects)\
It returns the cloned object so you can then use for example `SetPositionClientside` on it.

<pre class="language-csharp"><code class="lang-csharp"><strong>GameObject CloneClientside(this GameObject gameObject, Vector3 position = default, Vector3 rotation = default)
</strong></code></pre>

{% endtab %}

{% tab title="Example" %}

```csharp
GameObject plant = GameObject.Find("Skate Park").transform.Find("WoodPlanter (4)").gameObject;
GameObject clone = plant.CloneClientside(plant.transform.position + new Vector3(0,0,2));
```

Creates a copy of a woodplanter and moves it on the side.\
![](https://1009565841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdPzK9hYNRS2OIoKsRn5%2Fuploads%2Fq90eBDDWBhKbCfPBg1Aq%2Fimage.png?alt=media\&token=50337c28-60ce-4736-85c7-20d241b63577)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="SetComponentActiveClientside" %}
Allows you enable or disable specific components.\
You can use it to disable game scripts, renderers or parts of an object.

```csharp
void SetComponentActiveClientside(this Component component, bool active)
```

{% endtab %}

{% tab title="Example" %}

```csharp
Player player = Player.GetRandomPlayer(); // Here i'm alone so i use this.
MeshRenderer r = player.CurrentVehicle.transform.Find("shitbox_combined").GetComponentInChildren<MeshRenderer>();
r.SetComponentActiveClientside(false);
```

This will disable the rendering of the current vehicle body (Police shitbox for testing).\
![](https://1009565841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdPzK9hYNRS2OIoKsRn5%2Fuploads%2FUXf6k2ltmY8u8olmRcv4%2Fimage.png?alt=media\&token=ecdc00b2-8466-4941-bfc3-86c2acea35ab)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="InvokeMethodClientside" %}
This is probably one of the most powerful methods of the API yet.\
It allows to invoke any method on any object with any parameters.

```csharp
void InvokeMethodClientside(this Component component, string methodName, params object[] args)
```

{% endtab %}

{% tab title="Example" %}

```csharp
Player.GetRandomPlayer().CurrentVehicle.GetComponentInChildren<PoliceLight>().InvokeMethodClientside("SetIsOn", true);
```

This will enable the police lights and sirens on the current vehicle if any.\
![](https://1009565841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdPzK9hYNRS2OIoKsRn5%2Fuploads%2FSWaA9TBgcm8eXrNqDAY5%2Fimage.png?alt=media\&token=542c9ffe-8779-4470-89a4-d096d1977c4b)![](https://1009565841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdPzK9hYNRS2OIoKsRn5%2Fuploads%2FEpDVKTT4EThdgPus1XVz%2Fimage.png?alt=media\&token=fb9506a7-fe32-4b17-96b0-cbf435385b03)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="SetVariableClientside" %}
This is also one of the most powerful methods as it allows you to set any variables on any game object.

```csharp
void SetVariableClientside(this Component component, string variableName, object value)
```

{% endtab %}

{% tab title="Example" %}

```csharp
Player.GetRandomPlayer().GetComponentInChildren<PlayerMovement>(true).SetVariableClientside("StaticMoveSpeedMultiplier",10);
```

The code above sets the player movement speed to 10.

```csharp
Player.GetRandomPlayer().GetComponentInChildren<PlayerMovement>(true).SetVariableClientside("jumpForce",10);
```

This other example sets the jump force to 10.
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="DestroyClientside" %}
This allows you to destroy objects on the client.

{% hint style="danger" %}
I would personally not recommend using the DestroyClientside method but instead use SetActiveClientside unless you know what you are doing.\
Deleting map objects could cause the game to have errors, lag and eventually get the hierarchy out of sync and all other methods would stop working.
{% endhint %}
{% endtab %}

{% tab title="Example" %}

```csharp
GameObject.Find("Roads").DestroyClientside();
```

I think a screenshot will be enough for the explanation.\
![](https://1009565841-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOdPzK9hYNRS2OIoKsRn5%2Fuploads%2FPT3sWGJJs0AxBiv1lP5s%2Fimage.png?alt=media\&token=e05b0643-1b75-40ab-8d30-8ecc42e876a7)<br>
{% endtab %}
{% endtabs %}
