├── .gitignore
├── appdata
├── Achievement
│ └── Standalone_0
└── options.xml
├── docker-compose.yml
├── config
├── com.starfi5h.plugin.BulletTime.cfg
├── nebulaGameDescSettings.cfg
└── nebula.cfg
├── .github
└── workflows
│ └── docker-publish.yml
├── Dockerfile
├── README.md
└── bin
└── entrypoint.nu
/.gitignore:
--------------------------------------------------------------------------------
1 | game
2 | save
3 | .vscode
--------------------------------------------------------------------------------
/appdata/Achievement/Standalone_0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WhyKickAmooCow/dsp-docker-server/HEAD/appdata/Achievement/Standalone_0
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 |
3 | services:
4 | dsp-server:
5 | image: ghcr.io/whykickamoocow/dsp-docker-server:master
6 | # build: ./
7 | ports:
8 | - 8469:8469
9 | volumes:
10 | - ./game:/game:z
11 | - ./save:/save:z
12 | # - ./bin/entrypoint.nu:/usr/bin/entrypoint.nu
13 |
--------------------------------------------------------------------------------
/config/com.starfi5h.plugin.BulletTime.cfg:
--------------------------------------------------------------------------------
1 | ## Settings file was created by plugin BulletTime v1.2.10
2 | ## Plugin GUID: com.starfi5h.plugin.BulletTime
3 |
4 | [Multiplayer]
5 |
6 | ## Minimum UPS in client of multiplayer game
7 | ## 联机-客户端的最小逻辑帧
8 | # Setting type: Single
9 | # Default value: 50
10 | MinimumUPS = $MIN_UPS
11 |
12 | [Save]
13 |
14 | ## Do auto-save in background thread
15 | ## 在背景执行自动存档
16 | # Setting type: Boolean
17 | # Default value: true
18 | EnableBackgroundAutosave = true
19 |
20 | ## Keyboard shortcut for auto-save
21 | ## 自动存档的热键组合
22 | # Setting type: KeyboardShortcut
23 | # Default value: F10 + LeftShift
24 | KeyAutosave = F10 + LeftShift
25 |
26 | [Speed]
27 |
28 | ## Increase main menu loading speed
29 | ## 加快载入主选单
30 | # Setting type: Boolean
31 | # Default value: true
32 | EnableFastLoading = true
33 |
34 | ## Remove force garbage collection of build tools
35 | ## 移除建筑工具的强制内存回收
36 | # Setting type: Boolean
37 | # Default value: true
38 | RemoveGC = true
39 |
40 | ## Game speed when the game begin (0-100)
41 | ## 游戏开始时的游戏速度 (0-100)
42 | # Setting type: Single
43 | # Default value: 100
44 | # Acceptable value range: From 0 to 100
45 | StartingSpeed = 100
46 |
47 |
--------------------------------------------------------------------------------
/appdata/options.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 6
4 |
5 |
21 |
27 |
28 | 480
29 | 1
30 | 1
31 | 1
32 | 1023
33 | 1
34 | 1
35 | 1
36 | 1024
37 | 1
38 | 0
39 | 1
40 | 0
41 |
42 |
43 |
44 | 1
45 | 2
46 | 1
47 |
48 |
--------------------------------------------------------------------------------
/config/nebulaGameDescSettings.cfg:
--------------------------------------------------------------------------------
1 | [Basic]
2 |
3 | ## Cluster Seed. Negative value: Random or remain the same.
4 | # Setting type: Int32
5 | # Default value: -1
6 | galaxySeed = $SEED
7 |
8 | ## Number of Stars. Negative value: Default(64) or remain the same.
9 | # Setting type: Int32
10 | # Default value: -1
11 | starCount = $STAR_COUNT
12 |
13 | ## Resource Multiplier. Infinte = 100. Negative value: Default(1.0f) or remain the same.
14 | # Setting type: Single
15 | # Default value: -1
16 | resourceMultiplier = $RESOURCE_MUTLIPLIER
17 |
18 | [Combat]
19 |
20 | ## Aggressiveness (Dummy = -1, Rampage = 3)
21 | # Setting type: Single
22 | # Default value: 1
23 | # Acceptable values: -1, 0, 0.5, 1, 2, 3
24 | aggressiveness = $COMBAT_AGGRESSIVENESS
25 |
26 | ## Initial Level (Original range: 0 to 10)
27 | # Setting type: Int32
28 | # Default value: 0
29 | # Acceptable value range: From 0 to 30
30 | initialLevel = $COMBAT_INITIAL_LEVEL
31 |
32 | ## Initial Growth (Original range: 0 to 200%)
33 | # Setting type: Single
34 | # Default value: 1
35 | initialGrowth = $COMBAT_INITIAL_GROWTH
36 |
37 | ## Initial Occupation (Original range: 1% to 200%
38 | # Setting type: Single
39 | # Default value: 1
40 | initialColonize = $COMBAT_INITIAL_COLONIZE
41 |
42 | ## Max Density (Original range: 1 to 3)
43 | # Setting type: Single
44 | # Default value: 1
45 | maxDensity = $COMBAT_MAX_DENSITY
46 |
47 | ## Growth Speed (Original range: 25% to 300%)
48 | # Setting type: Single
49 | # Default value: 1
50 | growthSpeedFactor = $COMBAT_GROWTH_SPEED_FACTOR
51 |
52 | ## Power Threat Factor (Original range: 1% to 1000%)
53 | # Setting type: Single
54 | # Default value: 1
55 | powerThreatFactor = $COMBAT_POWER_THREAT_FACTOR
56 |
57 | ## Combat Threat Factor (Original range: 1% to 1000%)
58 | # Setting type: Single
59 | # Default value: 1
60 | battleThreatFactor = $COMBAT_BATTLE_THREAT_FACTOR
61 |
62 | ## Combat XP Factor (Original range: 1% to 1000%)
63 | # Setting type: Single
64 | # Default value: 1
65 | battleExpFactor = $COMBAT_BATTLE_EXP_FACTOR
66 |
67 | [General]
68 |
69 | ## False: Enable enemy force (combat mode)
70 | # Setting type: Boolean
71 | # Default value: false
72 | isPeaceMode = $PEACE_MODE
73 |
74 | ## True: Enable creative mode
75 | # Setting type: Boolean
76 | # Default value: false
77 | isSandboxMode = $SANDBOX_MODE
78 |
79 |
--------------------------------------------------------------------------------
/.github/workflows/docker-publish.yml:
--------------------------------------------------------------------------------
1 | name: Docker
2 |
3 | # This workflow uses actions that are not certified by GitHub.
4 | # They are provided by a third-party and are governed by
5 | # separate terms of service, privacy policy, and support
6 | # documentation.
7 |
8 | on:
9 | schedule:
10 | - cron: "0 0 * * 1"
11 | push:
12 | branches: ["master"]
13 | # Publish semver tags as releases.
14 | tags: ["v*.*.*"]
15 | pull_request:
16 | branches: ["master"]
17 | workflow_dispatch:
18 |
19 | env:
20 | # github.repository as /
21 | IMAGE_NAME: ${{ github.repository }}
22 |
23 | jobs:
24 | build:
25 | runs-on: ubuntu-latest
26 | permissions:
27 | contents: read
28 | packages: write
29 | # This is used to complete the identity challenge
30 | # with sigstore/fulcio when running outside of PRs.
31 | id-token: write
32 |
33 | steps:
34 | - name: Checkout repository
35 | uses: actions/checkout@v3
36 |
37 | # Workaround: https://github.com/docker/build-push-action/issues/461
38 | - name: Setup Docker buildx
39 | uses: docker/setup-buildx-action@v3
40 |
41 | # Login against a Docker registry except on PR
42 | # https://github.com/docker/login-action
43 | - name: Log into GitHub registry
44 | if: github.event_name != 'pull_request'
45 | uses: docker/login-action@v3
46 | with:
47 | registry: ghcr.io
48 | username: ${{ github.actor }}
49 | password: ${{ secrets.GITHUB_TOKEN }}
50 |
51 | - name: Login to Docker Hub registry
52 | if: github.event_name != 'pull_request'
53 | uses: docker/login-action@v3
54 | with:
55 | username: ${{ secrets.DOCKER_USERNAME }}
56 | password: ${{ secrets.DOCKER_TOKEN }}
57 |
58 | # Extract metadata (tags, labels) for Docker
59 | # https://github.com/docker/metadata-action
60 | - name: Extract Docker metadata
61 | id: meta
62 | uses: docker/metadata-action@v5
63 | with:
64 | images: |
65 | ghcr.io/${{ env.IMAGE_NAME }}
66 | ${{ secrets.DOCKER_USERNAME }}/dsp-server
67 |
68 | # Build and push Docker image with Buildx (don't push on PR)
69 | # https://github.com/docker/build-push-action
70 | - name: Build and push Docker image
71 | id: build-and-push
72 | uses: docker/build-push-action@v5
73 | with:
74 | context: .
75 | push: ${{ github.event_name != 'pull_request' }}
76 | tags: ${{ steps.meta.outputs.tags }}
77 | labels: ${{ steps.meta.outputs.labels }}
78 | cache-from: type=gha
79 | cache-to: type=gha,mode=max
80 |
--------------------------------------------------------------------------------
/config/nebula.cfg:
--------------------------------------------------------------------------------
1 | [Nebula - Settings]
2 |
3 | # Setting type: String
4 | # Default value:
5 | Nickname = $SERVER_NAME
6 |
7 | # Setting type: String
8 | # Default value:
9 | ServerPassword = $SERVER_PASSWORD
10 |
11 | # Setting type: String
12 | # Default value:
13 | LastClientPassword =
14 |
15 | # Setting type: UInt16
16 | # Default value: 8469
17 | HostPort = $PORT
18 |
19 | # Setting type: Boolean
20 | # Default value: false
21 | EnableUPnpOrPmpSupport = false
22 |
23 | # Setting type: Boolean
24 | # Default value: false
25 | EnableNgrok = $ENABLE_NGROK
26 |
27 | # Setting type: String
28 | # Default value:
29 | NgrokAuthtoken = $NGROK_TOKEN
30 |
31 | # Setting type: String
32 | # Default value:
33 | NgrokRegion = $NGROK_REGION
34 |
35 | # Setting type: Boolean
36 | # Default value: true
37 | RememberLastIP = true
38 |
39 | # Setting type: Boolean
40 | # Default value: true
41 | RememberLastClientPassword = true
42 |
43 | # Setting type: Boolean
44 | # Default value: true
45 | EnableDiscordRPC = false
46 |
47 | # Setting type: Boolean
48 | # Default value: false
49 | AutoAcceptDiscordJoinRequests = false
50 |
51 | # Setting type: IPConfiguration
52 | # Default value: Both
53 | # Acceptable values: Both, IPv4, IPv6
54 | IPConfiguration = Both
55 |
56 | # Setting type: Boolean
57 | # Default value: true
58 | ShowLobbyHints = true
59 |
60 | # Setting type: String
61 | # Default value:
62 | LastIP =
63 |
64 | # Setting type: Boolean
65 | # Default value: true
66 | SyncUps = $SYNC_UPS
67 |
68 | # Setting type: Boolean
69 | # Default value: false
70 | SyncSoil = $SYNC_SOIL
71 |
72 | # Setting type: Boolean
73 | # Default value: false
74 | StreamerMode = false
75 |
76 | # Setting type: Boolean
77 | # Default value: true
78 | AutoOpenChat = true
79 |
80 | # Setting type: Boolean
81 | # Default value: true
82 | EnableWarnMessage = true
83 |
84 | # Setting type: Boolean
85 | # Default value: true
86 | EnableInfoMessage = true
87 |
88 | # Setting type: ChatPosition
89 | # Default value: LeftMiddle
90 | # Acceptable values: LeftMiddle, RightMiddle, LeftTop, RightTop
91 | DefaultChatPosition = LeftMiddle
92 |
93 | # Setting type: ChatSize
94 | # Default value: Medium
95 | # Acceptable values: Small, Medium, Big
96 | DefaultChatSize = Medium
97 |
98 | # Setting type: Int32
99 | # Default value: 15
100 | NotificationDuration = 15
101 |
102 | # Setting type: Boolean
103 | # Default value: true
104 | CleanupInactiveSessions = true
105 |
106 | # Setting type: Boolean
107 | # Default value: false
108 | PowerGridEnabled = false
109 |
110 | # Setting type: Boolean
111 | # Default value: false
112 | VeinDistributionEnabled = false
113 |
114 | # Setting type: Boolean
115 | # Default value: true
116 | SpaceNavigationEnabled = true
117 |
118 | # Setting type: Boolean
119 | # Default value: true
120 | BuildingWarningEnabled = true
121 |
122 | # Setting type: Boolean
123 | # Default value: true
124 | BuildingIconEnabled = true
125 |
126 | # Setting type: Boolean
127 | # Default value: true
128 | GuidingLightEnabled = true
129 |
130 | # Setting type: Boolean
131 | # Default value: false
132 | RemoteAccessEnabled = $REMOTE_ACCESS
133 |
134 | # Setting type: String
135 | # Default value:
136 | RemoteAccessPassword = $REMOTE_ACCESS_PASSWORD
137 |
138 | # Setting type: Boolean
139 | # Default value: true
140 | AutoPauseEnabled = $AUTO_PAUSE
141 |
142 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ghcr.io/whykickamoocow/steamcmd-wine:main
2 |
3 | RUN usermod -l dsp ubuntu \
4 | && groupmod -n dsp ubuntu \
5 | && usermod -d /home/dsp -m dsp
6 |
7 | RUN mkdir /game \
8 | && mkdir /save \
9 | && mkdir /config \
10 | && chown -R dsp:dsp /game /save /config
11 |
12 | USER dsp
13 | ENV USER dsp
14 | ENV HOME /home/dsp
15 | WORKDIR $HOME
16 |
17 | ENV WINEPREFIX=$HOME/.wine
18 | ENV WINEDLLOVERRIDES="mscoree=n,b;mshtml=n,b;winhttp=n,b"
19 | ENV WINEDEBUG=fixme-all,err-d3d_shader
20 |
21 | RUN winetricks -q dotnet48
22 |
23 | COPY config/ /config/
24 | RUN mkdir -p "/home/dsp/.wine/drive_c/users/dsp/Documents/Dyson Sphere Program"
25 | RUN ln -s /save "/home/dsp/.wine/drive_c/users/dsp/Documents/Dyson Sphere Program/Save"
26 | COPY ["appdata/", "/home/dsp/.wine/drive_c/users/dsp/Documents/Dyson Sphere Program/"]
27 |
28 | # Looks weird, but means that it can cache installing dotnet rather then needing to reinstall it every damn time I change the entrypoint or install scripts.
29 | USER root
30 | COPY --chmod=777 bin/* /usr/bin/
31 |
32 | ARG NUSHELL_VER="0.97.1"
33 | RUN mkdir -p /home/dsp/.config/nushell/ \
34 | && wget -q https://raw.githubusercontent.com/nushell/nushell/${NUSHELL_VER}/crates/nu-utils/src/sample_config/default_config.nu -O /home/dsp/.config/nushell/config.nu \
35 | && wget -q https://raw.githubusercontent.com/nushell/nushell/${NUSHELL_VER}/crates/nu-utils/src/sample_config/default_env.nu -O /home/dsp/.config/nushell/env.nu \
36 | && cd /tmp \
37 | && wget -q https://github.com/nushell/nushell/releases/download/${NUSHELL_VER}/nu-${NUSHELL_VER}-x86_64-unknown-linux-gnu.tar.gz \
38 | && tar -xzf nu* \
39 | && cd nu*-linux-gnu \
40 | && mv nu* /usr/bin \
41 | && chmod +x /usr/bin/nu
42 |
43 | RUN chown -R dsp:dsp /home/dsp/.config/nushell \
44 | && echo '/usr/bin/nu' >> /etc/shells \
45 | && usermod --shell /usr/bin/nu dsp \
46 | && ls /usr/bin/nu_plugin* \
47 | | xargs -I{} su -c 'plugin add {}' dsp \
48 | && rm -rf /tmp/*
49 |
50 | USER dsp
51 |
52 | #
53 | # Server config env vars
54 | #
55 |
56 | ENV LAUNCH_ARGS="-batchmode -nographics -server"
57 |
58 | ENV GENERATE_CONFIG=true
59 |
60 | ENV DSP_INSTALL_PATH=/game
61 |
62 | ## BulletTime
63 | # Minimum UPS in client of multiplayer game
64 | ENV MIN_UPS=50
65 |
66 | ## Nebula Multiplayer
67 | # ENV SERVER_NAME
68 | # ENV SERVER_PASSWORD
69 | ENV PORT=8469
70 | ENV ENABLE_NGROK=false
71 | # ENV NGROK_TOKEN
72 | #ENV NGROK_REGION
73 | ENV SYNC_UPS=true
74 | ENV SYNC_SOIL=false
75 | ENV REMOTE_ACCESS=false
76 | # ENV REMOTE_ACCESS_PASSWORD
77 | ENV AUTO_PAUSE=true
78 |
79 | ENV SEED=-1
80 | ENV STAR_COUNT=-1
81 | ENV RESOURCE_MUTLIPLIER=-1
82 |
83 | ENV PEACE_MODE=false
84 | ENV SANDBOX_MODE=false
85 |
86 | ENV COMBAT_AGGRESSIVENESS=1
87 | ENV COMBAT_INITIAL_LEVEL=0
88 | ENV COMBAT_INITIAL_GROWTH=1
89 | ENV COMBAT_INITIAL_COLONIZE=1
90 | ENV COMBAT_MAX_DENSITY=1
91 | ENV COMBAT_GROWTH_SPEED_FACTOR=1
92 | ENV COMBAT_POWER_THREAT_FACTOR=1
93 | ENV COMBAT_BATTLE_THREAT_FACTOR=1
94 | ENV COMBAT_BATTLE_EXP_FACTOR=1
95 |
96 | ENV REQUIRED_PLUGINS=nebula-NebulaMultiplayerMod,nebula-NebulaMultiplayerModApi,PhantomGamers-IlLine,CommonAPI-CommonAPI,starfi5h-BulletTime,xiaoye97-LDBTool,CommonAPI-DSPModSave
97 |
98 |
99 | #
100 | # Weston runtime setup
101 | #
102 |
103 | ENV XDG_RUNTIME_DIR=/tmp/dsp
104 | RUN mkdir /tmp/dsp && chmod 0700 /tmp/dsp
105 | RUN mkdir /tmp/.X11-unix
106 |
107 | ENV DISPLAY=:0
108 |
109 | ENTRYPOINT [ "/usr/bin/entrypoint.nu" ]
110 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | | :warning: Notice |
2 | | :-- |
3 | | Closing the server doesn't appear to automatically save the game in this container. It should still autosave, but use commands after enabling remote access to save manually. |
4 |
5 | # About
6 |
7 | This is a Dyson Sphere Program game server running inside a docker container. This is accomplished using WINE and using Goldberg's Steam Emu to allow launching the game straight from the exe without steam installed. This requires you to already own the game in Steam and to provide login details so the game can be downloaded. You can of course set up your DSP game with the mods you want and then patch it with Goldberg's yourself and put it in the ./game folder if you don't trust / dont want to provide login details.
8 |
9 | # Installation
10 |
11 | To install the DSP Server to the ./game directory run:
12 |
13 | ```
14 | # Make the directories we are going to mount so that Docker doesn't create them (they would be owned by root).
15 | mkdir ./game
16 | mkdir ./save
17 |
18 | # Only requires username, then it will ask for password and token while running. If you want to run it without interactivity then give it the password and 2FA token.
19 | docker run -it --rm -v $(pwd)/game:/game -v $(pwd)/save:/save -p 8469:8469 ghcr.io/whykickamoocow/dsp-docker-server:master username [password] [2FA-token]
20 | ```
21 |
22 | Then in order to run the server normally you can run:
23 |
24 | ```
25 | docker run -it --rm -v $(pwd)/game:/game -v $(pwd)/save:/save -p 8469:8469 ghcr.io/whykickamoocow/dsp-docker-server:master
26 | ```
27 |
28 | To update the server run:
29 |
30 | ```
31 | # To Update the game.
32 | docker run -it --rm -v $(pwd)/game:/game -v $(pwd)/save:/save -p 8469:8469 ghcr.io/whykickamoocow/dsp-docker-server:master update username [password] [2FA-token]
33 | # To only update the mods.
34 | docker run -it --rm -v $(pwd)/game:/game -v $(pwd)/save:/save -p 8469:8469 ghcr.io/whykickamoocow/dsp-docker-server:master update_mods
35 | ```
36 |
37 | # Environment Variables
38 |
39 | | Name | Default | Description |
40 | | --- | --- | --- |
41 | | WINEDLLOVERRIDES | mscoree=n,b;mshtml=n,b;winhttp=n,b | WINEDLLOVERRIDES as in WINE. |
42 | | DSP_INSTALL_PATH | /game | Where in the container DSP should be installed to. |
43 | | LAUNCH_ARGS | -batchmode -nographics -server | Arguments to pass to DSP when launching the game. |
44 | | REQUIRED_PLUGINS | nebula-NebulaMultiplayerMod,nebula-NebulaMultiplayerModApi,... | Comma delimited list of plugins to install to the server. In the format namespace-name[-version] |
45 | | ADDITIONAL_PLUGINS | | Comma delimited list of additional plugins to install to the server. |
46 | | MIN_UPS | 50 | Minimum UPS of client of multiplayer game (BulletTime). |
47 | | SERVER_NAME | | |
48 | | SERVER_PASSWORD | | [Nebula Docs](https://github.com/hubastard/nebula/wiki/Setup-Headless-Server#config-options) |
49 | | PORT | 8469 | The port for the server to listen on |
50 | | ENABLE_NGROK | false | [Nebula Ngrok Docs](https://github.com/hubastard/nebula/wiki/Hosting-and-Joining#ngrok-support) |
51 | | NGROK_TOKEN | | [Nebula Ngrok Docs](https://github.com/hubastard/nebula/wiki/Hosting-and-Joining#ngrok-support) |
52 | | NGROK_REGION | | [Nebula Ngrok Docs](https://github.com/hubastard/nebula/wiki/Hosting-and-Joining#ngrok-support) |
53 | | SYNC_UPS | true | [Nebula Docs](https://github.com/hubastard/nebula/wiki/About-Nebula#shared-resources) |
54 | | SYNC_SOIL | false | [Nebula Docs](https://github.com/hubastard/nebula/wiki/About-Nebula#shared-resources) |
55 | | REMOTE_ACCESS | false | [Nebula Docs](https://github.com/hubastard/nebula/wiki/Setup-Headless-Server#config-options) |
56 | | REMOTE_ACCESS_PASSWORD | | [Nebula Docs](https://github.com/hubastard/nebula/wiki/Setup-Headless-Server#config-options) |
57 | | AUTO_PAUSE | true | [Nebula Docs](https://github.com/hubastard/nebula/wiki/Setup-Headless-Server#config-options) |
58 | | STAR_COUNT | 64 | When creating a new save, how large the cluster should be. |
59 | | RESOURCE_MUTLIPLIER | 1.0 | What the resource multiplier should be when creating a new save. |
60 | | SEED | | If left blank, randomly generated. An integer seed for when creating a new save. |
61 | | GENERATE_CONFIG | true | Whether to overwrite the game configs at runtime, substituting environment variables into the file. |
62 | | SAVE | | Manually specify what to use for save game related [CLI args](https://github.com/NebulaModTeam/nebula/wiki/Setup-Headless-Server#nebula-cli-arguments) |
63 | | PEACE_MODE | false | Disable combat |
64 | | SANDBOX_MODE | false | Enable sandbox mode |
65 | | COMBAT\_\* | Defaults of nebulaGameDescSettings.cfg | nebulaGameDescSettings.cfg combat settings |
66 |
67 | # Credits
68 |
69 | https://github.com/AlienXAXS/DSPNebulaDocker - This project uses a slimmed down version of their install script (particularly for installing the plugins).
70 |
--------------------------------------------------------------------------------
/bin/entrypoint.nu:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env nu
2 |
3 | let bepinex_plugins = do {
4 | let required = $env.REQUIRED_PLUGINS | split row ',' | each {|plugin| modstring_to_record $plugin}
5 | let additional_plugins = $env.ADDITIONAL_PLUGINS?
6 | if $additional_plugins != null {
7 | print $additional_plugins
8 | $required ++ (($additional_plugins | split row ',') | each {|plugin| modstring_to_record $plugin})
9 | } else {
10 | $required
11 | }
12 | }
13 |
14 | def modstring_to_record [modstring: string] -> record {
15 | let split = $modstring | split row '-'
16 | let retval = {namespace: $split.0, name: $split.1}
17 | if $split.2? != null {
18 | $retval | insert version $split.2
19 | } else {
20 | $retval
21 | }
22 | }
23 |
24 | def get_or_default [input, key, default: any = null] {
25 | if ($input | get -i $key) != null {
26 | $input | get $key
27 | } else {
28 | $default
29 | }
30 | }
31 |
32 | def main [...args] {
33 | match ($args.0?) {
34 | "update" => {
35 | install_game (get_or_default $args 1 "" | into string) (get_or_default $args 2 "" | into string) (get_or_default $args 3 "" | into string)
36 | install_mods $bepinex_plugins
37 | },
38 | "update_mods" => {
39 | install_mods $bepinex_plugins
40 | },
41 | _ => {
42 | if ($"($env.DSP_INSTALL_PATH)/DSPGAME.exe" | path exists) {
43 | if (echo $args | length) > 0 {
44 | error make {msg: $"Unknown argument ($args.0)"}
45 | }
46 | } else {
47 | main update $args.0? $args.1? $args.2?
48 | }
49 | }
50 | }
51 |
52 | run_game
53 | }
54 |
55 | def install_game [username: string, password: string, code: string] {
56 | if ($username | is-empty) {
57 | error make {msg: "You are required to provide a steam login that owns Dyson Sphere Program"}
58 | }
59 |
60 | steamcmd +force_install_dir $env.DSP_INSTALL_PATH +login $username $password $code +@sSteamCmdForcePlatformType windows +app_update 1366540 validate +quit
61 |
62 | http get https://gitlab.com/Mr_Goldberg/goldberg_emulator/-/jobs/4247811307/artifacts/raw/release/steam_api64.dll | save -f $"($env.DSP_INSTALL_PATH)/DSPGAME_Data/Plugins/steam_api64.dll"
63 |
64 | mkdir $"($env.DSP_INSTALL_PATH)/DSPGAME_Data/Plugins/steam_settings"
65 | touch $"($env.DSP_INSTALL_PATH)/DSPGAME_Data/Plugins/steam_settings/disable_networking.txt"
66 |
67 | "1366540" | save -f $"($env.DSP_INSTALL_PATH)/steam_appid.txt"
68 | }
69 |
70 | def install_mods [mods] {
71 | print "Installing BepInEx"
72 |
73 | rm -rf $"($env.DSP_INSTALL_PATH)/BepInEx"
74 |
75 | cd $env.DSP_INSTALL_PATH
76 | let latest_json = http get https://api.github.com/repos/BepInEx/BepInEx/releases/latest
77 | let asset = $latest_json.assets | where name =~ ^BepInEx_win_x64 | first
78 |
79 | http get $asset.browser_download_url | save $asset.name
80 | unzip -qq -o $asset.name
81 | rm $asset.name
82 |
83 | print $"Installing Mods: ($mods)"
84 |
85 | mkdir $"($env.DSP_INSTALL_PATH)/BepInEx/plugins"
86 | mkdir $"($env.DSP_INSTALL_PATH)/BepInEx/patchers"
87 |
88 | mkdir /tmp/dsp-mods
89 |
90 | for mod in $mods {
91 | cd /tmp/dsp-mods
92 |
93 | print $"Installing ($mod):"
94 |
95 | let asset = http get https://thunderstore.io/api/experimental/package/($mod.namespace)/($mod.name)/($mod.version?)
96 | let version = if $mod.version? != null {$mod.version} else {$asset.latest.version_number}
97 | let download_url = if $mod.version? != null {$asset.download_url} else {$asset.latest.download_url}
98 |
99 | print $"Downloading ($asset.name):($version) from ($download_url)"
100 |
101 | http get $download_url | save $"($asset.name).zip"
102 | mkdir $asset.name
103 | unzip -qq -o $"($asset.name).zip" -d $asset.name
104 | rm -f $"($asset.name).zip"
105 |
106 | cd $asset.name
107 |
108 | if ("./plugins" | path exists) {
109 | mkdir $"($env.DSP_INSTALL_PATH)/BepInEx/plugins/($asset.name)"
110 | cp -rf ./plugins/* $"($env.DSP_INSTALL_PATH)/BepInEx/plugins/($asset.name)"
111 | } else {
112 | cp -rf ./ $"($env.DSP_INSTALL_PATH)/BepInEx/plugins/"
113 | }
114 |
115 | if ("./patchers" | path exists) {
116 | mkdir $"($env.DSP_INSTALL_PATH)/BepInEx/patchers/($asset.name)"
117 | cp -rf ./patchers/* $"($env.DSP_INSTALL_PATH)/BepInEx/patchers/($asset.name)/"
118 | }
119 | }
120 | }
121 |
122 |
123 | def run_game [] {
124 | mkdir $"($env.DSP_INSTALL_PATH)/BepInEx/config"
125 |
126 | if ($env.GENERATE_CONFIG? | into bool) {
127 | for file in (ls /config/) {
128 | open --raw $file.name | envsubst | save -f $"($env.DSP_INSTALL_PATH)/BepInEx/config/($file.name | path basename)"
129 | }
130 | }
131 |
132 | mut save = -load-latest
133 | if (ls /save | length) == 0 {
134 | $save = "-newgame-cfg"
135 | }
136 |
137 | if $env.SAVE? != null {
138 | $save = $env.SAVE
139 | }
140 |
141 | bash -c "weston --xwayland -B headless &"
142 | wine $"($env.DSP_INSTALL_PATH)/DSPGAME.exe" ...($env.LAUNCH_ARGS | split row ' ') ...($save | split row ' ')
143 | }
--------------------------------------------------------------------------------