[DovetailLive]
ShipAuthServer="https://auth.railsimdev.com"
ShipLiveServer="https://api.railsimdev.com"
ShipIssuer="https://auth.railsimdev.com/auth/realms/dtl"
[DovetailLiveScreenshots]
LiveServer="https://dtl-screenshot-dev.dovetailgames.net/api/v1/screenshot"
[LoadingScreens]
LiveServer="https://storage.googleapis.com/dtg-tsw2-slides-dev/"
[OnlineStore]
LiveServer="https://storage.googleapis.com/dtg-tsw2-dlc-dev/"
[DTLEntitlements]
LiveServer="https://entitlements-dev.dovetailgames.net"
[DTGStats]
LiveServer="https://mastery.railsimdev.com"
LiveEventPath="/mastery/game/event"
LivePingPath="/health"
Copy and paste the above content into your Game.ini found at C:\Users\[USERNAME]\Documents\My Games\TrainSimWorld2\Saved\Config\WindowsNoEditor for Steam or C:\Users\[USERNAME]\Documents\My Games\TrainSimWorld2EGS\Saved\Config\WindowsNoEditor for Epic Games
[OnlineStore]
DevServer="https://storage.googleapis.com/dtg-tsw2-dlc-dev/"
TestServer="https://storage.googleapis.com/dtg-tsw2-dlc-test/"
LiveServer="https://tsw2-store.trainsimworld.net/"
As luck may have it, on 01.09.2021 the XML file list at https://tsw2-store.trainsimworld.net/ is currently not protected for outside users unlike every other file listing so this is easy to figure out. If the file is not public anymore you can check it on the Wayback Mashine.
TSW looks for the following files in the root directory:
/store.json Languages available
/live-en.json Master json (seemingly irrelevant for the user)
/steam-en.json Steam
/gdk-en.json Gamepass (Microsoft Store)
/ps5-en.json PlayStation 5
/egs-en.json Epic Games Store
The store.json looks like this:
{
"egs": [ "en" ],
"ps5": [ "en" ],
"steam": [ "en" ],
"psn": [ "en" ],
"live": [ "en" ],
"gdk": [ "en" ]
}
The platform store json files look like this:
{
"packages": [
{
"isOnPromo": false,
"isBundle": false,
"entitlesProducts": [
],
"itemType": "route",
"imageURLs": [
"",
""
],
"id": "000000000000",
"isVisible": true,
"title": "TITLE",
"logos": [
"",
""
],
"requires": [
"000000000000",
"000000000000"
],
"tags": [
"",
""
]
},
{
"isOnPromo": false,
"isBundle": false,
"entitlesProducts": [
],
"itemType": "loco",
"imageURLs": [
"",
""
],
"id": "000000000000",
"isVisible": true,
"title": "TITLE",
"logos": [
"",
""
],
"requires": [
"000000000000",
"000000000000"
],
"tags": [
"",
""
]
}
],
"rows": [
{
"name": "Category 1",
"weight": 1,
"packages": [
"000000000000",
"000000000000"
]
},
{
"name": "Category 2",
"weight": 2,
"packages": [
"000000000000",
"000000000000"
]
},
{
"name": "Category 3",
"weight": 3,
"packages": [
"000000000000",
"000000000000"
]
}
],
"products": [
]
}
Auto-formated them for you, thank me later[OnlineStore]
LiveServer="https://storage.googleapis.com/dtg-tsw2-dlc-dev/"
https://storage.googleapis.com/dtg-tsw2-dlc-dev/ 🔐
https://storage.googleapis.com/dtg-tsw2-dlc-dev/store.json
https://storage.googleapis.com/dtg-tsw2-dlc-dev/live-en.json
https://storage.googleapis.com/dtg-tsw2-dlc-dev/steam-en.json
https://storage.googleapis.com/dtg-tsw2-dlc-dev/gdk-en.json
[OnlineStore]
LiveServer="https://storage.googleapis.com/dtg-tsw2-dlc-test/"
https://storage.googleapis.com/dtg-tsw2-dlc-test/ 🔐
https://storage.googleapis.com/dtg-tsw2-dlc-test/store.json
https://storage.googleapis.com/dtg-tsw2-dlc-test/live-en.json
https://storage.googleapis.com/dtg-tsw2-dlc-test/steam-en.json
https://storage.googleapis.com/dtg-tsw2-dlc-test/gdk-en.json
https://storage.googleapis.com/dtg-tsw2-dlc-test/ps5-en.json
https://storage.googleapis.com/dtg-tsw2-dlc-test/psn-en.json
https://storage.googleapis.com/dtg-tsw2-dlc-test/egs-en.json
[OnlineStore]
LiveServer="https://tsw2-store.trainsimworld.net/"
https://tsw2-store.trainsimworld.net/ (redirects to http://tsw2-dlc-prod-origin.trainsimworld.net)
https://tsw2-store.trainsimworld.net/store.json
https://tsw2-store.trainsimworld.net/live-en.json
https://tsw2-store.trainsimworld.net/steam-en.json
https://tsw2-store.trainsimworld.net/gdk-en.json
https://tsw2-store.trainsimworld.net/ps5-en.json
Thanks to DTG's simple system custom stores are very easy to make. Unfourtunatly because the prices and descriptions are based on steam game IDs they are not editable and each ID can only be used once so no cheating.
(For hosting a custom stores I recomend GitHub like I did here)
The TSW 2 store is backwards-compatible with TSW 2020 with the below Game.ini-tweak, but not the other way around even though the files seem to be the same...
[OnlineStore]
FeedURL="https://storage.googleapis.com/dtg-tsw2-dlc-dev/"
TSW 2 store on TSW 2020
[DTGStats]
MaxEventsOffline=5000
DevServer="https://mastery.railsimdev.com"
DevEventPath="/mastery/game/event"
DevPingPath="/health"
TestServer="https://mastery-qa.railsimdev.com"
TestEventPath="/mastery/game/event"
TestPingPath="/health"
LiveServer="https://mastery.dovetailgames.com"
LiveEventPath="/mastery/game/event"
LivePingPath="/health"
The Mastery data is pulled as a JSON from the following URLs:
TSW 2: https://mastery.dovetailgames.com/mastery/tsw2
TSW 2020: https://mastery.dovetailgames.com/mastery/tsw
You can look at a specific user's Mastery by adding their username (NAME-XXXX) after a slash at the end of the URL.
They both have the same setup, just with different data and look like this in JSON form:
[WIP]
The Community Challange Rewards are fetched from https://mastery.dovetailgames.com/mastery/tsw2/community/rewards for TSW 2 or https://mastery.dovetailgames.com/mastery/tsw/community/rewards for TSW 2020 in JSON form:
[
{
"id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"franchise": 4,
"type": "DOWNLOAD_ITEM",
"title": "TITLE",
"description": "DESCRIPTION",
"image": "URL",
"image_hidden": "URL",
"image_expanded": "URL",
"value": 1,
"metadata": {
"id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"meta": { "download_url": "URL" }
},
"date_unlocked": "2021-10-14T23:00:00.000Z",
"unlocked": true,
"challenge": {
"id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"title": "EVENT TITLE",
"event_start": "2021-10-07T11:00:00.000Z",
"event_finish": "2021-10-14T23:00:00.000Z"
}
},
{
"id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"franchise": 4,
"type": "PROFILE_PICTURE",
"title": "TITLE",
"description": "DESCRIPTION",
"image": "URL",
"image_hidden": "URL",
"image_expanded": null,
"value": 1,
"date_unlocked": "2020-10-26T23:30:00.000Z",
"unlocked": true,
"challenge": {
"id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"title": "EVENT TITLE",
"event_start": "2020-10-05T12:00:00.000Z",
"event_finish": "2020-10-26T23:30:00.000Z"
}
}
]
The unlocked value get's it's data from the DTG servers based on your cookies, there is no way to look at a specific user by changing the URL.
The combined rewards list is fetched as a JSON from https://mastery.dovetailgames.com/mastery/tsw2/rewards/ for TSW 2 or https://mastery.dovetailgames.com/mastery/tsw/rewards/ for TSW 2020 and is a combination out of the above two JSONs. The mastery get's a mastery node and the community challanges a community node. You can look at a specific user's rewards by adding their username (NAME-XXXX) after a slash at the end of the URL.
TSW 2: https://mastery.dovetailgames.com/reports/tsw2/logs
TSW 2020: https://mastery.dovetailgames.com/reports/tsw/logs
If you try to fetch your entire logbook you are likely to end up with a 500 Server Error response, so use ?page=X&limit=X to only fetch a small part!
[LoadingScreens]
DevServer="https://storage.googleapis.com/dtg-tsw2-slides-dev/"
TestServer="https://storage.googleapis.com/dtg-tsw2-slides-test/"
LiveServer="https://tsw2-slides.trainsimworld.net/"
Train Sim World 2 and 2020 search for a json file named after this pattern [langauge]-[platform].json so for example en-stem.json on startup. This file contains URLs to image files which the client downloads and saves under C:\Users\[USERNAME]\Documents\My Games\TS2Prototype\Saved\LoadingScreens.
Here's how these json-files look like:
{
"feed": [ "[IMAGE URL]", "[IMAGE URL]" ],
"start": [],
"store": []
}
Pretty simple if you ask me.
Developer:
Usually just this image
[LoadingScreens]
LiveServer="https://storage.googleapis.com/dtg-tsw2-slides-dev/"
Test:
Usually none, so just a black screen
[LoadingScreens]
LiveServer="https://storage.googleapis.com/dtg-tsw2-slides-test/"
Live:
[LoadingScreens]
LiveServer="https://tsw2-slides.trainsimworld.net/"
None
[DovetailLive]
SandboxAuthServer="https://sandbox-auth.railsimdev.com"
SandboxLiveServer="https://sandbox-api.railsimdev.com"
SandboxIssuer="https://sandbox-auth.railsimdev.com/auth/realms/dtl"
DevAuthServer="https://auth.railsimdev.com"
DevLiveServer="https://api.railsimdev.com"
DevIssuer="https://auth.railsimdev.com/auth/realms/dtl"
ShipAuthServer="https://auth.dovetailgames.com"
ShipLiveServer="https://api.dovetailgames.com"
ShipIssuer="https://auth.dovetailgames.com/auth/realms/dtl"
ProductName="TSW2"
AuthClientId="tsw2"
TelemetryName="tsw2"
LocalisedTerms="fr de it pl ru zh es"
[DovetailLiveScreenshots]
DevServer="https://dtl-screenshot-dev.dovetailgames.net/api/v1/screenshot"
TestServer="https://dtl-screenshot-test.dovetailgames.net/api/v1/screenshot"
LiveServer="https://dtl-screenshot-prod.dovetailgames.net/api/v1/screenshot"
JPegQuality=90
[DTLEntitlements]
DevServer="https://entitlements-dev.dovetailgames.net"
TestServer="https://entitlements-test.dovetailgames.net"
LiveServer="https://entitlements-prod.dovetailgames.net"
When using the dev options of [DovetailLive] your normal Dovetail Live account won't work as this is a seperate DTL network, creating an account works just fine though. Also when uploading railfan shots they will be inaccessible because the https://react.railsimdev.com/train-sim-world/profile website where they end up is password protected.
To manage an account created on the railsimdev DTL network use https://auth.railsimdev.com/auth/realms/dtl/account/.
https://live.dovetailgames.com/api/profile-picture/NAME-XXXX
Returns a JSON with links to various sizes of the profile picture and the franchise & ID of the predetermined picture:
{
"franchise": "tsw",
"urlMed": "https://lh3.googleusercontent.com/[stuff]_q=s200",
"id": 115,
"urlSml": "https://lh3.googleusercontent.com/[stuff]_q=s100",
"urlLrg": "https://lh3.googleusercontent.com/[stuff]_q=s400"
}
https://id.dovetailgames.com/users/NAME-XXXX
Returns a JSON setup like this:
{
"displayName": "NAME",
"discriminator": "1234",
"kcUUID": "12345678-abcd-1234-abcd-123456789abc",
"createdAt": "2021-11-28T18:37:06.859Z",
"updatedAt": "2021-11-28T18:37:06.859Z",
"delimiter": "#",
"username": "NAME#1234",
"privacyOptions": {
"profile": "public",
"mastery": "public",
"screenshots": "public"
}
}