Host the Cities: Skylines map generator locally

There are times when the Cities: Skylines Map Generator at https://heightmap.skydark.pl is not available. The free MapBox token expires because of the number of requests it serves.

We can host the site ourselves on our workstation and use it any time.

Install XAMPP

XAMPP is a free web server created by Apache Friends.

  • Download the installer for your workstation’s operating system at https://www.apachefriends.org/download.html
  • Install the application. As the popup will warn you, do not install it in the Program Files directory, as Windows restricts the access there.

Download the Cities: Skylines Map Generator application

The source code of the application is available on GitHub.

Place the application in the XAMPP directory

XAMPP contains the Apache web server which can host our JavaScript web application.

  • Create a directory called map in the htdocs folder of XAMPP. If you installed XAMPP to the default location, it is at C:\xampp\htdocs
  • Move the images and src directories of the map generator application into the map folder

Start XMAPP

  • Start the XAMPP Control Panel from the Start Menu
  • Start the Apache web server
  • Open your web browser and navigate to http://localhost/map/src/

Changing the MapBox access token

If the MapBox access token expires

  • Create a free access token for yourself at https://www.mapbox.com/
  • Update the value of mapboxgl.accessToken in the src/app.js file in line 47

To host the app from another directory

With the default configuration, XAMPP is looking for the web application in the htdocs directory within the XAMPP installation folder.

If you want to keep the Map Generator in another directory and host it from there with XAMPP:

  • Open the XAMPP control panel
  • Stop the Apache server
  • Click the Config button and select Apache (httpd.conf)
  • Place the project location into the DocumentRoot and Directory lines
  • Start the Apache server
  • Open your web browser and navigate to http://localhost/src/

Create a high resolution overlay image for Cities: Skylines II

The Image Overlay mod for Cities: Skylines 2 allows us to build a city based on real world locations. See Image overlay in Cities: Skylines 2 on how to install and use it.

To generate a high resolution overlay image

Create the standard resolution overlay image

Create a 2560×2560 pixel overlay image matching the height map. See Using the Map Editor in Cities:Skylines 2

Update the overlay image to high resolution

We can update the resolution to 16,384×16,384 pixels with some editing work using GIMP, the free graphics editor.

  • With your web browser navigate to Cities: Skylines map generator
  • Use the same location you used for the height map and the standard resolution overlay image
  • Set the Map size to 2.24 km

Signature verification failed, repository.json is not valid

When the Cities: Skylines II mod publishing fails with

Syncing WIP mod “…”
[L3Error_][6574][4B66][EFB4][0181] Error getting repository metadata for repository mods/cities_skylines_2/…/repo/Windows__Any, got exception: Signature verification failed, repository.json is not valid
Could not sync WIP mod: Signature verification failed, repository.json is not valid

Check the state of your mod

  • With your web browser, open the My Uploaded Mods page on the Paradox Plaza,
  • Click the mod to open the details page.

The Mod ID

The Mod ID is in the URL

It is the number you saved in the PublishConfiguration.xml file at

If the mod is corrupted on the Paradox Plaza

If the mod is corrupted on the Paradox servers, and you cannot update it anymore with the regular publishing process, you may need to delete the corrupted copy.

Warning!!!

If you delete a mod, all users who have subscribed to it, will get the “This mod has been banned” message when they open their playsets. They have to delete it from their playsets, and add it again to their active playset.

Delete a mod from Paradox Plaza

  • Hover above the pencil on the mod’s thumbnail and select Delete mod

Upload the mod again

If a mod has been deleted from Paradox Plaza, we can no longer publish updates to it to keep the same Mod ID. If we try, we get the error message: Could not publish new version of the mod: Updates are disabled for this mod.

To upload the mod again, we need to publish the mod as new.

  • Right-click the project and select Publish
  • On the Publish page select PublishNewMod
  • When the publishing process completed, copy the new Mod ID to the clipboard
  • Update the ModId value with it in the PublishConfiguration.xml file.

Creating a new mod for Cities: Skylines II

Developer tools

To create a new mod for Cities: Skylines 2, first, we need to install the developer tools.

  • Start Cities: Skylines II
  • In the main menu select Options
  • In the Options menu select Modding
  • Step through the items to install the toolchain
  • Download and install the latest Active version of the .NET framework from .NET/.NET Core

