94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"gitea.maximumdirect.net/eric/narratio/internal/fileops"
|
|
)
|
|
|
|
const maxPartyDocumentBytes = 8 << 20
|
|
|
|
func resolvePartyInput(input ResolvedInputFile) (ResolvedParty, error) {
|
|
configuredPath := strings.TrimSpace(input.Path)
|
|
if configuredPath == "" {
|
|
return ResolvedParty{}, fmt.Errorf("party input path is required")
|
|
}
|
|
configPath := strings.TrimSpace(input.ConfigPath)
|
|
if configPath == "" {
|
|
return ResolvedParty{}, fmt.Errorf("party input %q has no declaring configuration path", configuredPath)
|
|
}
|
|
path := configuredPath
|
|
if !filepath.IsAbs(path) {
|
|
path = filepath.Join(filepath.Dir(configPath), path)
|
|
}
|
|
path = filepath.Clean(path)
|
|
raw, err := fileops.ReadRegularFile(path, maxPartyDocumentBytes)
|
|
if err != nil {
|
|
return ResolvedParty{}, fmt.Errorf("read party input %q: %w", path, err)
|
|
}
|
|
document, err := ParseParty(raw)
|
|
if err != nil {
|
|
return ResolvedParty{}, fmt.Errorf("parse party input %q: %w", path, err)
|
|
}
|
|
resolved := ResolvedParty{
|
|
Mode: document.Mode,
|
|
Source: PartySource{
|
|
Path: path,
|
|
ConfigPath: configPath,
|
|
Source: input.Source,
|
|
},
|
|
Canonical: document.Canonical,
|
|
}
|
|
if document.IsCanonical() {
|
|
return resolved, nil
|
|
}
|
|
return resolveLegacyParty(resolved)
|
|
}
|
|
|
|
func campaignPartyInput(campaignPath string, campaign *CampaignConfig) (ResolvedInputFile, error) {
|
|
if campaign == nil {
|
|
return ResolvedInputFile{}, fmt.Errorf("campaign config is required")
|
|
}
|
|
if strings.TrimSpace(campaign.Inputs.PartyFile) == "" {
|
|
return ResolvedInputFile{}, fmt.Errorf("campaign.inputs.party_file is required")
|
|
}
|
|
return ResolvedInputFile{
|
|
Path: campaign.Inputs.PartyFile,
|
|
ConfigPath: campaignPath,
|
|
Source: "campaign_config",
|
|
}, nil
|
|
}
|
|
|
|
func resolveCampaignParty(campaignPath string, campaign *CampaignConfig) (ResolvedParty, error) {
|
|
input, err := campaignPartyInput(campaignPath, campaign)
|
|
if err != nil {
|
|
return ResolvedParty{}, err
|
|
}
|
|
return resolvePartyInput(input)
|
|
}
|
|
|
|
func validateCanonicalPartySelection(campaign *CampaignConfig, session *SessionConfig) error {
|
|
if campaign == nil {
|
|
return fmt.Errorf("campaign config is required")
|
|
}
|
|
if strings.TrimSpace(campaign.Inputs.PlayersFile) != "" {
|
|
return fmt.Errorf("campaign.inputs.players_file is not allowed with a canonical party")
|
|
}
|
|
if session == nil {
|
|
return nil
|
|
}
|
|
if strings.TrimSpace(session.Inputs.PlayersFile) != "" {
|
|
return fmt.Errorf("session.inputs.players_file is not allowed with a canonical party")
|
|
}
|
|
if strings.TrimSpace(session.Inputs.PartyFile) != "" {
|
|
return fmt.Errorf("session.inputs.party_file cannot override a canonical campaign party")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func virtualPlayersInput() ResolvedInputFile {
|
|
return ResolvedInputFile{Source: "derived_from_party"}
|
|
}
|