ShieldPanelCut3Verify.cs stands in for NUnit coverage the same way Cut 1 and
Cut 2's probes do (Tests.asmdef cannot see Assembly-CSharp). It builds an
envelope/prototype/interceptor rig purely in code and steps ShieldPanel's
private Update() by reflection, since Cut 1 removed [ExecuteAlways] and
Update() otherwise never runs in edit mode. It needs GPU access, so unlike
Cut 1/2's probes it runs without -nographics.
Checks: same-frame injection (D17), the gate staying open on the following
frame (D20), reuse striking the existing panel and eroding its minimum temper,
pool exhaustion holding the cap with no allocation once full, null-guarded
Absorb, no rebuild across a pool return/reuse cycle (driven directly via
OnEnable/OnDisable reflection, since Object.Instantiate's OnEnable is not
synchronous in every context this runs in), and the D21 Penrose/Hex density
ratio at radius 1.5/3/5/10.
mutation_tests_shield_panel_cut3.py mutates each rule Cut 3 establishes back
to its pre-fix or pre-rule shape and asserts the probe goes red naming it,
plus a no-op control. Kept separate from _cut1.py/_cut2.py (each owns its own
cut's rules) and from mutation_tests.py (the item-provenance cut's headless
dotnet runner, no path to a Unity batchmode check).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ShieldManager's fallback (no ShieldEnvelope yet, e.g. every ship prefab
before the operator hand-rigs it per Q5) hard-failed to a fixed
Vector3.forward direction with a per-hit Debug.LogError. That silently
changed behaviour for every ship in the game until the operator edits
Longinus.prefab/Djinni.prefab on their own schedule -- worse than either
the deleted code or a loud one-time failure.
Extract ShieldEnvelope's local-direction primitive into two static,
no-component-required entry points -- SurfaceDirection(Transform, Vector3)
and LegacyLocalSurfacePoint(Transform, Vector3) -- so both FieldDriver's and
ShieldManager's fallbacks go through one owner instead of each re-deriving
the pre-Cut-2 formula by hand. ShieldManager's fallback now reproduces the
deleted normalize(shield.transform.InverseTransformPoint(point)) formula
exactly via the shared static, logging once (a warning, not a per-hit
error). FieldDriver's fallback is rewired onto the same static rather than
its own inline copy of the maths.
Documented, not silently assumed: FieldDriver's "envelope present" branch
(envelope.ProjectToSurface, world-space) and its fallback (the legacy local-
space formula) are only numerically identical when the carrier's transform
has zero position and identity rotation -- true of the one FieldDriver
carrier in the tree today, not true in general. This is a characteristic of
Cut 2 as scoped by the map (FieldDriver.cs:125 reads envelope.ProjectToSurface
directly, per the map's own text), not something this fix introduces or
resolves; flagged so nobody assumes the two branches are interchangeable for
a future non-origin, non-identity FieldDriver carrier.
ShieldPanelCut2Verify.CheckLegacyFallbackFormulas pins both static entry
points against an independent re-derivation of the exact pre-Cut-2 formulas,
on a carrier with a non-trivial transform (nonzero position, non-identity
rotation) so the check isn't vacuous. mutation_tests_shield_panel_cut2.py
gained two cases: SurfaceDirection collapsing back to a fixed Vector3.forward
(the exact regression fixed here), and LegacyLocalSurfacePoint collapsing to
the raw, untransformed world point -- both correctly fail the probe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
FieldDriver derived the shield ellipsoid from its own transform.localScale;
ShieldManager derived it independently from the Shield prefab instance's
transform, doing the same normalise-and-project by hand against a different
object. Add ShieldEnvelope as the one reader of a transform's centre, radii,
surface projection, and true outward normal (derived, not authored, per R6 --
no second copy of numbers the physical MeshCollider already owns), and switch
both consumers onto it, deleting their hand-rolled projections.
Radii read the attached collider mesh's own bounds.extents per axis rather
than assuming a flat 0.5 or 1.0: Shield.prefab's Icosphere collider measures
(0.0095106, 0.01, 0.01), not a uniform round number, and the cubesphere's
collider measures exactly (1,1,1) -- confirmed by a throwaway batchmode probe
against the actual mesh assets, not guessed.
SurfaceNormal is not normalize(p): a non-uniform ellipsoid's true normal is
the gradient of the implicit surface, transformed by rotation and the INVERSE
of lossyScale (a normal is a covector). The first implementation used
TransformDirection (rotation and forward scale) and the batchmode probe's
finite-difference gradient check caught it immediately -- exactly the
plausible-looking-wrong-answer failure mode the cut map called out by name.
Both original consumers keep normalize(p)-equivalent behaviour via the new
SurfaceDirection method, since they only ever wanted a direction.
FieldDriver falls back to its pre-cut formulas (logged once) when no
ShieldEnvelope is present, since it has no guaranteed carrier yet.
ShieldManager does not: every object that carries it gets an envelope in this
cut, so a missing one logs an error and degrades to a fixed direction rather
than recomputing a second projection.
No prefab or scene file is touched here (Q5: the operator rigs prefabs and
scenes by hand); ShieldPanelCut2Verify's batchmode probe instead builds
synthetic transforms carrying Longinus's and Djinni's actual override values
plus the real Icosphere mesh, and proves ProjectToSurface lands exactly on the
ellipsoid and SurfaceNormal matches a finite-difference gradient to 1e-3.
mutation_tests_shield_panel_cut2.py mutates SurfaceNormal three ways (back to
normalize(p), back to TransformDirection, and a flattened 0.5 extents factor)
and confirms the probe goes red for each, naming the reason.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Companion to a935b965: the actual verification tooling for the shield-panel
Cut 1 landing, split into its own commit since it's infrastructure rather
than the ported sources.
.gitignore: ignore tests/_scratch_* (the mutation harness's throwaway log
directory) alongside the existing scratch-* patterns.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
The port dropped the legacy drawer's FlexibleSpace, so the grid's group
stretched to the inspector width and the texture was fitted there instead.
Checked by the operator in Studio on LonginusX.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
On Studio 1.3.1, drawers are handed the owning record read-only as
CultInspector.Record. InspectableSchematicShapeDrawer reads the item from it
and restores what the Database Tools drawer did (d3db1730,
AetheriaInspectors.cs ShapeSchematicInspector):
- the item's schematic texture drawn under the toggle grid;
- the height derived from the texture's aspect when a texture exists;
- hull hardpoint cells tinted with HardpointData.TintColor.
The drawer never writes to the record. The comment saying these waited on
the Studio exposing the open record is gone.
Verified by the Unity batchmode compile (no error CS). The visual check is
in the operator's Studio click-through.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cut 8b. The Unity project compiles with 0 errors in 6000.3.24f1 batchmode.
Packages: manifest.json pins org.gamecult.cultlib at cultlib-unity-v1.0.57
and org.gamecult.caching.unity at caching-unity-v1.2.0, next to the 8a
CultMath tag. Aetheria.Shared.Unity references GameCult.CultLib and keeps
noEngineReferences.
The Database Tools (Assets/Scripts/CultCache/Editor) are deleted in this
commit, alongside their five ported drawers in
Assets/Scripts/Editor/CultCacheDrawers.cs, each an
[CultInspectorDrawer] ICultInspectorDrawer:
- InspectableType: popup of the attribute type's [Union] member names,
writing the string.
- InspectableColor: float3 and float4 through ColorField.
- InspectableAnimationCurve: float4[] and BezierCurve through CurveField.
- InspectableTemperature: Kelvin, Celsius and Fahrenheit fields over one
value.
- InspectableSchematicShape: size and cell toggles. The old drawer also
drew the item's schematic texture and tinted hull hardpoints, which need
the parent document. The tagged Studio hands a drawer only the value, so
those wait on the Studio exposing the open record.
Unity call sites:
- ActionGameManager opens the catalog through AetheriaStores; Cut 10 adds
the run and player stores.
- Refs resolve through ItemManager.GetData or Get(ref); orbit, planet and
belt maps key by CultRecordKey; identity is compared by reference or key.
- The PlayerSettings.msgpack reader and writer, which Cut 10 deletes, pass
CultDocumentMessagePackSerialization.OptionsFor, since the embedded run
reaches CultMath values and refs. Keyboard layouts need no resolver and
keep MessagePack's defaults until Cut 10.
- The input map uses the nested action to binding shape.
- PropertiesPanel reads CultInspectorRangeAttribute.
- NameTools loses its legacy name-file writer.
- Slime compares serialized settings instead of the deleted SHA1 helper.
- FieldDriver drops InspectorHeader.
- .gitignore covers the test project's build output.
Builds: Aetheria.Shared, AetherDb, Aetheria.Shared.Tests (6/6), Unity
batchmode (0 errors).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Delete Economy.Server/Economy.Shared, LiteNetLib, network message types,
the texture-based Gravity duplicate, unreferenced scripts and agent
states, and unused plugins (MSAGL, NaughtyAttributes, AsyncAwaitUtil,
Allegorithmic, Localization samples, MrtTest, ThinkGear, QuickGraph),
plus vendored sample scenes, root zips/logs, and the stray Obsidian
folder. MainMenu logs faulted galaxy-generation tasks directly instead of
AsyncAwaitUtil's WrapErrors. Stop tracking UserSettings and the Wwise
.backup folder; ignore generated .sln/.csproj by pattern.
Game-system test scenes are kept. Playdead stays: VolumeCloudRenderer
derives from its EffectBase.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Removed hard zone boundaries
Fixed stuff that broke because of hard zone boundary assumption (stardust placement, vertical fog)
Added a skybox!
Removed density-based albedo boost (_TintExponent) to improve perceptual uniformity at different step sizes, reconfigured shader to achieve / surpass previous looks and performance
Cell Brush has a material editor now to enable variant selection
Enabled Caching Shader Preprocessor
Moved raymarching loop into CloudShader
Get environment settings from game manager to enable configuration / variation
Introduced slope-based nebulae damping and volumetric flow
Hid optional volumetric features behind preprocessor branches
Created shader variants selected by global keywords for all shaders depending on volumetrics
Environment settings used to configure shader variant selection
Moved dynamic lighting settings to own subclass
Dynamically adjust gravity map isoline contour depth range according to zone contents
Selecting a weapon now displays weapon group toggles
Added global drag and drop handling in game manager
Weapon group toggles can be dragged to action bar to bind them
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
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
DatabaseCache now reads and stores entry types marked ExternalEntry from separate files in their own folder
Updated name file cleaning code and re-cleaned name files
Disabled planet generation (very slow)
Fixed wormhole traversal - can now explore galaxy
Added faction allegiance matrix and slider inspector code
Added sector map in Galaxy tab of in-game menu
Added player flag to Ship (replaces AGM.PlayerEntities)
Refactored sector map to depend on AGM
Moved sector generation to main menu
Main menu now supports resuming previous playthrough
Database and player settings now statically available via AGM
AGM saves current game state in PlayerSettings on exit
Sector generation is now asynchronous
Added progress callbacks to sector gen + progress dialog in menu
Confirmation Dialog / properties panel can now display dynamic text entry
Added zone title to Zone map
Eliminated ZoneData class (properties moved to ZonePack)
Sector, Zone and Entity serialization now fully functional
Entity settings now separate from player settings
Cleaned up old unused networking message classes
Name files now integrated with database cache
Added ability to save/load additive DB cache files in database panel
Cleaned up Wwise sound setup - removed redundant items & fixed spelling errors
Deleted Wwise cache + added to .gitignore
Generating links between zones within the sector using elimination algorithm with connectedness testing
Improved sample elimination API - now accepts simple density function!
Ported MIConvexHull library to single precision, Unity.Mathematics math
Removed old galaxy generator (new code is much better!)
Fixed Laser cancelling bug
Fixed Turrets not activating
Added ability to bind player perspective to orbital entities
Added Markov Chain name generator + Australian place name dataset
Modified old "galaxy" shader to serve as sector background
Implemented Cem Yuksel's Weighted Sample Elimination for Poisson Disk Sample Sets
Created sector generator which places sectors using WSE
Added heat variation option for Performance Stats
Ability to toggle radiators on/off using H key
Item durability loss (Wear) is now heat dependent and incurred only when used
Restricted equip/unequip to docked (inactive) entities
Fixed race condition causing exceptions in database sync code
New damage system, much easier to understand
Splash damage support
Hardpoint armor consolidated with hull armor
Minimap shows view cone
New industry standard palette for temperature display
Temperature range display contains palette
Restoring loadouts now ignores temperature and armor
Items can ignore thermal mass when adding heat
Burst weapons can consume single ammo (mainly shotguns)
New missile type that follows crosshairs
New airburst projectile type that deals splash damage
Auto Shotgun and Charged Shotgun
Weapons are now monolithic behaviors
Various new weapon behavior types implemented
All weapons have optional magazine and reload mechanic
Visibility now decays globally
Added MPL license headers
SectorRenderer renders entities in sector, manages particle systems for ship thrusters
Thrusters apply torque based on orientation and position relative to ship center of mass
GameManager controls the player ship's thrusters
Player can dock with station if they are near
Entities now have dedicated docking bays with their own cargo area for loading/unloading
Inventory panel allows display of any ship or cargo bay at the currently docked station or within the current ship if undocked
Improved inventory grid layout system by creating a single spritesheet with all 256 possible combinations of cell adjacency, and modified the inventory script to index individual sprites using adjacency
Aetheria Database Tools now has the ability to customize the shapes of items and hardpoints, and displays hardpoints when editing hull shape
List elements now have foldouts
Lists are presented in the Database Inspector with colors when the list type implements ITintInspector interface
Removed universal GameContext references
Refactored GameContext: It's now only responsible for item management. As such it's now called ItemManager
GlobalData is gone, relevant settings are distributed amongst specialized settings classes
Entities are no longer database entries, references to them are now direct - Zone is reponsible for storing them in ZonePacks
Controller subtypes are now generic classes, class argument is task type
Inventory is now a 2D grid instead of a list
Entity temperature is now a 2D grid instead of a number
Item sizes are now arbitrary shapes instead of a number
Hardpoints are now arbitrary shapes instead
Equipped items have their own temperatures
Map view now displays sunlight colors
Integrated Allegorithmic Substance Plugin
Imported Djinni ship and assigned Substance materials
Removed Node Editor framework (might come back later but needs work to integrate with behavior system)
Made it possible to turn new hulls into drones which can then be outfitted and activated for service
Missing blueprint ingredients no longer crash the game and gracefully log what's broken
Loadout cargo is now stored entirely separate from gear
Entities such as colonies and ships can now be clicked on to reveal their properties or context menus
Orbital Colony loadout now has a new item (thermostatic heater) which itself has a new behavior type (Thermotoggle) allowing it to regulate its temperature for more agreeable living conditions
Fixed stat modifiers for hull stats (e.g. Hull Expansion)
Widened property label in DB inspector
Entity rendering now fully supports dynamic entities from game context
Entity children now displayed underneath icon
GameContext can spawn entities by loadout
Selected corporation's initial fleet is spawned in parent corp's home sector
Properties panel API is now unified with context menu API
Properties panel labels now update dynamically