Start a new Visual Studio solution

  • Open Visual Studio and select Create a new project
  • Enter colossal into the search box and select the Cities Skylines II mod, and click the Next button at the bottom of the page
  • Enter the project name, and click the button with the three dots to select the directory where Visual Studio will create a directory for the mod using the “Project name”
  • Click the Next button
  • Make sure The game installation path points to the C:\Program Files (x86)\Steam\steamapps\common\Cities Skylines II\Cities2_Data\Managed folder.
  • Click the Create button

Deploy the mod locally for testing

To deploy the new mod and activate it in the game

  • Exit Cities: Skylines II, otherwise the deployment will fail, because it cannot access the mod files in the Mods directory.
  • Right-click the solution in Solution Explorer
  • Select Rebuild Solution
  • The new mod appears in the Mods folder at C:\Users\YOUR_USER_NAME\AppData\LocalLow\Colossal Order\Cities Skylines II\Mods
  • When you open the city, the mod’s log file is created in the Logs folder at C:\Users\YOUR_USER_NAME\AppData\LocalLow\Colossal Order\Cities Skylines II\Logs

To disable the mod

To run the game without the local deployment of the mod

  • Exit from the game to the desktop,
  • Rename the mod folder to start the name with a period
    C:\Users\YOUR_USER_NAME\AppData\LocalLow\Colossal Order\Cities Skylines II\Mods\.MY_MOD
  • Start the game again.

Publishing the mod

Create a Paradox account

  • Navigate to Paradox Plaza
  • Click Log in in the upper right corner
  • Click the Create Account button

Create a forum thread for the mod

  • Create a Paradox forum thread for your mod at Cities Skylines 2: User Mods. We will add the URL to the mod’s metadata, so users can ask questions, report bugs and share their experience with you and other users.

Create the Paradox account data file

To be able to publish the new mod to Paradox, we need to create the paradox account data file.

  • Create a text file, the Paradox account data file, with two lines in it, and save it outside of the mod repository, like the Desktop, so it will not be pushed into source control (GitHub).
MY_PARADOX_USERNAME
MY_PARADOX_PASSWORD
  • Right-click the project in the Visual Studio Solution Explorer, and select Edit Project File
  • Add the file location to the PDXAccountDataPath element of the mod’s project file. The default value will point to the “pdx_account.txt” file on the Desktop:
<PDXAccountDataPath>$(USERPROFILE)\Desktop\pdx_account.txt</PDXAccountDataPath>
  • Save the project file

Update the Publish Configuration

The PublishConfiguration.xml file in the Properties folder of your mod contains its metadata. We need to update it to provide the values to be displayed on the mod’s information page.

ModId

We will populate this very important value when we first publish the mod. See Publish the mod below. We will need this 5 or 6 digit number to be able to send metadata and code updates to Paradox later. For the first publishing leave it empty string.

DisplayName

This will be the name of the mod in the library where users select from the list of mods.

ShortDescription

The short description of the mod, at this moment it is not obvious where it is displayed.

LongDescription

The long description explains the purpose and usage of the mod. For the formatting to work, make sure all lines of the LongDescription start at the left margin of the page!!!

To make it easier to format the text, create a file in the Properties directory, many modders call it LongDescription.md

It will not be uploaded to Paradox, but the .md extension tells Visual Studio how to display the preview in the editor. Just click the Preview button in the upper left corner to see how the text will look like when Paradox displays it.

When the formatting is done,

  • save the file for future reference,
  • copy and paste the text into the LongDescription element of the PublishConfiguration.xml file,
  • IMPORTANT: Select the pasted text in the PublishConfiguration.xml file, and press Shift-Tab twice, to move the text to the left margin. Otherwise the formatting will not work when it is displayed on the mod information page.

Thumbnail

Create a square .png or .jpg image to be the thumbnail of your mod.

Save it in the Properties folder of the mod. Update the Thumbnail element of the PublishConfiguration.xml file to point to the image.

Screenshot

The screenshot images are displayed on the mod information page.

Save the .png or .jpg files in the Properties folder and update the Screenshot element. If you have multiple images, add more Screenshot lines.

Tag

Regardless of the comment in the file, for code mods at this point it has to be one element with the value: “Code Mod”.

ForumLink

Enter the URL of the Paradox forum thread for the mod you have created above.

ModVersion

The current version of the mod.

GameVersion

It is the version of the game, your mod is compatible with. When the new version of the game is released, all users will automatically receive it at the same time. It is important to test your mod with it, and update this value, otherwise a warning sign will appear on the mod’s information page telling all users, your mod is not compatible with their game version. At the time of writing the game’s “major.minor” version is 1.1 Most likely you mod will work fine until at least the next minor version, so today 1.1.* will provide the correct game version value.

