Skip to content

Latest commit

 

History

87 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Terra Invicta Save Parser

Small local parser for Terra Invicta .gz saves. It reads the full save once, builds a compact indexed snapshot, and reuses a cache keyed by save path, size, modification time, and packaged runtime catalog bytes. Cache hits validate the current runtime bundle; malformed cache entries rebuild automatically, and completed cache files replace previous entries atomically.

Implementation layout:

  • tools/ti_parser_core.py owns save loading, template loading, indexing, and reference helpers.
  • tools/ti_parser_snapshot.py owns compact snapshot summaries and snapshot cache handling.
  • tools/ti_parser_income.py owns councilor and nation income calculations.
  • tools/ti_parser_hab.py owns hab module, support, mining, and power calculations.
  • tools/ti_parser_org.py owns org-plan parsing, conditional evaluation, and committee assignment search.
  • tools/ti_parser_ship.py owns pure ship component, resource, power, armor, and ranking helpers.
  • tools/ti_parser_ship_plan.py owns saved-design simulation, shipyard timing, and ship plans.
  • tools/ti_parser_hab_ui.py owns hab location, solar power, UI, and slot calculations.
  • tools/ti_parser_hab_construction.py owns build requirements, materials, timing, and economic deltas.
  • tools/ti_parser_hab_plan.py owns module candidate scoring, upgrade selection, and fill plans.
  • tools/ti_parser_research.py owns research income, category modifiers, distribution, and current research UI.
  • tools/ti_parser_research_plan.py owns available research candidates and planning scores.
  • tools/ti_parser_project_analysis.py owns project consequences, module unlocks, and resource tradeoffs.
  • tools/ti_parser_topbar.py owns faction income aggregation, maintenance, and resource forecasts.
  • tools/ti_parser_world.py owns world population, environment, markets, wars, and atrocities.
  • tools/ti_parser_nation_ui.py owns nation display values and priority-validity presentation.
  • tools/ti_parser_projection_adapter.py extracts save state and assembles inputs for the projection engine.
  • tools/ti_parser_config.py owns shared constants and configured calculation settings.
  • tools/ti_parser_runtime.py owns configured snapshot/income/hab adapters and shared save-state helpers.
  • tools/ti_parser_commands.py owns CLI input loading, domain calls, and output rendering.
  • tools/ti_parser_cli.py owns argument parsing and command dispatch.
  • tools/ti_parser_catalogs.py validates the packaged runtime bundle, manifest, exact scenario overlays, and fingerprints.
  • tools/ti_parser_mechanics.py owns stable mechanics rule IDs and DLL/catalog/test provenance.
  • tools/ti_parser_nation_validity.py owns the shared value-only, tri-state priority-validity evaluator.
  • tools/ti_parser_nation_projection.py owns cloned projection state, plan parsing, transactional updates, and fail-closed coverage.
  • tools/ti_parser_projection_coverage.py owns execution-derived metric evidence and dependency propagation.
  • tools/ti_save_parser.py keeps only the public script entrypoint and explicit compatibility exports. Existing function names and signatures remain available.
  • tools/catalog_utils.py contains shared catalog-generator helpers.

Domain modules import their dependencies directly and do not import the public facade. Their dependency graph is acyclic. Tests or integrations that replace a dependency with a mock should patch the module where it is used, rather than rebinding the facade export.

Examples:

