feat: add UE4SS DLL runtime extension
This commit is contained in:
@@ -161,6 +161,19 @@ func (svc *CoreService) dispatchExistingServerLifecycle(command domain.ServerLif
|
||||
if err := validator.ValidateServerInstanceDependencies(instance, plugin, endpoint); err != nil {
|
||||
return domain.ServerLifecycleResult{}, err
|
||||
}
|
||||
if action == domain.ServerLifecycleActionStart {
|
||||
binding, bindingErr := svc.runtimeBindingForServer(instance.ID)
|
||||
if bindingErr != nil && !errors.Is(bindingErr, repo.ErrNotFound) {
|
||||
return domain.ServerLifecycleResult{}, bindingErr
|
||||
}
|
||||
if bindingErr == nil {
|
||||
if profile, exists := runtimeLifecycleProfileForKey(plugin.RuntimeProfiles, binding.ProfileKey); exists && len(profile.DLLExtensionRefs) > 0 {
|
||||
if _, extensionErr := lifecycleDLLExtensionPlans(plugin.RuntimeProfiles, profile, endpoint); extensionErr != nil {
|
||||
return domain.ServerLifecycleResult{}, extensionErr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := svc.requireCompleteRuntimeBindings(instance.OwnerUserID, instance.ID, "server.lifecycle."+string(action)+".denied"); err != nil {
|
||||
return domain.ServerLifecycleResult{}, err
|
||||
}
|
||||
@@ -203,7 +216,8 @@ func (svc *CoreService) dispatchLifecycleJob(instance domain.ServerInstance, act
|
||||
return domain.Job{}, err
|
||||
}
|
||||
actionRef := binding.ProfileKey
|
||||
if profile, ok := runtimeLifecycleProfileForKey(plugin.RuntimeProfiles, binding.ProfileKey); ok {
|
||||
profile, hasProfile := runtimeLifecycleProfileForKey(plugin.RuntimeProfiles, binding.ProfileKey)
|
||||
if hasProfile {
|
||||
if ref := runtimeProfileActionRef(profile.ActionRefs, action); ref != "" {
|
||||
actionRef = ref
|
||||
}
|
||||
@@ -213,6 +227,17 @@ func (svc *CoreService) dispatchLifecycleJob(instance domain.ServerInstance, act
|
||||
if strings.TrimSpace(actionRef) == "" {
|
||||
return domain.Job{}, validationError(fmt.Sprintf("plugin %s lifecycle action is required", action))
|
||||
}
|
||||
var dllExtensions []domain.RuntimeDLLExtensionPlan
|
||||
if action == domain.ServerLifecycleActionStart && hasProfile {
|
||||
endpoint, err := svc.store.RunEndpoints().Get(instance.RunEndpointID)
|
||||
if err != nil {
|
||||
return domain.Job{}, err
|
||||
}
|
||||
dllExtensions, err = lifecycleDLLExtensionPlans(plugin.RuntimeProfiles, profile, endpoint)
|
||||
if err != nil {
|
||||
return domain.Job{}, err
|
||||
}
|
||||
}
|
||||
job, err := svc.CreateJob(domain.Job{
|
||||
ID: lifecycleJobID(instance.ID, action, idempotencyKey),
|
||||
ServerInstanceID: instance.ID,
|
||||
@@ -224,6 +249,7 @@ func (svc *CoreService) dispatchLifecycleJob(instance domain.ServerInstance, act
|
||||
WorkspaceScope: binding.ProfileKey,
|
||||
PluginID: plugin.ID,
|
||||
LifecycleOperation: lifecycleExecutionOperation(action),
|
||||
DLLExtensions: dllExtensions,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
@@ -274,6 +300,37 @@ func runtimeLifecycleProfileForKey(profiles domain.GamePluginRuntimeProfiles, ke
|
||||
return domain.RuntimeLifecycleProfile{}, false
|
||||
}
|
||||
|
||||
func lifecycleDLLExtensionPlans(profiles domain.GamePluginRuntimeProfiles, profile domain.RuntimeLifecycleProfile, endpoint domain.RunEndpoint) ([]domain.RuntimeDLLExtensionPlan, error) {
|
||||
if len(profile.DLLExtensionRefs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
byKey := make(map[string]domain.RuntimeDLLExtensionProfile, len(profiles.DLLExtensions))
|
||||
for _, extension := range profiles.DLLExtensions {
|
||||
byKey[extension.Key] = extension
|
||||
}
|
||||
plans := make([]domain.RuntimeDLLExtensionPlan, 0, len(profile.DLLExtensionRefs))
|
||||
for _, key := range profile.DLLExtensionRefs {
|
||||
extension, exists := byKey[key]
|
||||
if !exists || extension.ReleaseState != "ready" {
|
||||
return nil, validationError("extension_release_unavailable: selected DLL release is not ready")
|
||||
}
|
||||
if !runtimeDLLExtensionSupportsTarget(extension, endpoint.Platform, endpoint.Architecture) {
|
||||
return nil, validationError("unsupported_extension_platform: UE4SS DLL requires windows/amd64")
|
||||
}
|
||||
plans = append(plans, domain.RuntimeDLLExtensionPlan{Key: extension.Key, Version: extension.Version, ReleaseURL: extension.ReleaseURL, Checksum: extension.Checksum, SizeBytes: extension.SizeBytes, TargetKey: extension.TargetKey, ModKey: extension.ModKey, DLLRef: extension.DLLRef, SCUMExecutableChecksum: extension.SCUMExecutableChecksum, UE4SSABI: extension.UE4SSABI, RCONPort: extension.RCONPort})
|
||||
}
|
||||
return plans, nil
|
||||
}
|
||||
|
||||
func runtimeDLLExtensionSupportsTarget(extension domain.RuntimeDLLExtensionProfile, platform string, architecture string) bool {
|
||||
for _, target := range extension.SupportedTargets {
|
||||
if strings.EqualFold(target.OS, platform) && strings.EqualFold(target.Arch, architecture) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (svc *CoreService) validateLifecycleIdempotency(runEndpointID string, idempotencyKey string, serverInstanceID string, capability string) error {
|
||||
existing, err := svc.store.Jobs().GetByIdempotency(runEndpointID, idempotencyKey)
|
||||
if errors.Is(err, repo.ErrNotFound) {
|
||||
|
||||
Reference in New Issue
Block a user