Skip to content

Commit

Permalink
Add support for remote servers
Browse files Browse the repository at this point in the history
  • Loading branch information
mircearoata committed Dec 17, 2023
1 parent 1906aaf commit 9237ae8
Show file tree
Hide file tree
Showing 18 changed files with 264 additions and 19 deletions.
18 changes: 18 additions & 0 deletions backend/bindings/ficsitcli/installs.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ficsitcli

import (
"os"
"os/exec"
"sort"

Expand All @@ -17,6 +18,11 @@ func (f *FicsitCLI) initInstallations() error {
return errors.Wrap(err, "failed to initialize found installations")
}

err = f.initRemoteServerInstallations()
if err != nil {
return errors.Wrap(err, "failed to initialize remote server installations")
}

sort.Slice(f.installations, func(i, j int) bool {
if f.installations[i].Info.Launcher != f.installations[j].Info.Launcher {
return f.installations[i].Info.Launcher < f.installations[j].Info.Launcher
Expand Down Expand Up @@ -81,6 +87,18 @@ func (f *FicsitCLI) initLocalInstallations() error {
return nil
}

func (f *FicsitCLI) initRemoteServerInstallations() error {
for _, installation := range f.ficsitCli.Installations.Installations {
if _, err := os.Stat(installation.Path); errors.Is(err, os.ErrNotExist) {
// It is not a local installation
if err := f.AddRemoteServer(installation.Path); err != nil {
return errors.Wrap(err, "failed to add remote server")
}
}
}
return nil
}

func (f *FicsitCLI) GetInstallations() []*InstallationInfo {
return f.installations
}
Expand Down
9 changes: 2 additions & 7 deletions backend/bindings/ficsitcli/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"github.com/satisfactorymodding/ficsit-cli/cli"
"github.com/satisfactorymodding/ficsit-cli/utils"
wailsRuntime "github.com/wailsapp/wails/v2/pkg/runtime"

"github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders"
)

func (f *FicsitCLI) validateInstall(installation *InstallationInfo, progressItem string) error {
Expand Down Expand Up @@ -134,11 +132,8 @@ func (f *FicsitCLI) EmitModsChange() {
}

func (f *FicsitCLI) EmitGlobals() {
installInfos := make([]*installfinders.Installation, 0, len(f.installations))
for _, install := range f.installations {
installInfos = append(installInfos, install.Info)
}
wailsRuntime.EventsEmit(f.ctx, "installations", installInfos)
wailsRuntime.EventsEmit(f.ctx, "installations", f.GetInstallationsInfo())
wailsRuntime.EventsEmit(f.ctx, "remoteServers", f.GetRemoteInstallations())
profileNames := make([]string, 0, len(f.ficsitCli.Profiles.Profiles))
for k := range f.ficsitCli.Profiles.Profiles {
profileNames = append(profileNames, k)
Expand Down
93 changes: 93 additions & 0 deletions backend/bindings/ficsitcli/remote_servers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package ficsitcli

import (
"github.com/pkg/errors"

"github.com/satisfactorymodding/SatisfactoryModManager/backend/installfinders"
)

func (f *FicsitCLI) GetRemoteInstallations() []*installfinders.Installation {
remoteInstallations := []*installfinders.Installation{}
for _, install := range f.installations {
if install.Info.Location == installfinders.LocationTypeRemote {
remoteInstallations = append(remoteInstallations, install.Info)
}
}
return remoteInstallations
}

func (f *FicsitCLI) AddRemoteServer(path string) error {
installation := f.ficsitCli.Installations.GetInstallation(path)
if installation == nil {
fallbackProfile := "Default"
if f.ficsitCli.Profiles.GetProfile(fallbackProfile) == nil {
// Pick first profile found
for name := range f.ficsitCli.Profiles.Profiles {
fallbackProfile = name
break
}
}

var err error
installation, err = f.ficsitCli.Installations.AddInstallation(f.ficsitCli, path, fallbackProfile)
if err != nil {
return errors.Wrap(err, "failed to add installation")
}
}
gameVersion, err := installation.GetGameVersion(f.ficsitCli)
if err != nil {
return errors.Wrap(err, "failed to get game version")
}

platform, err := installation.GetPlatform(f.ficsitCli)
if err != nil {
return errors.Wrap(err, "failed to get platform")
}
var installType installfinders.InstallType
switch platform.TargetName {
case "Windows":
installType = installfinders.InstallTypeWindowsClient
case "WindowsServer":
installType = installfinders.InstallTypeWindowsServer
case "LinuxServer":
installType = installfinders.InstallTypeLinuxServer
}

branch := installfinders.BranchEarlyAccess // TODO: Do we have a way to detect this for remote installs?

f.installations = append(f.installations, &InstallationInfo{
Installation: installation,
Info: &installfinders.Installation{
Path: installation.Path,
Type: installType,
Location: installfinders.LocationTypeRemote,
Branch: branch,
Version: gameVersion,
Launcher: "Remote",
},
})

f.EmitGlobals()

return nil
}

func (f *FicsitCLI) RemoveRemoteServer(path string) error {
for _, install := range f.installations {
if install.Info.Path == path && install.Info.Location != installfinders.LocationTypeRemote {
return errors.New("installation is not remote")
}
}
err := f.ficsitCli.Installations.DeleteInstallation(path)
if err != nil {
return errors.Wrap(err, "failed to delete installation")
}
for i, install := range f.installations {
if install.Info.Path == path {
f.installations = append(f.installations[:i], f.installations[i+1:]...)
break
}
}
f.EmitGlobals()
return nil
}
2 changes: 2 additions & 0 deletions backend/installfinders/epic_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ func FindInstallationsWindowsEpic() ([]*Installation, []error) {
installs = append(installs, &Installation{
Path: epicManifest.InstallLocation,
Version: versionData.Changelist,
Type: InstallTypeWindowsClient,
Location: LocationTypeLocal,
Branch: branch,
Launcher: "Epic Games",
LaunchPath: []string{
Expand Down
2 changes: 2 additions & 0 deletions backend/installfinders/heroic_flatpak_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func FindInstallationsLinuxHeroicFlatpak() ([]*Installation, []error) {
installs = append(installs, &Installation{
Path: legendaryGame.InstallPath,
Version: version,
Type: InstallTypeWindowsClient,
Location: LocationTypeLocal,
Branch: branch,
Launcher: "Heroic",
LaunchPath: nil, // Heroic doesn't support launching from command line
Expand Down
2 changes: 2 additions & 0 deletions backend/installfinders/heroic_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func FindInstallationsLinuxHeroic() ([]*Installation, []error) {
installs = append(installs, &Installation{
Path: legendaryGame.InstallPath,
Version: version,
Type: InstallTypeWindowsClient,
Location: LocationTypeLocal,
Branch: branch,
Launcher: "Heroic",
LaunchPath: nil, // Heroic doesn't support launching from command line
Expand Down
2 changes: 2 additions & 0 deletions backend/installfinders/heroic_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ func FindInstallationsWindowsHeroic() ([]*Installation, []error) {
installs = append(installs, &Installation{
Path: legendaryGame.InstallPath,
Version: version,
Type: InstallTypeWindowsClient,
Location: LocationTypeLocal,
Branch: branch,
Launcher: "Heroic",
LaunchPath: nil, // Heroic doesn't support launching from command line
Expand Down
2 changes: 2 additions & 0 deletions backend/installfinders/legendary_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ func FindInstallationsLinuxLegendary() ([]*Installation, []error) {
installs = append(installs, &Installation{
Path: legendaryGame.InstallPath,
Version: version,
Type: InstallTypeWindowsClient,
Location: LocationTypeLocal,
Branch: branch,
Launcher: "Legendary",
LaunchPath: launchPath,
Expand Down
2 changes: 2 additions & 0 deletions backend/installfinders/legendary_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func FindInstallationsWindowsLegendary() ([]*Installation, []error) {
installs = append(installs, &Installation{
Path: legendaryGame.InstallPath,
Version: version,
Type: InstallTypeWindowsClient,
Location: LocationTypeLocal,
Branch: branch,
Launcher: "Legendary",
LaunchPath: launchPath,
Expand Down
2 changes: 2 additions & 0 deletions backend/installfinders/steam.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ func findInstallationsSteam(steamPath string, launcher string, executable []stri
installs = append(installs, &Installation{
Path: fullInstallationPath,
Version: versionData.Changelist,
Type: InstallTypeWindowsClient,
Location: LocationTypeLocal,
Branch: branch,
Launcher: launcher,
LaunchPath: append(
Expand Down
27 changes: 22 additions & 5 deletions backend/installfinders/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,29 @@ var (
BranchExperimental GameBranch = "Experimental"
)

type InstallType string

var (
InstallTypeWindowsClient InstallType = "WindowsClient"
InstallTypeWindowsServer InstallType = "WindowsServer"
InstallTypeLinuxServer InstallType = "LinuxServer"
)

type LocationType string

var (
LocationTypeLocal LocationType = "Local"
LocationTypeRemote LocationType = "Remote"
)

type Installation struct {
Path string `json:"path"`
Version int `json:"version"`
Branch GameBranch `json:"branch"`
Launcher string `json:"launcher"`
LaunchPath []string `json:"launchPath"`
Path string `json:"path"`
Version int `json:"version"`
Type InstallType `json:"type"`
Location LocationType `json:"location"`
Branch GameBranch `json:"branch"`
Launcher string `json:"launcher"`
LaunchPath []string `json:"launchPath"`
}

type InstallFindError struct {
Expand Down
2 changes: 2 additions & 0 deletions backend/installfinders/wine_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ func findInstallationsWineEpic(winePrefix string, launcher string, launchPath []
installs = append(installs, &Installation{
Path: wineInstallLocation,
Version: versionData.Changelist,
Type: InstallTypeWindowsClient,
Location: LocationTypeLocal,
Branch: branch,
Launcher: launcher,
LaunchPath: launchPath,
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lib/components/left-bar/LeftBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import Settings from './Settings.svelte';
import Updates from './Updates.svelte';
import LaunchButton from './LaunchButton.svelte';
import ServerManager from './ServerManager.svelte';
import SvgIcon from '$lib/components/SVGIcon.svelte';
import { installs, profiles, canModify, selectedInstall, selectedInstallPath, selectedProfile, modsEnabled, progress } from '$lib/store/ficsitCLIStore';
Expand Down Expand Up @@ -307,6 +308,7 @@
</div>
<div class="flex flex-col mt-4 h-md:mt-8">
<span class="pl-4">Other</span>
<ServerManager />
<Settings />
<Button variant="unelevated" class="w-full mt-2" on:click={() => BrowserOpenURL('https://docs.ficsit.app/satisfactory-modding/latest/ForUsers/SatisfactoryModManager.html')}>
<Label>
Expand Down
102 changes: 102 additions & 0 deletions frontend/src/lib/components/left-bar/ServerManager.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<script lang="ts">
import Button, { Label } from '@smui/button';
import { mdiServerNetwork, mdiTrashCan } from '@mdi/js';
import Dialog, { Actions, Content, Title } from '@smui/dialog';
import DataTable, { Body, Cell, Row } from '@smui/data-table';
import Select, { Option } from '@smui/select';
import Textfield from '@smui/textfield';
import SvgIcon from '$lib/components/SVGIcon.svelte';
import { remoteServers } from '$lib/store/ficsitCLIStore';
import { AddRemoteServer, RemoveRemoteServer } from '$lib/generated/wailsjs/go/ficsitcli/FicsitCLI';
import type { installfinders } from '$lib/generated/wailsjs/go/models';
let dialogOpen = false;
const allowedProtocols = ['ftp://'];
async function removeServer(server: installfinders.Installation) {
try {
await RemoveRemoteServer(server.path);
} catch (e) {
if(e instanceof Error) {
err = e.message;
} else if (typeof e === 'string') {
err = e;
} else {
err = 'Unknown error';
}
}
}
let newProtocol = allowedProtocols[0];
let newServerPath = '';
let err = '';
async function addNewRemoteServer() {
if (!newServerPath) {
return;
}
try {
await AddRemoteServer(newProtocol + newServerPath);
newServerPath = '';
} catch (e) {
if(e instanceof Error) {
err = e.message;
} else if (typeof e === 'string') {
err = e;
} else {
err = 'Unknown error';
}
}
}
</script>

<Button variant="unelevated" class="w-full mt-2" on:click={() => dialogOpen = true}>
<Label>
Manage Servers
</Label>
<div class="grow" />
<SvgIcon icon={mdiServerNetwork} class="h-5 w-5" />
</Button>

<Dialog
bind:open={dialogOpen} scrimClickAction="" escapeKeyAction=""
surface$style="max-height: calc(100vh - 128px); max-width: calc(100vw - 128px);"
surface$class="!min-w-[800px] min-h-[400px]"
>
<Title>Dedicated Servers</Title>
<Content>
<DataTable table$aria-label="Todo list" style="width: 100%;">
<Body>
{#each $remoteServers as remoteServer}
<Row>
<Cell>{remoteServer.path}</Cell>
<Cell>{remoteServer.type}</Cell>
<Cell>{remoteServer.version}</Cell>
<Cell>
<Button on:click={() => removeServer(remoteServer)}>
<SvgIcon icon={mdiTrashCan} class="!p-1 !m-0 !w-full !h-full group-hover:!hidden"/>
</Button>
</Cell>
</Row>
{/each}
</Body>
</DataTable>
<div class="mt-4">
<div class="flex h-10">
<Select bind:value={newProtocol} class="!h-full w-32">
{#each allowedProtocols as protocol}
<Option value={protocol}>{protocol}</Option>
{/each}
</Select>
<Textfield bind:value={newServerPath} class="!h-full grow mx-4"/>
<Button on:click={() => addNewRemoteServer()} class="!h-full">Add</Button>
</div>
<p>{err}</p>
</div>
</Content>
<Actions>
<Button on:click={() => dialogOpen = false}>Close</Button>
</Actions>
</Dialog>
2 changes: 1 addition & 1 deletion frontend/src/lib/components/mods-list/ModsList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
</script>

<div class="h-full flex flex-col">
<div class="flex-none">
<div class="flex-none z-10">
<ModListFilters />
</div>
<AnnouncementsBar />
Expand Down
Loading

0 comments on commit 9237ae8

Please sign in to comment.