python .\tools\ti_save_parser.py summary
python .\tools\ti_save_parser.py faction ResistCouncil
python .\tools\ti_save_parser.py nation KOR
python .\tools\ti_save_parser.py councilor Hanna
python .\tools\ti_save_parser.py councilor Hanna --target-nation USA --details
python .\tools\ti_save_parser.py councilor Hanna --current-location-context
python .\tools\ti_save_parser.py org-plan --focus balanced
python .\tools\ti_save_parser.py org-plan --focus science --market-only --top 3
python .\tools\ti_save_parser.py nation-ui "유럽 연합"
python .\tools\ti_save_parser.py hab-ui "제303기초연구단"
python .\tools\ti_save_parser.py hab-slots --faction ResistCouncil
python .\tools\ti_save_parser.py hab-plan --upgrading-to-tier 3 --focus research
python .\tools\ti_save_parser.py ship-plan --role colony --top 5
python .\tools\ti_save_parser.py ship-plan --role combat --include-obsolete
python .\tools\ti_save_parser.py ship-plan --design "PKG Defiant"
python .\tools\ti_save_parser.py project-analysis --top 10 --sort research-sustainable
python .\tools\ti_save_parser.py research --details
python .\tools\ti_save_parser.py research-ui
python .\tools\ti_save_parser.py research-plan --top 5
python .\tools\ti_save_parser.py topbar --details
python .\tools\ti_save_parser.py nation-claims KOR --target PRK --diagnostics
python .\tools\ti_save_parser.py nation-projection KOR --days 365
python .\tools\ti_save_parser.py nation-projection KOR --days 365 --plan-file plans.json --checkpoints 30,90,180,365
python .\tools\ti_save_parser.py nation-projection KOR --days 365 --plan-file plans.json --details --diagnostics
python .\tools\ti_save_parser.py ai-fleet-diagnostics --stale-days 365
python .\tools\build_research_catalog.py
python .\tools\build_runtime_catalogs.py --templates-dir "C:\...\StreamingAssets\Templates"
python .\tools\ti_save_parser.py --templates-dir "C:\...\StreamingAssets\Templates" catalog-verify --scenario ModernScenario
python .\tools\build_module_catalog.py
python .\tools\build_location_catalog.py
python .\tools\verify_fresh_export.py
python .\tools\ti_save_parser.py world-ui
python .\tools\ti_save_parser.py advise "Lati Wirya" "중화민국"
python .\tools\ti_save_parser.py types --limit 30
python .\tools\ti_save_parser.py raw --type TIFactionState --template ResistCouncil --keys displayName,resources,baseIncomes_year,missionControlUsage

Use global options such as --save <path> and --refresh-cache before the subcommand.

Package-only runtime and incomplete results

Normal commands do not discover or read an installed Terra Invicta template tree. Calculation data comes from the packaged effect, trait, org, research, ship, nation-claim, hab-module, and location catalogs under data/. Raw base/DLC templates and Assembly-CSharp.dll are generation or catalog-verify inputs only. --templates-dir is verification-only and is rejected for normal commands.

The common catalog_manifest.json records each new runtime catalog's file SHA-256, schema version, payload fingerprint, and a bundle fingerprint. Catalog envelopes contain deterministic source hashes, supported canonical scenarios, base data, and exact scenario overrides; timestamps and mtimes are excluded. Unsupported scenarios never inherit another scenario's values.

Each CLI invocation reuses its validated runtime bundles for matching scenario, data directory, and requested catalogs. The next invocation validates files again. Library callers can opt into the same lifetime with ti_parser_catalogs.runtime_catalog_scope(); otherwise loads remain fresh.

If a save references a required effect, trait, applying org, active hab module/body location, weighted research row, saved ship component, or packaged shipyard that cannot be resolved, the CLI exits with code 2 and prints status: "incomplete" plus structured missingDependencies. Valid absence remains valid: empty source lists, non-applying orgs, zero-weight or locked research slots, and empty optional ship slots do not require catalog rows. Successful command JSON keeps its existing result shape.

Commands with --diagnostics include the selected scenario and catalog fingerprints. nation-claims --diagnostics keeps runtime provenance and rule-domain evidence separately under calculationDiagnostics.runtime and .claims, so scenario/fingerprint data cannot overwrite threshold, formula, assumptions, limitations, or missing-dependency evidence.

Ship catalogs are generated by resolving each component family against the exact scenario template tree and storing recursive minimal deltas. Weapon names are checked for cross-family collisions for base and every scenario. If the installed DLC supplies no ship overrides, the corresponding packaged scenario correctly reuses the base rows and reports no ship override applied.

catalog-verify is the only command that consumes raw templates. It rebuilds normalized reference catalogs, checks source hashes and scenario overlays, and—when a matching save is available—compares Mercury solar, CP cap, MC, research, org eligibility, and saved-design simulation with rel_tol=1e-9 and abs_tol=1e-6.

catalog-verify exits with code 0 only when every check passes. Failed or unavailable checks produce code 2 and preserve the detailed failed or partial JSON report. With no local save, catalog checks still run and save-dependent checks are reported as unavailable; an explicitly requested missing save is an error.

