> 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/architecture/server-code-and-assemblies.md).

# How Server Code Is Compiled

## Summary

Reactor compiles your server scripts into a separate assembly from your Unity code, and generates a Unity-side proxy class for each one so the inspector has something to attach. The menu items that create server scripts set this up for you, so most developers never need to know it exists.

You need to know it exists the moment you do anything the menu items did not do for you: import a project someone else made, move a script folder, restructure `Assets`, or add server scripts to a project by copying files. When the wiring is wrong, the compiler errors point at your code rather than at the wiring, and they look convincingly like a Reactor version mismatch.

This page describes the model, the folder layout it produces, and what a broken layout looks like.

### Requirements

* [Reactor Requirements](/reactor/overview.md#requirements)
* Completion of [Running Rooms Locally and Online](/reactor/tutorials/basics.md)

## Why Server Code Is Separate

Server code runs in the Reactor runtime server, which is a standalone process. It is not Unity, so there is no `UnityEngine`, no `MonoBehaviour`, and no `GameObject`. That is why server scripts use `ksVector3` rather than `Vector3`, and derive from `ksServerEntityScript` rather than `MonoBehaviour`.

Keeping server code in its own assembly is what enforces that. It is also what keeps your server logic out of the game clients you ship, which matters, because anything in a client build can be read by anyone who has it.

## The Three Assemblies

A Reactor project has two assembly definitions of its own, and uses Unity's default assembly for everything else.

| Assembly           | Contains                                      | Engine access | Ships in a client build |
| ------------------ | --------------------------------------------- | ------------- | ----------------------- |
| `KSScripts-Common` | Constants and types shared by both sides      | No            | Yes                     |
| `KSScripts-Server` | Server scripts and player controllers         | No            | No, editor only         |
| `Assembly-CSharp`  | Your Unity scripts, and the generated proxies | Yes           | Yes                     |

The settings that produce this are worth reading once, because each one is doing a specific job.

*Assets/ReactorScripts/Common/KSScripts-Common.asmdef*

```json
{
    "name": "KSScripts-Common",
    "references": [],
    "overrideReferences": true,
    "precompiledReferences": ["KSCommon.dll"],
    "autoReferenced": true,
    "noEngineReferences": true
}
```

*Assets/ReactorScripts/Server/KSScripts-Server.asmdef*

```json
{
    "name": "KSScripts-Server",
    "references": ["KSScripts-Common"],
    "includePlatforms": ["Editor"],
    "overrideReferences": true,
    "precompiledReferences": ["KSCommon.dll", "KSReactor.dll"],
    "autoReferenced": false,
    "noEngineReferences": true
}
```

* `noEngineReferences` on both is what makes `Vector3` fail to resolve in a server script. That is the setting doing it, and it is deliberate.
* `autoReferenced: true` on Common means your ordinary Unity scripts can use the shared constants without adding a reference. This is why a property id constant defined once is visible to both sides.
* `autoReferenced: false` on Server is the opposite, and is the important one. Your Unity code cannot see your server classes at all, so you cannot accidentally call server logic from the client and discover the problem at runtime.
* `includePlatforms: ["Editor"]` on Server means server scripts are compiled in the editor and excluded from every player build.

## Proxies

Your Unity code cannot see server classes, but the inspector still has to show a server script on a prefab, and `[ksEditable]` fields still have to be editable. Reactor solves this by generating a proxy: an empty Unity component with the same name and the same editable fields, in a mirrored namespace.

*Assets/ReactorScripts/Proxies/Scripts/ParentDemo/seWaypoints.cs*

```c#
/* This file was auto-generated. DO NOT MODIFY THIS FILE. */
namespace KSProxies.Scripts.ParentDemo
{
    public class seWaypoints : ksProxyEntityScript
    {
#if UNITY_EDITOR
        public KSProxies.Structs.ParentDemo.seWaypoints.Waypoint[] Waypoints;
        ...
#endif
    }
}
```

Three things follow from this, and all three catch people out.

**The proxy is what you attach and what you reference from editor code.** The component on the prefab is `KSProxies.Scripts.ParentDemo.seWaypoints`, not `ParentDemo.seWaypoints`. A custom inspector targets the proxy:

```c#
using KSProxies.Scripts.ParentDemo;

[CustomEditor(typeof(seWaypoints))]
public class seWaypointsEditor : Editor { ... }
```

**The proxy mirrors your namespace under `KSProxies`.** A server class in `ParentDemo` produces a proxy in `KSProxies.Scripts.ParentDemo`. Enums and structs nested in server scripts get the same treatment under `KSProxies.Enums` and `KSProxies.Structs`.

**Field types are not always identical.** The proxy carries the Unity-serializable equivalent of each `[ksEditable]` field, which is not always the type you declared. A server field declared `List<Waypoint>` appears on the proxy as `Waypoint[]`, because Unity serializes arrays. Editor code uses `.Length`; server code uses `.Count`. Remember this, because it is about to matter.

Proxies live in `Assets/ReactorScripts/Proxies` with no assembly definition of their own, so they compile into `Assembly-CSharp` alongside your Unity code. Reactor regenerates them from your server scripts. Never edit them, and if one looks out of date, rebuild the server runtime.

## Adding Server Scripts Outside ReactorScripts

The menu items put new server scripts in `Assets/ReactorScripts/Server`, where the assembly definition already applies. If you would rather keep your server code beside the rest of your feature, put an assembly reference file in that folder instead of moving the assembly definition.

```
Assets/MyFeature/Scripts/
    Common/
        KSScripts-Common.asmref     <- { "reference": "KSScripts-Common" }
        Constants.cs
    Server/
        KSScripts-Server.asmref     <- { "reference": "KSScripts-Server" }
        seMyEntity.cs
    Editor/
        seMyEntityEditor.cs         <- no asmref, this is Unity code
```

An `.asmref` folds that folder into the named assembly. The contents are a single line:

```json
{
    "reference": "KSScripts-Server"
}
```

Two rules keep this working. Every folder containing server scripts needs the server asmref, and no folder containing Unity code may have one, because Unity code needs the engine references the server assembly forbids.

## When the Wiring Is Missing

This is the failure worth recognising on sight, because it does not describe itself.

An `.asmref` that names an assembly definition which does not exist in the project does not produce an error of its own. It silently does nothing, and the scripts in that folder fall back into `Assembly-CSharp`. This happens to any project that ships asmrefs but has never had Reactor initialised in it, which includes most sample projects downloaded and opened for the first time.

Now the real server classes and the generated proxies are in the same assembly, with the same class names, in namespaces that differ only by the `KSProxies` prefix. That is enough for C# name resolution to pick the wrong one, and it does so silently, because preferring the enclosing namespace over a `using` directive is correct C# behaviour.

Take the editor script above. It sits in `namespace ParentDemo` and has `using KSProxies.Scripts.ParentDemo;`, so `seWaypoints` is meant to resolve to the proxy. Once the real `ParentDemo.seWaypoints` also lands in `Assembly-CSharp`, the enclosing namespace `ParentDemo` contains a `seWaypoints` of its own, and the enclosing namespace wins. Every unqualified `seWaypoints` in that file now means the server class.

The errors that follow are all consequences of that one substitution:

* `.Waypoints.Length` fails, because the server field is a `List<Waypoint>` and lists have `Count`
* `(seWaypoints)target` fails, because the server class does not derive from `UnityEngine.Object`
* `[CustomEditor(typeof(seWaypoints))]` is no longer pointing at a component

Read individually, these say that the fields and base types are not what the code expects, which is exactly what a version mismatch looks like. Nothing in them mentions assemblies. The fix is not in any of the files reporting an error.

**How to tell the difference.** Ask Unity which assembly a file actually compiles into. Selecting a script in the Project window shows this in the inspector, and you can also query it directly:

```c#
using UnityEditor;

public class AssemblyCheck
{
    [MenuItem("Tools/Reactor/Report Script Assemblies")]
    private static void Report()
    {
        foreach (string guid in AssetDatabase.FindAssets("t:MonoScript"))
        {
            string path = AssetDatabase.GUIDToAssetPath(guid);
            if (!path.StartsWith("Assets/"))
            {
                continue;
            }
            Debug.Log(path + " -> " +
                UnityEditor.Compilation.CompilationPipeline.GetAssemblyNameFromScriptPath(path));
        }
    }
}
```

A correctly wired project reports this shape:

```
ParentDemo/Scripts/Server/seWaypoints.cs                 -> KSScripts-Server.dll
ParentDemo/Scripts/Common/Utils.cs                       -> KSScripts-Common.dll
ParentDemo/Scripts/Client/ceParent.cs                    -> Assembly-CSharp.dll
ParentDemo/Scripts/Editor/seWaypointsEditor.cs           -> Assembly-CSharp-Editor.dll
ReactorScripts/Proxies/Scripts/ParentDemo/seWaypoints.cs -> Assembly-CSharp.dll
```

Server scripts must report `KSScripts-Server`. If one reports `Assembly-CSharp`, it is sharing an assembly with its own proxy, and that is the whole problem. No amount of editing the files that report errors will help. Create the missing assembly definitions, or copy `Assets/ReactorScripts` from a project where Reactor has been initialised.

## Building the Server

Two separate build steps produce two different things, and both are needed before a room will run.

| Step                 | Shortcut | Produces                                                                    |
| -------------------- | -------- | --------------------------------------------------------------------------- |
| Build Scene Configs  | Ctrl+F2  | Entity and scene configuration, including the entity ids scene objects need |
| Build Server Runtime | Ctrl+F3  | The compiled server module from your server assembly                        |

The runtime is compiled outside Unity using the .NET SDK, which Reactor locates through a setting rather than by searching. If that setting is empty you get "Unable to locate server build tools", which reads like a missing installation even when the SDK is present.

Set it in `Reactor > Settings`, under the server section:

```
DotNetPath: C:\Program Files\dotnet\dotnet.exe
```

## Common Problems

| Symptom                                                                                               | Cause                                                                                                                                                                                                                                                                                                                               |
| ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Server scripts report missing fields, wrong base types, or missing methods, as though the API changed | The asmrefs name assembly definitions that do not exist, so server code compiled into `Assembly-CSharp` and shadowed the proxies. Check the assembly shown in the inspector.                                                                                                                                                        |
| `Vector3` or `MonoBehaviour` not found in a server script                                             | Working as intended. Server code has no engine references. Use `ksVector3`, and derive from the `ksServer...` base classes.                                                                                                                                                                                                         |
| A server class is not visible from a Unity script                                                     | Also intended. The server assembly is not auto referenced. Move anything both sides need into `KSScripts-Common`.                                                                                                                                                                                                                   |
| A custom inspector will not compile against a server script                                           | Target the proxy in `KSProxies.Scripts`, and use the proxy's field types. Collections declared as lists appear on the proxy as arrays.                                                                                                                                                                                              |
| Server scripts fail to compile only in a player build                                                 | An asmref was added to a folder containing Unity code, pulling it into an editor-only assembly with no engine references.                                                                                                                                                                                                           |
| "Unable to locate server build tools"                                                                 | `DotNetPath` is empty in the Reactor server settings.                                                                                                                                                                                                                                                                               |
| Server code changes have no effect, with no errors anywhere                                           | A local server that was already running is still executing the previously built runtime. Rebuilding does not reliably reload a running server. Check the newest file in `KinematicSoup/Reactor/logs` against the build time of `KinematicSoup/Reactor/image/KSServerRuntime.Local.dll`, and restart the server if the log is older. |
| A scene entity has an entity id of 0 at runtime                                                       | Scene configs have not been built. Press Ctrl+F2.                                                                                                                                                                                                                                                                                   |

## Where to Go Next

* [Running Rooms Locally and Online](/reactor/tutorials/basics.md): the build steps in the context of a first room.
* [The Runtime Server](/reactor/architecture/architecture-server.md): what the compiled server module is loaded into.
* [Server Object Model](/reactor/architecture/server-object-model.md): what your server scripts act on once they compile.
