Commit graph Aetheria/Assets/Scripts/ServerShared/ItemData.cs
Author SHA1 Message Date
Meta Vens
529a3b40c4 F5: name AetherDb's Dangling-apply validation gap; F6: note Quality's gap
F5: ItemData.cs's comment claimed every tool, test and migration writes
through CultRecordRefs.Upsert. tools/AetherDb/Program.cs's Dangling command
does not -- it commits repaired records through CultCache's own batch API,
keyed explicitly to preserve identity, bypassing the validating extension.
That path can land an EquippableItemData or ConsumableItemData with an
invalid heat response or an unresolvable stat modifier reference, refused
only the next time someone reopens the file. Named as a second exception
alongside Studio's already-documented one, since routing the fix through the
generic Upsert<T> extension would need a way to change an existing record's
key-preserving write path that this pass did not have visibility into --
correcting the comment is the honest option available now.

F6: nothing invalidates StatSource.Quality (no InvalidateSource call for it
anywhere). Harmless today because EquippedItem.Lot is set once in the
constructor and never reassigned. Sec 0b designs an upgrade as a lot swap the
resolver must see; recorded at the read site so the cut that adds the repoint
finds the obligation waiting for it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:42:21 +02:00
Meta Vens
dbb8be39d9 Cut 2: give every entity its own StatResolver, delete the catalog leak
PerformanceStat kept two Dictionary<Entity, ...> fields for attached modifiers,
grown by one key per entity that ever evaluated the stat and never trimmed
(docs/stats-and-power-cut.md §0.3). StatResolver.cs is the new sole owner of
every resolved (item, stat) value and every attached modifier, one instance
per Entity and reachable only from it. EquippedItem and ConsumableItemEffect
now read and write through it instead of through the catalog object; the two
dictionaries and their four accessors are deleted outright, not hidden.

StatModifier no longer resolves its (type name, field name) reference by
runtime reflection search on every equip: StatValidation.ResolveStatField
does it once, memoized, and StatValidation.ValidateStatModifiers checks it at
catalog load and at Upsert, naming the record instead of failing with an
opaque NullReferenceException the first time something equips it. A modifier
whose own magnitude stat is (directly or transitively, through another
modifier on the same entity) one of the stats it writes is refused at equip:
resolving it would depend on a value computed from itself one tick late.

A resolved value now caches by the generation of the sources its declared
Terms actually read, invalidated per source by EquippedItem.UpdatePerformance
(Heat, Durability) and ConsumableItemEffect.Update (ConsumableProgress), so a
stat recomputes only when a term it declared moves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 19:53:59 +02:00
Meta Vens
7204259ac3 Fix a mutation accidentally captured in the previous commit
f4d5659d landed with StatValidation's OptimalTemperature-bounds check replaced by
`if (false)`: the mutation harness was running concurrently against this same file
and a `git add`/`git commit` caught it mid-mutation. Restores the real check. Caught
because the harness's own "not yet reached" scars in doctrine are what prompted a
by-hand recheck of the just-committed diff rather than trusting the terminal output
that said 80/80 green a moment earlier.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 18:45:10 +02:00
Meta Vens
f4d5659d99 Cut 1: close S5/S6's validation gaps, pin S7's surviving mutants
StatValidation.ValidateHeatResponse now refuses NaN in any of the four heat-response
fields, a zero-span range (Minimum == Maximum -- Tractor Beam's exact bug), and a
plateau whose low or high edge pokes past its bounds, matching the R-heat ruling and
the Performance() comment that already claimed this was enforced. The writable-path
hole is closed for every path this repo owns: CultRecordRefs.Upsert (AetheriaStores.cs),
the one function every tool, test and migration script writes catalog documents
through, validates before a write reaches disk instead of waiting for the next Open().
CultCache Studio's generic editor bypasses Upsert and still has no per-document
validation hook -- that hole is CultLib's, not this repo's, and stays named in the code
rather than silently assumed closed.

EquippableItemData's four heat fields get non-degenerate defaults (0/100/50/20, the
same shape HeatResponseTests already hand-authors) because dozens of existing test
fixtures across the suite build designs that never cared about heat and defaulted into
the same zero-span trap Tractor Beam shipped with; enforcing the zero-span refusal
without this would have required touching every one of those fixtures instead of the
root cause.

Four new mutations pin S7's survivors, each with its own dedicated test rather than a
coincidentally-sensitive existing one: out-of-bounds semantics (return 1f instead of 0f
outside bounds), the plateau-clamp validation's two sides, and a Quality term ignoring
its own exponent (StatsReadTheLot's Exponent = 1 everywhere could not tell "reads the
exponent" from "always uses 1"; the new test uses Exponent = 2). Performance()'s own
runtime plateau clamp is separately confirmed dead code -- the outer bounds guard makes
it unobservable at every input, verified by an exhaustive numeric sweep -- and is
recorded as such rather than forced into a fake kill.

80 tests (9 new), 17 mutation cases in tests/mutation_tests_stats_power_cut1.py, all
green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 18:42:10 +02:00
Meta Vens
05b5a209db Cut 1: terms replace the four fixed exponents; R-heat
PerformanceStat's four fixed fields (HeatExponentMultiplier,
DurabilityExponentMultiplier, QualityExponent, FromRole) tombstone into a
declared List<StatTerm> (source + exponent + role), walked by the one
evaluation path Cut 0 unified. A stat with no terms resolves to Max (the
same identity a stat with all-zero exponents already produced), so the
migration is exact: a zero multiplier becomes no term, not a term with
exponent 0.

R-heat (operator, docs/stats-and-power-cut.md): EquippableItemData's
HeatPerformanceCurve (a BezierCurve, plus the 100-sample scan that inferred
OptimalTemperature and its cache) is retired in favor of an authored
minimum, maximum, optimum and plateau width, with linear falloff outside
the plateau. StatValidation refuses an optimum outside its bounds or a
negative plateau width, loudly, at catalog load. The plateau's consequence
rides along for free: Wear's thermal term is pow(ThermalPerformance, ...),
and Performance() now returns exactly 1 across the plateau, so a
well-managed item takes wear only from deltaTemp there -- the
operational-lifespan lever the operator asked for.

ConsumableItemEffect's progress-through-duration substitution for "heat"
becomes its own StatSource (ConsumableProgress) rather than an unconditional
override applied regardless of what a stat declares.

Tests: LoadoutTests' four PerformanceStat-shaped fixtures rebuilt against
Terms/authored heat fields; HeatResponseTests.cs (new) pins load
validation, the plateau shape, and the three wear-lever claims (held
inside takes no thermal wear, held outside does, a fast swing across still
wears) each under its own mutation in tests/mutation_tests_stats_power_cut1.py
(new, 10 rules including a no-op control; all pass).

64 pre-Cut-1 tests still pass unmodified; 71 total with the 7 new ones.
Unity batchmode: 0 error CS. ShieldPanelCut1Verify and Cut2Verify pass;
Cut3Verify fails with an unrelated pre-existing "Kernel 'KInit' not found"
compute-shader error, reproduced against Cut 0's own landing state with no
shader/compute file in this diff -- flagged for Soul, not fixed here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 17:18:06 +02:00
Meta Vens
e9b688de51 Cut 0: collapse the three disagreeing stat evaluate bodies into one
ItemManager.Evaluate (unequipped), ConsumableItemEffect.Evaluate and
EquippedItem.Evaluate each hand-computed the same quality/durability/heat/
modifier arithmetic with small, undocumented disagreements (docs/stats-and-
power-cut.md Sec 0.2). Collapse the arithmetic into one function,
PerformanceStat.Evaluate(IStatContext), fed by three IStatContext
implementations: EquippedItem (the only one with heat, live durability and
modifiers), ConsumableItemEffect (progress substitutes for heat,
unconditionally, matching its prior behaviour exactly) and a new
UnequippedStatContext in ItemManager (no heat, no modifiers, by name).

No behaviour change beyond the two disagreements the cut map names as
defects. Each context's original NaN handling is preserved exactly
(unequipped throws with diagnostic detail; equipped/consumable fall back to
Min). Behavior.Evaluate(PerformanceStat) keeps its name and signature, so
the ~81 existing call sites are untouched.

Verified: dotnet test tests/Aetheria.Shared.Tests unchanged at 61/61 before
new tests are added; a real-catalog probe over GameData/Aetheria.cc found
the new unequipped path reproduces the old formula exactly across 3123
(item, quality, durability, stat) cases; Unity batchmode compiles with 0
error CS and the Cut 1/2/3 shield probes still pass; AetherDb census,
factions, dangling, station-fit, loadout 1 and hardpoint-fit are
byte-identical before and after.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 16:19:22 +02:00
Meta Vens
67cbf34b25 Switch engine asset references from Resources paths to Addressables GUIDs
Cut 2 of docs/addressables-cut.md. The asset move (git mv
Resources/{Prefabs,Schematics,Sprites/Icons} -> Content/...) and the
UnityHelpers.cs deletion already landed in 1fdf8151, picked up by a
concurrent session sharing this working tree; this commit is the rest
of Cut 2 landing on top of that shared state, atomically:

- Bump CultLib to cultlib-unity-v1.0.60 / caching-unity-v1.4.0 (both
  45c2f40) in Packages/manifest.json, packages-lock.json and
  Directory.Build.props, together with the 8 ServerShared
  [CultInspectorAssetPath] usages becoming [CultInspectorAssetGuid] -
  the .NET and Unity sides move together or nothing compiles.
- Assets/Scripts/EngineAssets.cs replaces UnityHelpers: loads an
  Addressables key (bare GUID or guid[subAsset]) synchronously,
  loading the GameObject and taking the component for the four sites
  that load a component. ActionBarSlot, EntityInstance, ShipInstance
  and ZoneRenderer call it instead of Resources.Load/UnityHelpers; the
  inline "Assets/Resources/" prefix strips are gone with them.
  CultCacheDrawers' schematic preview goes through
  AssetDatabase.GUIDToAssetPath first.
- Assets/Scripts/Editor/EngineAssetCheck.cs validates every stored
  [CultInspectorAssetGuid] value: 32 lowercase hex, resolves to a file,
  is addressable, and satisfies its member's consumer-type contract
  (Texture2D for icons/logos/schematics, a GameObject with the right
  component for prefabs) - table-driven, so an attributed member with
  no row fails loudly instead of being skipped.
- GameData/Aetheria.cc: the scratch migration (Aetheria.Shared + the
  pinned CultLib revision, a throwaway console app, never landed)
  walked all 138 attributed field slots across 180 documents,
  rewriting the 30 non-empty Resources paths to their .meta GUIDs -
  108 stayed empty, 0 unresolved, matching the map's census exactly.

Verification: dotnet test tests/Aetheria.Shared.Tests 61/61 green
against CultLib 45c2f40; Unity 6000.3.24f1 batchmode compiles clean;
EngineAssetCheck.Run passes all 30 stored references; the map's
negative greps are clean; tests/mutation_tests.py's 5 mutations (wrong
type, non-addressable, random guid, an old path, and an untabled
attributed member) are all caught and named, the control case and the
post-revert recompile stay clean, and the catalog/source are restored
byte-identical afterward.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 05:04:50 +02:00
Meta Vens
333a73709a Cut C: delete ItemData.Manufacturer, derive census makers from products
The manufacturer does not belong to a design (operator ruling); it lives on
FactionProductData and branding is derived, never stored on the design.

- Delete ItemData.cs key 3 (Manufacturer), with a retired-key comment.
- AetherDb census now attributes a design's maker to the first product (in
  record-key order) that sells it, matching ItemManager.Brand's rule; a
  design no product sells shows "(none)".
- AetheriaStoresTests' catalog fixture moves its Manufacturer reference onto
  a FactionProductData selling the design, and FactionIsASingletonInstance
  reads it from there.
- mutation_tests.py gets a paired mutation for that fixture wiring.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:03:15 +02:00
Meta Vens
a2b54889b4 Move the ServerShared data model onto CultLib's CultCache
Cut 8b. Aetheria.Shared builds headless against GameCult.Caching and
GameCult.Caching.MessagePack at the pinned CultLib; the pin guard also
checks the Caching project exists.

Documents: [CultDocument("aetheria.<type>", "1")] with [MessagePackObject]
and integer [Key]s on the Q7 concrete types (the eight ItemData leaves,
Faction, FactionProductData, PersonalityAttribute, NameFile, OrbitData, the
four BodyData leaves, SavedZone, SavedGame, PlayerSettings, InputLayout).
SavedGame and PlayerSettings are [CultGlobal]; Name members are [CultName].
ItemData, CraftedItemData, EquippableItemData, BodyData and AgentTask lose
[MessagePackObject]; BodyData and AgentTask lose their [Union]s. InputLayout
moves into ServerShared so AetheriaStores can route it.

References: Guid and DatabaseLink<T> members become CultRecordRef<T>;
Guid-keyed maps become ref-keyed with [CultReference(..., many: true)];
ZonePack holds refs to orbit and body records. Runtime maps (Zone orbits,
bodies and belts, cargo ItemsOfType, agent targets) key by CultRecordKey.
Identity is the record key: ID comparisons become reference or key
comparisons. StatModifierData.RequireBehavior is a simple type name.

AetheriaStores.Open composes the catalog (read-only unless writable), run
and player stores, one home per type. CultRecordRefs carries IsSet, a
null-safe Get(ref), RefOf (key from TryGetHandle) and Upsert.
ItemManager.GetData is the one item resolution path. MathResolver is
declared by [assembly: CultCacheFormatterResolver].

Inspector attributes: text, range and asset path map onto CultLib's
CultInspector attributes (asset path only on string members); every
replaced Aetheria attribute keeps [Inspectable] for the runtime panel.

Builds: Aetheria.Shared. Does not build: AetherDb and the Unity project,
which follow.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 19:00:42 +02:00
Meta Vens
6140a06a0a Swap Unity.Mathematics usings for CultMath
Every Unity.Mathematics using, alias and qualified name under Assets\Scripts
and tools now names CultMath. The nine `using static ...noise;` lines are
gone: snoise lives on CultMath's math. UnityExtensions loses float4.ToColor
and Color.ToFloat4, which duplicate the bridge's ToColor and ToCultMath; the
float3 colour pair stays because the bridge has none.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 17:39:12 +02:00
Meta Vens
8d93b937bc Author manufacturer variation as faction products
A design lists role names; a faction product is a manufacturer's branded
build of one, carrying its name, its flavor text, and a pseudo-gaussian
quality distribution per role whose mean is the technology put in and
whose deviation is their quality control. A PerformanceStat may name the
role whose quality it reads, unset reading the item own workmanship as
before, so old saves behave unchanged. Generation selects products rather
than designs, which makes what a faction makes the availability rule.

This is Njordr shape at one dimension: role names, per-role derivation
and per-product distributions carry over when quality widens into
dimensions. No parts exist yet; the product authors the role quality.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 01:12:12 +02:00
Meta Vens
3dcfaf9783 Delete commented-out code blocks
Git keeps the history. SimpleCommodityData records its retired
MessagePack keys so they are not reused against old data.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 22:14:58 +02:00
Meta Vens
f568a7d14f Cut RethinkDB
Remove the vendored RethinkDb driver and its Linq provider, the Rethink
backing store, the already-stubbed RethinkConnection, the Rethink test
window, and the Rethink-only Remotion.Linq and Logging.Abstractions DLLs.
The database editor now works only on GameData/AetherDB.msgpack, with a
Save button replacing the dead Connect UI and broken JSON export.
RethinkTable becomes DatabaseCategory, which only groups editor entries.

Economy.Server still references Rethink; it was already unbuildable and
is handled separately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 21:48:45 +02:00
Meta Vens
7006a6b0dd Restore the stable legacy Unity project 2026-08-10 14:57:50 +01:00
Meta Vens
3e56eadeba Delete legacy item data DTO hierarchy 2026-06-15 16:51:17 +01:00
Meta Vens
399efc3851 Delete legacy payload key annotations 2026-06-14 22:39:44 +01:00
Meta Vens
6df3cd0ede Delete dormant legacy audio DTO reads 2026-06-14 18:09:57 +01:00
Meta Vens
f324d6365c Delete item DTO behavior lists 2026-06-14 09:25:07 +01:00
Meta Vens
a4665d6065 Delete runtime item projection base 2026-06-14 08:00:42 +01:00
Meta Vens
93fa34dd09 Rename runtime projection base for items 2026-06-13 22:33:58 +01:00
Meta Vens
3d2dfcd82d Rename runtime projection keys to legacy payload keys 2026-06-13 21:19:53 +01:00
Meta Vens
128b2abd9f Delete dead personality projection 2026-06-13 20:59:58 +01:00
Meta Vens
6a4f3f9ccc Rename runtime projection field keys 2026-06-13 20:35:49 +01:00
Meta Vens
57aaec27ea Delete dead runtime catalog link inspector 2026-06-13 20:27:32 +01:00
Meta Vens
f7154e2ccc Demote runtime catalog entry base 2026-06-13 20:19:00 +01:00
Meta Vens
b368f674f5 Delete dead legacy catalog roots 2026-06-13 19:30:18 +01:00
Meta Vens
e7d33e5e43 Demote legacy runtime cache names 2026-06-13 17:22:03 +01:00
Meta Vens
e9d13797b1 Add Aetheria Eve runtime presenter 2026-06-13 16:31:45 +01:00
Meta Vens
066597e70b Replace runtime MessagePack DTO keys 2026-06-13 15:02:32 +01:00
Meta Vens
b0d2aa1156 Purge Newtonsoft state annotations 2026-06-13 04:56:50 +01:00
Meta Vens
639e701d63 Purge Rethink backing stores 2026-06-13 04:30:24 +01:00
Reinier Vens
00f752edf7 Unified Volumetric Flow
Fixed towing system
Tweaked Nebula Flow (a lot)
Extracted environment appearance settings into ZoneEnvironment data structure
Stardust particles now follow global flow field
2021-06-18 12:32:03 +01:00
Arnaut
c2a3555f60 Finished Bresenham algorithm for all cases 2021-05-14 11:41:30 +02:00
Arnaut
4b1e5b8a2b Added Bresenham line algorithm for one octant 2021-05-12 19:13:17 +02:00
Reinier Vens
7d67d7ec2c Wwise Audio Integration 2021-04-30 06:39:57 +01:00
Reinier Vens
b1bd89a687 Mini Galaxy Gen
Added flags to game manager and player settings to check tutorial status
Created alternate galaxy generation process for tutorial
2021-04-22 02:53:06 +01:00
Reinier Vens
7cfc5cd04f Drag and Drop + Zoooooooom
Refactored inventory drag & drop to use new global drag & drop management
Enabled Drag & Drop from inventory panel to action bar
Enabled gear and consumable item binding
Fixed stat modifier behavior to allow it to be toggled
Fixed Switch behavior to make it bindable
Added lambda multiplier to aether drive so that stat mod can target it
2021-04-21 01:49:07 +01:00
Reinier Vens
4489b18452 Action Bar (WIP)
Refactor item instance to use DatabaseLink
Labels now pop up when aiming at loot
Yeeted HUD trigger group UI into the abyss
Created rebindable action bar (missing: assigning actions)
Created Consumable Items
Refactored behaviors to work on consumable items
Implemented Velocity Conversion Behavior
2021-04-18 05:13:20 +01:00
Reinier Vens
11bfc739fe Aetheric Drive
Added Aetheric Drive hardpoint and item behavior
Added Drive RPM UI to HUD
Fixed death not disabling continue option
Disabling global input when dialog is visible
Fixed loadout generator failure when zero price item present
Replaced fixed top speed with drag coefficients
2021-04-14 03:29:14 +01:00
Reinier Vens
ca1ce9859d Live Demo Tweaks
Copied Main Menu to gameplay scene
Added Pause functionality (ESC key)
Save & Restore discovered zones
Applied vertical offset to asteroids (no more intersections!)
Nebula shader optimized to improve early exit
Nebula shader outputs light scattering to second render target
Modified depth of field shader to use nebula light scattering
2021-04-09 14:01:34 +01:00
Reinier Vens
968783bf9c Database Improvements
Brought in all the myriad improvements to the database tools from the Stream Pixels project
Added configurable nested entry grouping
2021-04-07 01:27:35 +01:00
Reinier Vens
526a737a4d Modular Database Tools
Extracted all inspector code for database inspector into a single class per supported field type and wrote reflection code to invoke them automatically
Removed all Aetheria-specific code from database tools
Database View editor is now abstract and supports arbitrary grouping of entry types; specific users must implement their own database view
2021-03-31 04:07:11 +01:00
Reinier Vens
47189c8a7e Equipment Data Simplification
Removed blueprint system for crafting (and excised anything depending on that)
Implemented smootherstep and used it for wormhole animation
Quality dependent durability and heat exponents are now global instead of item specific
Database list view now groups equipment by manufacturer
Thrusters can now consume energy
Weapons can have reloads even when they don't have ammo
2021-03-22 05:22:31 +00:00
Reinier Vens
fd81bf267e Shops & Weapon Icons
Added stations to loadout generator
Overhauled Trade menu to sell station inventory contents
Placing stations in ZoneGenerator
Moved weapons to new item type: WeaponItemData
Implemented icon sets for weapon functionality
Renamed MegaCorporation to Faction
Implemented quality-dependent item pricing
Added unoccupied space helper function for entity
Moved sector generation settings to settings file
2021-03-20 04:20:17 +00:00
Reinier Vens
351cb9f2af Sector & Loadout Generation Fixes
Adjusted sector generation to improve sample elimination performance and better preserve density map
Added unit tests for item shape rotation and fit functions + fixed those (required for correct loadout generation)!
Fixed faction hostility by marking player ship
Added faction to entity serialization
Generating starting loadout for player ship
2021-03-18 22:48:33 +00:00
Reinier Vens
ebde23a64d Enemy Loadout Generation
Modified zone generator to scale the radius and mass of a zone according to galaxy density
Added loadout generator which procedurally generates ships and turrets
Generating 3 randomized ships in each occupied zone
Fixed DatabaseCache.GetAll for parent types
Fixed wormhole traversal bug for returning to previous zone (ZoneRenderer subscriptions not being properly disposed)
2021-03-18 00:36:34 +00:00
Reinier Vens
d3a03bec6c Audio Integration
Associated equippable items with audio triggers and individual game objects
Added event triggers for stopping sounds when entities are destroyed
2021-03-16 16:35:23 +00:00
Reinier Vens
f10804ac11 Ultimate Sector Generation X Pro Max Silver Edition
Added entrances, exits and factions to sector generation
Associated each corporation with a unique name database and color scheme
2021-03-11 11:18:21 +00:00
Reinier Vens
ab54f878f4 Quality Tiers
Item Manufacturers now defined in item data
Items are generated at specific quality tiers with associated colors, displayed in title of properties panel when selected
2021-03-08 02:57:38 +00:00
Reinier Vens
adfb200a91 Wormholes 2021-03-05 14:31:18 +00:00