verify_fresh_export.py is the cross-platform release gate. It creates a temporary git -c core.autocrlf=false archive HEAD, runs the full and package-only suites inside that export, and loads every packaged supported scenario. This verifies committed bytes and manifest hashes rather than trusting the current checkout's line-ending conversion.

Councilor attributes are calculated from save base values plus unconditional trait and active-org modifiers, then clamped to the game's normal 25 cap. Conditional trait modifiers are not mixed into finalAttributes; use --target-nation <name/code> or --current-location-context to get contextualAttributes for a specific situation.

The org-plan command evaluates the faction's currently acquirable availableOrgs against every councilor. It reports per-councilor views for balanced stats and each individual stat, applies the Administration capacity limit, checks acquisition costs, required/prohibited owner traits, nation interest, and faction ideology restrictions, and recommends a committee-wide assignment sequence. candidateSources is a diagnostic inventory rather than a recommendation list; each row's recommendationEligibility is derived from its actual eligibleCouncilors, while actionable stat views are emitted under councilors.goalViews and committeePlan. Already-owned unassigned orgs are included by default so useful inventory is assigned before spending resources; pass --market-only to evaluate acquisitions only. The committee plan uses a bounded beam search with practical defaults; increase --max-actions or --beam-width when a slower, broader search is useful.

The research command recalculates the UI's daily research tooltip from raw save values, including councilor trait/org income, CP research effects, knowledge-sector bonuses, hab efficiency modules, excess MC research, and research-distribution bonuses. The advise command applies one hypothetical Advise assignment to a nation and reports both the direct source increase and the final increase after research-distribution bonuses.

The research-ui command reconstructs the Research screen's active slots. It reads the three global techs from TIGlobalResearchState.techProgress, active faction projects from TIFactionState.currentProjectProgress slots 3-5, slot weights from researchWeights, category/project-facility modifiers, current progress, daily slot output, faction contribution bars, and ETA dates. Project records in slots 6+ are reported separately as paused/stored progress, not as currently active project research slots.

The research-plan command builds an LLM-ready report for the question "what global tech or faction project should I research next?" It automates objective candidate collection and evidence shaping: currently active slots, paused projects, available global techs, available projects, research costs, ETA estimates at current slot weights, category synergy, downstream unlock counts, critical template flags, resource-deficiency coverage, and existing progress. It intentionally does not collapse those signals into a final strategic utility ranking; the output includes goal-specific score views and source notes so an LLM can make the value judgment explicitly.

The topbar command reconstructs the top resource bar from the save, including current stockpiles, monthly/yearly net resource income, research distribution, mission-control usage/capacity, and control-point maintenance usage/cap. Its MissionControl row keeps current values separate from projectedAfterCurrentQueue; habitat and project planning use that queued projection while current research and excess-MC calculations use only operating sources.

Factioned commands resolve the human player from TIPlayerState.isAI == false and cross-check TIMetadataState.playerFactionName. They fail closed when the player is missing, ambiguous, or conflicting; an explicit faction argument or --faction remains an override. Faction identity output includes display name, internal template, and player status.

topbar --diagnostics adds module/location catalog and effect provenance, mining formula samples, and explicit calculation assumptions. topbar --forecast-resource Volatiles recalculates faction-hab production and support after each module completion, reports the completing modules and resulting hab power balance, and identifies the first sustained positive event. A projected negative-power hab marks the forecast incomplete instead of silently treating every completed module as operational.

The packaged data/module_catalog.json is the runtime source of truth for hab module income, upkeep, crew, power, MC, CP cap, build cost, requirements, and bonuses. Missing catalogs or referenced templates are fatal calculation-data errors, never zero-valued modules. The catalog generator reads raw templates from the local Terra Invicta install and refreshes that JSON plus the human-readable docs/module_catalog.md; raw module templates are generator inputs, not an implicit runtime fallback.

The packaged data/location_catalog.json is the runtime source of truth for location-aware body, Lagrange-point navigable, and orbit values used by solar output, gravity, irradiation, construction, and mining calculations. Missing, corrupt, empty, or incompatible catalogs are fatal calculation-data errors. Variable-output solar modules also fail when their exact body/orbit dependency cannot be resolved; they never use nominal power as a fallback because that value can be wrong by several times near Mercury. build_location_catalog.py reads the raw TISpaceBodyTemplate.json, TINavigableTemplate.json, and TIOrbitTemplate.json files only to regenerate the packaged catalog. Normal parser execution does not read those raw files.

