Resolve canonical parties with campaign configuration
This commit is contained in:
@@ -167,12 +167,11 @@ func LoadWithSessionOptions(pipelinePath, campaignPath, sessionPath string, sess
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return LoadSessionWithPipelineCampaignOptions(LoadedPipelineCampaign{
|
||||
PipelinePath: pipelinePath,
|
||||
Pipeline: pipelineCfg,
|
||||
CampaignPath: campaignPath,
|
||||
Campaign: campaignCfg,
|
||||
}, sessionPath, sessionOpts)
|
||||
loaded, err := LoadPipelineCampaign(pipelinePath, pipelineCfg, campaignPath, campaignCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return LoadSessionWithPipelineCampaignOptions(loaded, sessionPath, sessionOpts)
|
||||
}
|
||||
|
||||
// LoadedPipelineCampaign retains one already loaded pipeline and campaign for
|
||||
@@ -183,6 +182,35 @@ type LoadedPipelineCampaign struct {
|
||||
Pipeline *PipelineConfig
|
||||
CampaignPath string
|
||||
Campaign *CampaignConfig
|
||||
Party ResolvedParty
|
||||
}
|
||||
|
||||
// LoadPipelineCampaign combines already loaded pipeline and campaign documents
|
||||
// with their campaign-owned party source. Callers that later resolve a session
|
||||
// retain this context rather than independently reimplementing party loading.
|
||||
func LoadPipelineCampaign(pipelinePath string, pipeline *PipelineConfig, campaignPath string, campaign *CampaignConfig) (LoadedPipelineCampaign, error) {
|
||||
if pipeline == nil {
|
||||
return LoadedPipelineCampaign{}, fmt.Errorf("pipeline config is required")
|
||||
}
|
||||
if campaign == nil {
|
||||
return LoadedPipelineCampaign{}, fmt.Errorf("campaign config is required")
|
||||
}
|
||||
party, err := resolveCampaignParty(campaignPath, campaign)
|
||||
if err != nil {
|
||||
return LoadedPipelineCampaign{}, err
|
||||
}
|
||||
if party.Mode == PartyModeCanonical {
|
||||
if err := validateCanonicalPartySelection(campaign, nil); err != nil {
|
||||
return LoadedPipelineCampaign{}, err
|
||||
}
|
||||
}
|
||||
return LoadedPipelineCampaign{
|
||||
PipelinePath: pipelinePath,
|
||||
Pipeline: pipeline,
|
||||
CampaignPath: campaignPath,
|
||||
Campaign: campaign,
|
||||
Party: party,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// LoadSessionWithPipelineCampaignOptions loads one local session and combines
|
||||
@@ -203,6 +231,24 @@ func LoadSessionWithPipelineCampaignOptions(loaded LoadedPipelineCampaign, sessi
|
||||
// the resolved pipeline/campaign context for callers that need to locate or
|
||||
// retrieve a session without rereading the root pipeline.
|
||||
func ResolveLoadedPipelineCampaign(loaded LoadedPipelineCampaign, sessionPath string, sessionCfg *SessionConfig, sessionSource SessionSource) (*Config, error) {
|
||||
if loaded.Pipeline == nil {
|
||||
return nil, fmt.Errorf("pipeline config is required")
|
||||
}
|
||||
if loaded.Campaign == nil {
|
||||
return nil, fmt.Errorf("campaign config is required")
|
||||
}
|
||||
if loaded.Party.Mode == "" {
|
||||
party, err := resolveCampaignParty(loaded.CampaignPath, loaded.Campaign)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
loaded.Party = party
|
||||
}
|
||||
if loaded.Party.Mode == PartyModeCanonical {
|
||||
if err := validateCanonicalPartySelection(loaded.Campaign, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
cfg := &Config{
|
||||
Pipeline: loaded.Pipeline,
|
||||
Campaign: loaded.Campaign,
|
||||
@@ -211,6 +257,12 @@ func ResolveLoadedPipelineCampaign(loaded LoadedPipelineCampaign, sessionPath st
|
||||
CampaignPath: loaded.CampaignPath,
|
||||
SessionPath: sessionPath,
|
||||
SessionSource: sessionSource,
|
||||
Party: loaded.Party,
|
||||
}
|
||||
if cfg.Party.Mode == PartyModeCanonical && sessionCfg != nil {
|
||||
if err := validateCanonicalPartySelection(loaded.Campaign, sessionCfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if sessionCfg == nil {
|
||||
return cfg, nil
|
||||
@@ -226,6 +278,22 @@ func ResolveLoadedPipelineCampaign(loaded LoadedPipelineCampaign, sessionPath st
|
||||
if strings.TrimSpace(cfg.SessionSource.LocalPath) == "" {
|
||||
cfg.SessionSource.LocalPath = sessionPath
|
||||
}
|
||||
if cfg.Party.Mode == PartyModeCanonical {
|
||||
stableInputs.PlayersFile = virtualPlayersInput()
|
||||
cfg.Session.Inputs.PlayersFile = ""
|
||||
} else {
|
||||
party, err := resolvePartyInput(stableInputs.PartyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if party.Mode == PartyModeCanonical {
|
||||
return nil, fmt.Errorf("session.inputs.party_file cannot select a canonical party; canonical parties are campaign-owned")
|
||||
}
|
||||
cfg.Party = party
|
||||
if strings.TrimSpace(stableInputs.PlayersFile.Path) == "" {
|
||||
return nil, fmt.Errorf("players_file is required with a legacy party")
|
||||
}
|
||||
}
|
||||
cfg.StableInputs = stableInputs
|
||||
return cfg, nil
|
||||
}
|
||||
@@ -236,12 +304,11 @@ func Resolve(pipelinePath string, pipelineCfg *PipelineConfig, campaignPath stri
|
||||
if sessionCfg == nil {
|
||||
return nil, fmt.Errorf("session config is required")
|
||||
}
|
||||
return ResolveLoadedPipelineCampaign(LoadedPipelineCampaign{
|
||||
PipelinePath: pipelinePath,
|
||||
Pipeline: pipelineCfg,
|
||||
CampaignPath: campaignPath,
|
||||
Campaign: campaignCfg,
|
||||
}, sessionPath, sessionCfg, sessionSource)
|
||||
loaded, err := LoadPipelineCampaign(pipelinePath, pipelineCfg, campaignPath, campaignCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ResolveLoadedPipelineCampaign(loaded, sessionPath, sessionCfg, sessionSource)
|
||||
}
|
||||
|
||||
func campaignSessionPaths(paths ...string) (campaignPath, sessionPath string, err error) {
|
||||
|
||||
Reference in New Issue
Block a user