Skip to content

Cities skylines - Multiuser collaboration

Potential collaboration tool schemes in Cities:Skylines

Preface

Info needed to transfer cities between users:

  • City save file (*.crp file)
  • List of assets used (to be subscribed to)
  • List of activated mods

The game uses Colossal Raw Asset Package (CRAP) files to save user-created cities.

CRAP files are ZIP-like binary files with .crp extension.

Further info on specific formatting scheme of crp files: https://skylines.paradoxwikis.com/CRAP_File_Format

We’ve successfully created a mod that serializes entire city scenes into JSON files:

https://steamcommunity.com/sharedfiles/filedetails/?id=2582603217

The rest of this document assumes assets and mods are the same among all collaborators.

Collaboration between users can be classified into two subclasses, realtime and non-realtime.

Non-Realtime Collaboration

In non-realtime collaboration, users can’t edit city files simultaneously but use a version control system (VCS) to manage changes.

Most version control systems support two main functionalities: version tracking and conflict resolving.

Version control:

It’s relatively easy to achieve version control since there are a lot of ready-made solutions (e.g git)

We can use a library like libgit2sharp (https://github.com/libgit2/libgit2sharp) to create a simple mod that manages a git repo containing the save game file of the city.

This will allow us only to keep track of which save file is the latest version and restrict collaborators to only make modifications after updating to the latest version (pulling in git).

This however, doesn’t allow us to compare two versions of the city since the save files are binary files that are not interpretable by humans and git only views changes between text-based files.

This introduces some problems with branching and merge conflicts resolution.

Conflict resolution

As stated before, to be able to track changes, and in consequence resolve conflicts, we need to be able to view city save data in a human-interpretable text-based format.

Extracting interpretable data from *.crp files

We tried following the CRAP file documentation to create a python script that extracts save data from the .crp file

https://github.com/Mhmd-Hisham/CitiesOS/blob/main/crp_to_json.py

But even after extracting the save data from the .crp file, it was still uninterpretable as it is most likely generated using unity’s serialization scheme which would be difficult to deserialize without knowing the exact class structure of the data being serialized.

We tried decompiling the game to find out how the save was being serialized, but it proved to be rather difficult and time-consuming because of the huge amount of classes in the game.


The decompiling of the game was done using ILSpy (https://github.com/icsharpcode/ILSpy) and then opening the “Assembly-CSharp.dll” file found inside “\<%steam%>\steamapps\common\Cities_Skylines\Cities_Data\Managed\”,

Where \<%steam%> is your machine’s steam installation directory.

Creating our own serializer

We then took a different approach and tried to create a mod that serializes the current game state rather than relying on the game’s save file.

Since the game allows mods to create and inject unity monobehaviors into the game, we tried to write a simple in-game script that serializes all GameObjects in the scene into JSON format.

The mod traverses the hierarchy of the scene and saves them in the following format:

  • Each game object has its hierarchy path as a key in the json dictionary (example key: “Parent1/Parent2/sceneGameObject”) this can later help us find the gameobject in the scene using Unity’s built-in GameObject.Find method.
  • The value associated with each gameobject is a list of dictionaries, the dictionaries in this list correspond to the components attached to that game object.
  • Each of the dictionaries that correspond to a component contains the type of the component and the values of all variables in the component.

The generated JSON can later be used to find the differences between 2 scenes.

To merge 2 scenes we need to first merge their corresponding JSON files and then deserialize that JSON inside the game.

This serialization test mod generates a JSON serialization file at the start of the game and saves it inside a JSON folder inside the default game saves folder.

https://steamcommunity.com/sharedfiles/filedetails/?id=2582603217

Limitations:

  • This mod serializes everything in a scene (including Camera and UI) which is not optimal.
  • Another limitation of this mod is that it can break if 2 sibling game objects (under the same parent) have the same name since they will have the same key in the serialized JSON.

Realtime Collaboration

The key to achieving realtime collaboration is having a common node (server) which manages changes done by many users (clients) to a certain scene and updates/merges those changes in all the client sides.

The proposed scheme is the following:

  • The server node will use a RESTful API for communication.
  • The updates occur at fixed time intervals.
  • Initially, all clients have the same level locally as the latest scene.
  • At the time of the update, all clients compare the scenes they currently have with the local latest scenes and a change log is generated from the differences between the two scenes.
  • All clients send the change logs to the server.
  • The server then merges and handles conflicts in these change logs and then sends to each client the corresponding changes needed to make them have the same latest scene.

The two key parts in this scheme are:

  • Network communication
  • Change detection

Network communication

In order to use api calls the mod should be able to use network communication, fortunately, we can use Unity’s WWW class to use API calls/read responses.

This simple demo mod reads a file over the internet:

\

Back to top