The research catalog v2 generator reads global tech and faction project templates from the local Terra Invicta install and writes data/research_catalog.json plus docs/research_catalog.md. The JSON stores research prerequisites as explicit all/any boolean trees, plus derived graph indexes such as edges and childrenByPrereq. Save-specific completion, objectives, milestones, faction gates, and nation gates should be evaluated against that static catalog rather than baked into it.

The world-ui command reconstructs the Intel screen's world tab values: population, GDP, global public opinion, resource market prices, environmental damage, active wars, and faction atrocity counts.

The nation-ui command reconstructs the nation panel values used for UI validation, including federation-pooled funding/boost income, faction research share, control-point priority weights, accumulated investment points, public opinion, army/navy limits, nukes, and diplomacy lists.

The nation-projection command simulates conditional control-point priority and Advisor policies without mutating the loaded save. Segment conditions are observed only after a complete investment or verified periodic transaction; a satisfied segment takes effect immediately before the next investment tick. nation.* metrics describe the nation, while factionContribution.* describes only the selected faction's share from that target nation. Advisor placement is a desired repeat-order policy. The projection reads the save's mission-phase cadence, clears active advisors at each phase, and reapplies them at the audited expected order-0 resolution time. Actionable Advise has automatic 100% success and MoveToTarget moves on assignment, so its travel duration is zero rather than distance-based. advisorMissionProjection reports every renewal, the inactive gap, and required Influence; future resource availability, target invalidation, detention, and competing orders remain held fixed.

Projection mechanics are fail closed. Economy, Knowledge, Government, Welfare, Unity, Funding, Mission Control, BuildArmy, and BuildNavy have supported paths; MC and BuildArmy coverage is resolved from the actual execution path. Economy keeps GDP, inequality, and region effects authoritative even when only its independent world-market branch is unavailable. Unity requires a plan-level stochasticPolicy.unityPublicOpinion: "meanPath" opt-in. Its direct cohesion, education, and legitimize branches remain exact when their own inputs are exact, while CP-owner propaganda is a sequential conditional expected transition. BuildNavy converts the DLL-selected Human Standard army to Naval without creating a new army. It preserves identity and location, updates live maintenance and eligibility, and keeps its mean-input market effect independently covered.

Population and Unity both use coverage: expected, provenance: meanPath, and expectationGuarantee: false, but they are not the same approximation. Population reports stochasticTreatment: deterministicMeanInput because each random scalar input is replaced by its mean. Unity reports deterministicExpectedTransition because each integer-sample transition kernel is replaced by its conditional expected flow and then fed sequentially to the next CP owner. Neither is claimed to equal the mathematical expectation across the complete nonlinear stochastic trajectory. metricCoverage is built from the inputs and outputs actually executed, so each treatment reaches only its real descendants. Rule-level placement/branch coverage remains separate from placement-independent aggregate metric coverage.

Unsupported priorities or newly activated blocking dependencies return an incomplete plan and are excluded from comparison/ranking. A completed handler, its cost, and CP fallback/cache repair remain in the authoritative prefix; an unsupported next allocation/effect is never executed. A missing independent Economy or BuildArmy/BuildNavy market value instead leaves nation/faction scopes complete and marks only scopeStatus.worldMarket incomplete. runtimeStop identifies the exact timestamp/day/transaction/phase, trigger, authoritative mutations, unsupported next step, state context, affected metrics, and attempted transaction. lastAuthoritativeState and successful authoritativeFinalState include CP raw and effective pips plus weight caches. nation-ui uses the same tri-state live priority-validity evaluator and reports every CP's serialized/recomputed weight consistency; missing inputs remain valid: null, not silently false. See docs/nation_projection_mechanics_audit.md for the current rule index, coverage resolvers, and validation boundary.

The hab-ui command reconstructs a hab panel from raw sector/module state and module templates, including crew, location-adjusted solar power with active solar-mirror bonuses, monthly net resources, research category bonuses, Earth LEO priority bonuses, construction modifiers, and modules.slots slot accounting. Raw saves can include locked future sector placeholders with empty module slots; these should not be treated as currently available build slots.

