Schedule Dedicated Servers Documentation
  • SDS Documentation
  • Schedule In Unity
    • Extracting the game to unity
    • Creating an assetbundle
  • Creating plugins
    • How to create a plugin
    • The ClientAPI (custom content)
  • Custom Assets
  • Plugin Events
  • Texture/Material Replacement
  • Chat Messages
  • Chat Commands
  • Console Commands
  • HAPI Methods
Powered by GitBook
On this page
  1. Creating plugins

The ClientAPI (custom content)

PreviousHow to create a pluginNextCustom Assets

Last updated 1 month ago

THIS PAGE IS A WORK IN PROGRESS.

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.

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.

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.

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).

This sets the position of the object you pass. There is also SetLocalPositionClientside for changing the position relative to the gameobject parent.

void SetPositionClientside(this GameObject gameObject, Vector3 position, bool local = false)
void SetLocalPositionClientside(this GameObject gameObject, Vector3 position)
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).

This sets the rotation of the object you pass. There is also SetLocalRotationClientside for changing the rotation relative to the gameobject parent.

void SetRotationClientside(this GameObject gameObject, Quaternion rotation, bool local = false)
void SetLocalRotationClientside(this GameObject gameObject, Quaternion rotation)
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)

This allows you to disable objects, simple call it with either true or false to set the object as active (true) or inactive (false).

void SetActiveClientside(this GameObject gameObject, bool active)

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).

This allows you to set a gameobject parent.

void SetParentClientside(this GameObject gameObject, GameObject parent)

TODO

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.

GameObject CloneClientside(this GameObject gameObject, Vector3 position = default, Vector3 rotation = default)
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.

Allows you enable or disable specific components. You can use it to disable game scripts, renderers or parts of an object.

void SetComponentActiveClientside(this Component component, bool active)
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 is probably one of the most powerful methods of the API yet. It allows to invoke any method on any object with any parameters.

void InvokeMethodClientside(this Component component, string methodName, params object[] args)
Player.GetRandomPlayer().CurrentVehicle.GetComponentInChildren<PoliceLight>().InvokeMethodClientside("SetIsOn", true);

This is also one of the most powerful methods as it allows you to set any variables on any game object.

void SetVariableClientside(this Component component, string variableName, object value)
Player.GetRandomPlayer().GetComponentInChildren<PlayerMovement>(true).SetVariableClientside("StaticMoveSpeedMultiplier",10);

The code above sets the player movement speed to 10.

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

This other example sets the jump force to 10.

This allows you to destroy objects on the client.

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.

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

This will disable the rendering of the current vehicle body (Police shitbox for testing).

This will enable the police lights and sirens on the current vehicle if any.

I think a screenshot will be enough for the explanation.