Dependency

If the mod depends on other mods, list them here.

If the mod does not have any dependencies, leave the value an empty string.

ChangeLog

This will generate the change log entries on the mod info page. After publishing the first version of the mod, this is not yet displayed anywhere. Starting with the second version, it will be appended to the list on the right margin of the mod info page.

To make the ChangeLog formatting easier, like what we did for the LongDescription above, create the LatestChangelog.md file. It will not be uploaded to Paradox, but using it makes the text formatting a better experience.

There are two options to send information to the change log: One line, or multiple lines.

One line change log entry

The ChangeLog Value element can only have one formatted line.

Multi-line change log entry

The ChangeLog element can have multiple formatted lines. To use it, comment out or delete the ChangeLog Value element, and uncomment the ChangeLog start and end tags. List the changes of the current update, for the formatting to work, make sure all lines start at the left margin.

ExternalLink

The URLs of YouTube videos, Discord servers, GitHub repositories, PayPal donation pages.

Publish the mod

  • Exit Cities: Skylines II, so the build process can overwrite the mod in the Mods directory
  • Right-click the mod’s project and select Publish
  • On the Publish page select the action, for the first time, leave PublishNewMod selected, and click the Publish button
  • Copy the Mod ID from the output window
  • Save it in the PublishConfiguration.xml file. It is required to publish updates in the future.

Troubleshooting

Error

Error MSB3231 Unable to remove directory “C:\Users\…\AppData\LocalLow\Colossal Order\Cities Skylines II\Mods\…”. Access to the path ‘…_win_x86_64.dll’ is denied. C:\Users\…\AppData\LocalLow\Colossal Order\Cities Skylines II.cache\Modding\Mod.targets

Solution

Visual Studio cannot deploy the new version of the mod, because Cities: Skylines II is running. Exit the game to the Desktop and build the solution again in Visual Studio.

Error

PDX account data file is not found. Please check the ‘PDXAccountDataPath’ property value of your project. If you have no such file, you should create it. It is a simple text file where the first line is your PDX account login and the second line is your PDX account password.

Solution

Create and reference the Paradox account data file, see Create the Paradox account data file above.

Error:

Error while processing args
ChangeLog must be set in configuration

Solution:

To be able to publish an update to the mod, we need to add to the ChangeLog value in the PublishConfiguration.xml file

<ChangeLog Value="Updated metadata and added screenshot image" />
<!--ChangeLog>

Error:

Could not update the mod configuration: Couldn’t upload all files to the backend

Solution:

Make sure the image file name does not contain spaces.

Decompiling the Cities: Skylines II code

To be able to view the source code code of Cities: Skylines 2, we need a few tools.

Visual Studio

Visual Studio Community edition is a free IDE to write .NET code in C# and other languages.

Decompiler

To decompile the game code to the source code, we will use the ILSpy Visual Studio extension.

  • Search for the link to the latest version on the ILSpy GitHub page at ILSpy
  • At the time of writing, ILSpy 2022 is the latest version, download it from ILSpy 2022
  • Double-click the downloaded .vsix file
  • Restart Visual Studio if it was running at the time of the extension installation

Decompiling Cities: Skylines II

  • Start Visual Studio
  • Select Continue without code to start a new project
  • In the Tools menu select ILSpy
  • In the ILSpy window select File, Open
  • Select Game.dll in the “C:\Program Files (x86)\Steam\steamapps\common\Cities Skylines II\Cities2_Data\Managed” directory
  • On the left side expand the Game node

Save the game code

To save the game code as a Visual Studio project

  • Right-click the Game node and select Save Code…

Examining the original game code

  • In the Visual Studio File menu select Open, Project/Solution
  • Open the Game.csproj C# project
  • To search for words in the game source code press CTRL-F or open the Quick Find dialog box

How to stop the rain and snow in Cities: Skylines II

The snow makes it hard to see the image overlay in Cities: Skylines II. To stop the rain and snow we can

  • use the Weather+ mod or
  • make temporary changes in Developer mode.

Weather+ mod

  • Install the Weather+ mod in the main menu

Temporary change in Developer mode

The Override Precipitation setting in Developer Mode is not saved in the city, so every time you open the city, you need to set it again.

  • Enable Developer mode, see https://pinter.org/archives/15586
  • Start the game and open the city
  • Press the Tab key to open the Developer menu
  • On the Climate tab check Override Precipitation, the Precipitation value should automatically set to zero.
  • Close the Developer menu with the Tab key
  • To melt the snow, click the fast forward icon to forward to summer