The hab-slots command lists faction habs with currently usable empty slots. It defaults to the player faction, excludes habs with zero usable empty slots unless --all is passed, and reports raw, usable, occupied, empty, locked, and locked-empty slot counts for each hab.

The hab-plan command is a save-derived planning view for current and future hab slots. It can scan the player's habs, filter to cores currently upgrading to a target tier, and rank buildable module candidates for balanced, research, projects, category-bonus, or resources focus. research means monthly Research output only; Projects output and tech category bonuses are separate score axes and are not silently converted into research. Its suggestedFill output aggregates a transparent heuristic fill plan by module count and includes projected final power, MC availability, and monthly resource/research deltas. Candidate rows and suggested fills include slot opportunity costs: for each focus, the best affordable candidate's score is treated as the per-slot alternative value, and selected modules are charged for the focus score they give up. If every candidate is non-positive for that focus, the alternative value is zero. Locked placeholder slots are only included in plannedEmpty when the current core module is actively upgrading to a higher tier that will unlock those sectors. Candidate and upgrade rows also report location-adjusted construction materials, build time, and market-value break-even estimates. Location costs include gravity scaling, solar-mirror distance scaling, irradiated-location extra metals, and the two-thirds module-upgrade discount. Helium-3 access substitutes water for eligible fissiles costs. Build time includes hab construction-speed modifiers and any minimum wait for an in-progress core upgrade to complete.

hab-plan is intentionally not a full optimizer yet. It filters out combat and objective-only modules for the economic planning view and should be treated as a shortlist generator before committing construction in-game. Candidate monthly deltas are calculated by comparing the whole hab before and after a hypothetical completed module. For farm-style modules, negative support means reduced existing crew upkeep rather than resource production.

The project-analysis command ranks available and stored faction projects on multiple transparent heuristic axes instead of choosing a final answer. It combines the current research slot model, active resource bottlenecks, direct project effects/resource grants, and hab modules that a project would unlock. Unlocked-module samples pretend the project is complete, scan current/planned empty hab slots, and report 1/2/4-module effects using the best current hab option. Treat those samples as LLM/human decision inputs: they do not solve the global construction queue, reserve power-support modules, or enforce global MC across every hypothetical build.

The ship-plan command builds an LLM-ready ship-design report from the player's finished projects, obsolete-part settings, existing designs, resource state, and packaged ship-component catalog. It reports unlocked hulls and core components, separate drive shortlists for thrust and exhaust velocity, legal power-plant pairings, weapon shortlists, and role-specific utility modules for balanced, combat, intercept, transfer, colony, assault, or science planning. Use --include-obsolete when a hidden legacy component is still useful and --all-components when the full unlocked drive, utility, and weapon lists are needed. Pass --design <name-or-template-fragment> to inspect one saved design without printing the large candidate catalog.

Saved designs include a non-combat ship-builder simulation reconstructed from the packaged catalog. It reports crew; wet, dry, propellant, component, and armor mass; cruise and combat acceleration; delta-v; angular acceleration; power demand; waste heat; radiator mass; battery and heat-sink storage; construction resources with component breakdowns; tier 1/2/3 shipyard build times; MC; and monthly money upkeep. It intentionally excludes combat performance ratings. Drive and weapon shortlist scores remain transparent comparison proxies rather than a transfer or combat simulation.

The nation-claims command distinguishes peaceful, statically hostile, and democracy-conditional hostile claims. It reports the strict comparison target.democracy > claimant.democracy + democracyDecreaseToMakeHostileClaim with values and provenance. Permanence and post-annexation/unification/independence succession remain unknown / not reconstructed unless directly evidenced.

The ai-fleet-diagnostics command inspects supported attack/transport goals, assigned and pending fleets, ships, habs, shipyards, queues, resources, and mission-control evidence for one or all AI factions. It separates observed, derived, suspected, and unknown facts. An empty queue never implies a resource shortage, and stale suspicion is added only when --stale-days is supplied.

Module and location catalogs carry embedded canonical payload fingerprints. Runtime loaders reject altered payloads and duplicate module IDs; provenance timestamps are excluded from the fingerprint. Regenerate older custom catalogs with tools/build_module_catalog.py or tools/build_location_catalog.py before use. These standalone fingerprints are separate from the runtime bundle manifest.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages