feat: add UE4SS DLL runtime extension
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
package dto
|
||||
|
||||
import "browser.local/platform/domain"
|
||||
import (
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
)
|
||||
|
||||
type RuntimeTargetBody struct {
|
||||
OS string `json:"os"`
|
||||
@@ -23,6 +28,7 @@ type RuntimeLifecycleProfileBody struct {
|
||||
ActionRefs PluginLifecycleActionsBody `json:"actionRefs,omitempty"`
|
||||
TransportKeys []string `json:"transportKeys,omitempty"`
|
||||
ClientManagerRef string `json:"clientManagerRef,omitempty"`
|
||||
DLLExtensionRefs []string `json:"dllExtensionRefs,omitempty"`
|
||||
Platforms []string `json:"platforms,omitempty"`
|
||||
}
|
||||
|
||||
@@ -150,6 +156,62 @@ type RuntimeClientManagerProfileBody struct {
|
||||
UpdatePolicy RuntimeClientManagerUpdatePolicyBody `json:"updatePolicy,omitempty"`
|
||||
}
|
||||
|
||||
type RuntimeDLLExtensionProfileBody struct {
|
||||
Key string `json:"key"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Kind string `json:"kind"`
|
||||
Activation string `json:"activation"`
|
||||
Version string `json:"version"`
|
||||
ReleaseState string `json:"releaseState"`
|
||||
ReleaseURL string `json:"releaseUrl,omitempty"`
|
||||
ReleaseHost string `json:"releaseHost,omitempty"`
|
||||
ReleaseFilename string `json:"releaseFilename,omitempty"`
|
||||
Checksum string `json:"checksum,omitempty"`
|
||||
SizeBytes int64 `json:"sizeBytes,omitempty"`
|
||||
TargetKey string `json:"targetKey"`
|
||||
ModKey string `json:"modKey"`
|
||||
DLLRef string `json:"dllRef"`
|
||||
SCUMExecutableChecksum string `json:"scumExecutableChecksum,omitempty"`
|
||||
UE4SSABI string `json:"ue4ssAbi,omitempty"`
|
||||
SupportedTargets []RuntimeTargetBody `json:"supportedTargets"`
|
||||
UpdateOnStart bool `json:"updateOnStart"`
|
||||
RCONPort int `json:"rconPort"`
|
||||
}
|
||||
|
||||
// RuntimeDLLExtensionProfileResponseBody is the browser-safe projection of a
|
||||
// declared DLL extension. The immutable deployment path, RCON port, and full
|
||||
// release URL remain internal to the manifest/start-job contracts.
|
||||
type RuntimeDLLExtensionProfileResponseBody struct {
|
||||
Key string `json:"key"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Kind string `json:"kind"`
|
||||
Activation string `json:"activation"`
|
||||
Version string `json:"version"`
|
||||
ReleaseState string `json:"releaseState"`
|
||||
ReleaseHost string `json:"releaseHost,omitempty"`
|
||||
ReleaseFilename string `json:"releaseFilename,omitempty"`
|
||||
Checksum string `json:"checksum,omitempty"`
|
||||
SizeBytes int64 `json:"sizeBytes,omitempty"`
|
||||
SCUMExecutableChecksum string `json:"scumExecutableChecksum,omitempty"`
|
||||
UE4SSABI string `json:"ue4ssAbi,omitempty"`
|
||||
SupportedTargets []RuntimeTargetBody `json:"supportedTargets"`
|
||||
UpdateOnStart bool `json:"updateOnStart"`
|
||||
}
|
||||
|
||||
type RuntimeDLLExtensionPlanBody struct {
|
||||
Key string `json:"key"`
|
||||
Version string `json:"version"`
|
||||
ReleaseURL string `json:"releaseUrl"`
|
||||
Checksum string `json:"checksum"`
|
||||
SizeBytes int64 `json:"sizeBytes"`
|
||||
TargetKey string `json:"targetKey"`
|
||||
ModKey string `json:"modKey"`
|
||||
DLLRef string `json:"dllRef"`
|
||||
SCUMExecutableChecksum string `json:"scumExecutableChecksum"`
|
||||
UE4SSABI string `json:"ue4ssAbi"`
|
||||
RCONPort int `json:"rconPort"`
|
||||
}
|
||||
|
||||
type GamePluginRuntimeProfilesBody struct {
|
||||
Discovery []RuntimeDiscoveryProbeBody `json:"discovery,omitempty"`
|
||||
LifecycleProfiles []RuntimeLifecycleProfileBody `json:"lifecycleProfiles,omitempty"`
|
||||
@@ -159,6 +221,22 @@ type GamePluginRuntimeProfilesBody struct {
|
||||
LogEvents []RuntimeLogEventBody `json:"logEvents,omitempty"`
|
||||
TransportProfiles []RuntimeTransportProfileBody `json:"transportProfiles,omitempty"`
|
||||
ClientManagers []RuntimeClientManagerProfileBody `json:"clientManagers,omitempty"`
|
||||
DLLExtensions []RuntimeDLLExtensionProfileBody `json:"dllExtensions,omitempty"`
|
||||
}
|
||||
|
||||
// GamePluginRuntimeProfilesResponseBody is intentionally distinct from the
|
||||
// manifest input shape so browser responses cannot accidentally include
|
||||
// machine-local DLL placement or RCON activation details.
|
||||
type GamePluginRuntimeProfilesResponseBody struct {
|
||||
Discovery []RuntimeDiscoveryProbeBody `json:"discovery,omitempty"`
|
||||
LifecycleProfiles []RuntimeLifecycleProfileBody `json:"lifecycleProfiles,omitempty"`
|
||||
DependencyProbes []RuntimeDependencyProbeBody `json:"dependencyProbes,omitempty"`
|
||||
InstallPlans []RuntimeInstallPlanBody `json:"installPlans,omitempty"`
|
||||
LogSources []RuntimeLogSourceBody `json:"logSources,omitempty"`
|
||||
LogEvents []RuntimeLogEventBody `json:"logEvents,omitempty"`
|
||||
TransportProfiles []RuntimeTransportProfileBody `json:"transportProfiles,omitempty"`
|
||||
ClientManagers []RuntimeClientManagerProfileBody `json:"clientManagers,omitempty"`
|
||||
DLLExtensions []RuntimeDLLExtensionProfileResponseBody `json:"dllExtensions,omitempty"`
|
||||
}
|
||||
|
||||
func (body GamePluginRuntimeProfilesBody) ToDomain() domain.GamePluginRuntimeProfiles {
|
||||
@@ -167,7 +245,7 @@ func (body GamePluginRuntimeProfilesBody) ToDomain() domain.GamePluginRuntimePro
|
||||
profiles.Discovery = append(profiles.Discovery, domain.RuntimeDiscoveryProbe{Key: item.Key, Kind: item.Kind, TargetKey: item.TargetKey, Required: item.Required, Expected: item.Expected, Platforms: domain.CopyStringSlice(item.Platforms)})
|
||||
}
|
||||
for _, item := range body.LifecycleProfiles {
|
||||
profiles.LifecycleProfiles = append(profiles.LifecycleProfiles, domain.RuntimeLifecycleProfile{Key: item.Key, Mode: item.Mode, Capabilities: domain.CopyStringSlice(item.Capabilities), ActionRefs: item.ActionRefs.ToDomain(), TransportKeys: domain.CopyStringSlice(item.TransportKeys), ClientManagerRef: item.ClientManagerRef, Platforms: domain.CopyStringSlice(item.Platforms)})
|
||||
profiles.LifecycleProfiles = append(profiles.LifecycleProfiles, domain.RuntimeLifecycleProfile{Key: item.Key, Mode: item.Mode, Capabilities: domain.CopyStringSlice(item.Capabilities), ActionRefs: item.ActionRefs.ToDomain(), TransportKeys: domain.CopyStringSlice(item.TransportKeys), ClientManagerRef: item.ClientManagerRef, DLLExtensionRefs: domain.CopyStringSlice(item.DLLExtensionRefs), Platforms: domain.CopyStringSlice(item.Platforms)})
|
||||
}
|
||||
for _, item := range body.DependencyProbes {
|
||||
profiles.DependencyProbes = append(profiles.DependencyProbes, domain.RuntimeDependencyProbe{Key: item.Key, Kind: item.Kind, TargetKey: item.TargetKey, Required: item.Required, MinimumVersion: item.MinimumVersion, Platforms: domain.CopyStringSlice(item.Platforms)})
|
||||
@@ -207,17 +285,24 @@ func (body GamePluginRuntimeProfilesBody) ToDomain() domain.GamePluginRuntimePro
|
||||
}
|
||||
profiles.ClientManagers = append(profiles.ClientManagers, manager)
|
||||
}
|
||||
for _, item := range body.DLLExtensions {
|
||||
extension := domain.RuntimeDLLExtensionProfile{Key: item.Key, DisplayName: item.DisplayName, Kind: item.Kind, Activation: item.Activation, Version: item.Version, ReleaseState: item.ReleaseState, ReleaseURL: item.ReleaseURL, Checksum: item.Checksum, SizeBytes: item.SizeBytes, TargetKey: item.TargetKey, ModKey: item.ModKey, DLLRef: item.DLLRef, SCUMExecutableChecksum: item.SCUMExecutableChecksum, UE4SSABI: item.UE4SSABI, UpdateOnStart: item.UpdateOnStart, RCONPort: item.RCONPort}
|
||||
for _, target := range item.SupportedTargets {
|
||||
extension.SupportedTargets = append(extension.SupportedTargets, domain.RuntimeTarget{OS: target.OS, Arch: target.Arch})
|
||||
}
|
||||
profiles.DLLExtensions = append(profiles.DLLExtensions, extension)
|
||||
}
|
||||
return profiles
|
||||
}
|
||||
|
||||
func runtimeProfilesFromDomain(profiles domain.GamePluginRuntimeProfiles) GamePluginRuntimeProfilesBody {
|
||||
func runtimeProfilesFromDomain(profiles domain.GamePluginRuntimeProfiles) GamePluginRuntimeProfilesResponseBody {
|
||||
profiles = domain.CopyGamePluginRuntimeProfiles(profiles)
|
||||
body := GamePluginRuntimeProfilesBody{}
|
||||
body := GamePluginRuntimeProfilesResponseBody{}
|
||||
for _, item := range profiles.Discovery {
|
||||
body.Discovery = append(body.Discovery, RuntimeDiscoveryProbeBody{Key: item.Key, Kind: item.Kind, TargetKey: item.TargetKey, Required: item.Required, Expected: item.Expected, Platforms: item.Platforms})
|
||||
}
|
||||
for _, item := range profiles.LifecycleProfiles {
|
||||
body.LifecycleProfiles = append(body.LifecycleProfiles, RuntimeLifecycleProfileBody{Key: item.Key, Mode: item.Mode, Capabilities: item.Capabilities, ActionRefs: lifecycleActionsFromDomain(item.ActionRefs), TransportKeys: item.TransportKeys, ClientManagerRef: item.ClientManagerRef, Platforms: item.Platforms})
|
||||
body.LifecycleProfiles = append(body.LifecycleProfiles, RuntimeLifecycleProfileBody{Key: item.Key, Mode: item.Mode, Capabilities: item.Capabilities, ActionRefs: lifecycleActionsFromDomain(item.ActionRefs), TransportKeys: item.TransportKeys, ClientManagerRef: item.ClientManagerRef, DLLExtensionRefs: item.DLLExtensionRefs, Platforms: item.Platforms})
|
||||
}
|
||||
for _, item := range profiles.DependencyProbes {
|
||||
body.DependencyProbes = append(body.DependencyProbes, RuntimeDependencyProbeBody{Key: item.Key, Kind: item.Kind, TargetKey: item.TargetKey, Required: item.Required, MinimumVersion: item.MinimumVersion, Platforms: item.Platforms})
|
||||
@@ -257,5 +342,36 @@ func runtimeProfilesFromDomain(profiles domain.GamePluginRuntimeProfiles) GamePl
|
||||
}
|
||||
body.ClientManagers = append(body.ClientManagers, manager)
|
||||
}
|
||||
for _, item := range profiles.DLLExtensions {
|
||||
host, filename := safeDLLReleaseLocation(item.ReleaseURL)
|
||||
extension := RuntimeDLLExtensionProfileResponseBody{Key: item.Key, DisplayName: item.DisplayName, Kind: item.Kind, Activation: item.Activation, Version: item.Version, ReleaseState: item.ReleaseState, ReleaseHost: host, ReleaseFilename: filename, Checksum: safeDLLChecksumPrefix(item.Checksum), SizeBytes: item.SizeBytes, SCUMExecutableChecksum: safeDLLChecksumPrefix(item.SCUMExecutableChecksum), UE4SSABI: item.UE4SSABI, UpdateOnStart: item.UpdateOnStart}
|
||||
for _, target := range item.SupportedTargets {
|
||||
extension.SupportedTargets = append(extension.SupportedTargets, RuntimeTargetBody{OS: target.OS, Arch: target.Arch})
|
||||
}
|
||||
body.DLLExtensions = append(body.DLLExtensions, extension)
|
||||
}
|
||||
return body
|
||||
}
|
||||
|
||||
func dllExtensionPlansFromDomain(plans []domain.RuntimeDLLExtensionPlan) []RuntimeDLLExtensionPlanBody {
|
||||
items := make([]RuntimeDLLExtensionPlanBody, 0, len(plans))
|
||||
for _, item := range plans {
|
||||
items = append(items, RuntimeDLLExtensionPlanBody{Key: item.Key, Version: item.Version, ReleaseURL: item.ReleaseURL, Checksum: item.Checksum, SizeBytes: item.SizeBytes, TargetKey: item.TargetKey, ModKey: item.ModKey, DLLRef: item.DLLRef, SCUMExecutableChecksum: item.SCUMExecutableChecksum, UE4SSABI: item.UE4SSABI, RCONPort: item.RCONPort})
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func safeDLLReleaseLocation(value string) (string, string) {
|
||||
parsed, err := url.Parse(value)
|
||||
if err != nil || parsed == nil {
|
||||
return "", ""
|
||||
}
|
||||
return parsed.Hostname(), path.Base(parsed.Path)
|
||||
}
|
||||
|
||||
func safeDLLChecksumPrefix(value string) string {
|
||||
if len(value) <= len("sha256:")+12 {
|
||||
return value
|
||||
}
|
||||
return value[:len("sha256:")+12] + "…"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user