Argument of type ‘(number | null)[]’ is not assignable to parameter of type ‘(err: Error, result: QueryResult) => void’

The latest “npm install @types/pg –save-dev” command changed the “@types/pg” Node.js module version in the package.json file from to “^8.11.4”.

Since that, the build of my TypeScript applications fail with the error message below, if the PostgreSQL .query function contains mixed “value” types, like this:

const query = "INSERT INTO ..."
const values = [string, number, stringArray, nullableValue]
const result = await conn.query(
      query,
      values
    );   

The error message is:

.. : error TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type ‘(number | null)[]’ is not assignable to parameter of type ‘(err: Error, result: QueryResult) => void’.
Type ‘(number | null)[]’ provides no match for the signature ‘(err: Error, result: QueryResult): void’.

or

…: error TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type ‘(string | number)[]’ is not assignable to parameter of type ‘(err: Error, result: QueryResult) => void’.

or

… : error TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type ‘(string | number | null)[]’ is not assignable to parameter of type ‘(err: Error, result: QueryResult) => void’.
Type ‘(string | number | null)[]’ provides no match for the signature ‘(err: Error, result: QueryResult): void’.

Solution

I can see two solutions:

Make sure all elements of the array have the same data type

If possible, make sure the type of all value elements is the same, the simplest is to

  • convert numeric values to strings,
  • specify default values for “null” values,
  • convert string arrays to strings, or get the first element if only that has value.
const values = [number.toString(), canBeNullString || '' (canBeNullNumber || 0).toString(), stringArray[0]]

A better solution is to centralize the database access

If the database access is centralized in a function, and the values are passed in as “any” type, the TypeScript compiler will not reject it, because it does not iterate through all references of the function.

This is an example of the centralized PostgreSQL database call.
Install the required Node.js packages with

npm install typescript --save-dev
npm install @types/node --save-dev
npm install dotenv
npm install pg
npm install @types/pg --save-dev

The centralized PostgeSQL access file

// db.js

import * as dotenv from "dotenv";
dotenv.config()
import pg from 'pg'

// Create the reusable pool to the PostgreSQl database
// Read config values from environment variables
let conn = new pg.Pool({
  user: process.env.USER_NAME,
  password: process.env.PASSWORD,
  host: process.env.HOST,
  port: parseInt(process.env.PORT || "5432"),
  database: process.env.DATABASE,
});

// Call the "query" method of the pool to execute the text of the query with optional parameters
export const query = async (text: string, params: any) => {
  let res;

  try{

    if (params) {
      // There are parameters, send them with the query text
      res = await conn.query(text, params)
    } else {
      // There are no parameters
      res = await conn.query(text)
    }

  } catch (e) {
    // There is an error executing the query, log the error, the text of the query and the parameters
    console.log('error', e)
    console.log('query', text)
    console.log('params', params)
  }

  return res
}
  
export default query ;

Call the centralized function with

// selectData.ts

import * as conn from './db';

export async function selectData (id: string) {

  let result;
  let query;
  let values;

  try {
    
    // Build the query
    const baseQuery = "SELECT * FROM table";  

      query = baseQuery + ' ' + "WHERE id = $1";
      values = [id]

    // Query the database
    result = await conn.query(
        query
        , values
    );

    return result?.rows[0];

  } catch ( error ) {
    console.log("In selectData", error);
    console.log("result: ", result);
    console.log("query: ", query);
    console.log("values: ", values)
    return null;
    }
};

Cities: Skylines II Developer Mode

WARNING: MAKING CHANGES IN DEVELOPER MODE CAN CREATE UNFORESEEN RESULTS AND CAN CORRUPT THE SAVE FILE. USE DEVELOPER MODE WITH CAUTION!!!

In developer mode we can gain access to more tools than what the regular user interface provides. We can

  • Adjust the concrete surface area around buildings

To start Cities: Skylines II in developer mode from the Steam app

  • Start the Steam app
  • In the Library right-click Cities: Skylines II and select Properties
  • On the General tab, enter -developerMode into the Launch Options field
  • There is no Save button, so close the panel in the upper right corner

Using Developer Mode

Changing the Game play

Changes in this area can create unforeseen results and can break the change file.

  • To open the game setting developer menu press the Tab key on the keyboard
  • Press the Tab key again to close the game play developer menu

Object developer menu

  • To open the Object developer menu, press the Home key on the keyboard