Build ServerShared without Unity and add AetherDb scripts
Aetheria.Shared.csproj compiles ServerShared with MessagePack, UniRx core, Ink and Unity.Mathematics from source against .NET Standard 2.1 (Unity's API level) with no Unity defines; a clean build checks that the simulation stays engine-independent. tools/AetherDb opens AetherDB.msgpack through the game's own CultCache for file-based C# scripts; station-fit checks every station hull can take a docking bay. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
25ecb46fcd
commit
02058a3cdf
6 changed files with 126 additions and 3 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -58,6 +58,12 @@ ExportedObj/
|
|||
# Per-user editor state
|
||||
/[Uu]ser[Ss]ettings/
|
||||
|
||||
# .NET build output outside Unity
|
||||
/Aetheria.Shared/bin/
|
||||
/Aetheria.Shared/obj/
|
||||
/tools/**/bin/
|
||||
/tools/**/obj/
|
||||
|
||||
# Unity3D generated meta files
|
||||
*.pidb.meta
|
||||
*.pdb.meta
|
||||
|
|
|
|||
35
Aetheria.Shared/Aetheria.Shared.csproj
Normal file
35
Aetheria.Shared/Aetheria.Shared.csproj
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- The game simulation built without Unity: the headless counterpart of the Aetheria.Shared.Unity assembly.
|
||||
Compiles ServerShared and its dependencies from source with no Unity defines, so a successful build is the
|
||||
check that the simulation stays independent of the engine. Tools and test harnesses reference this project. -->
|
||||
<PropertyGroup>
|
||||
<!-- Unity compiles ServerShared against .NET Standard 2.1; newer targets also impose C# 11 ref-safety rules the vendored MessagePack predates -->
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<Nullable>disable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
<!-- UniRx's own switch for building outside Unity -->
|
||||
<DefineConstants>$(DefineConstants);UniRxLibrary</DefineConstants>
|
||||
<!-- Existing code warnings; the build is a Unity-independence check, not a lint pass -->
|
||||
<NoWarn>$(NoWarn);CS0108;CS0114;CS0162;CS0168;CS0169;CS0219;CS0414;CS0618;CS0649;CS8321;CS8981;SYSLIB0021</NoWarn>
|
||||
<Assets>$(MSBuildThisFileDirectory)..\Assets\</Assets>
|
||||
<!-- Unity.Mathematics ships only as a Unity package; its sources come from the package cache Unity resolved -->
|
||||
<MathematicsSource>$(MSBuildThisFileDirectory)..\Library\PackageCache\com.unity.mathematics@*\Unity.Mathematics\</MathematicsSource>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(Assets)Scripts\ServerShared\**\*.cs" />
|
||||
<Compile Include="$(Assets)Plugins\MessagePack\**\*.cs" Exclude="$(Assets)Plugins\MessagePack\Unity\**" />
|
||||
<Compile Include="$(Assets)Plugins\UniRx\Scripts\**\*.cs" Exclude="$(Assets)Plugins\UniRx\Scripts\UnityEngineBridge\**;$(Assets)Plugins\UniRx\Scripts\UnityWinRTBridge\**;$(Assets)Plugins\UniRx\Scripts\InternalUtil\MicroCoroutine.cs" />
|
||||
<!-- The reactive collections live in UniRx's Unity bridge but fence their Unity parts behind UniRxLibrary -->
|
||||
<Compile Include="$(Assets)Plugins\UniRx\Scripts\UnityEngineBridge\ReactiveProperty.cs;$(Assets)Plugins\UniRx\Scripts\UnityEngineBridge\ReactiveCollection.cs;$(Assets)Plugins\UniRx\Scripts\UnityEngineBridge\ReactiveDictionary.cs" />
|
||||
<Compile Include="$(Assets)Plugins\Ink\**\*.cs" />
|
||||
<Compile Include="$(MathematicsSource)**\*.cs" Exclude="$(MathematicsSource)math_unity_conversion.cs;$(MathematicsSource)PropertyAttributes.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<!-- Bundled by Unity; .NET Standard 2.1 lacks it -->
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -59,9 +59,12 @@ AI share it, so AI accuracy is no longer superhuman by construction.
|
|||
pickup (`ShieldManager`), `TractorBeam`, `Mine`. Not blockers.
|
||||
|
||||
**Invariant: game simulation runs independently of Unity.** `ServerShared`
|
||||
enforces this at compile time (`Aetheria.Shared.Unity.asmdef` sets
|
||||
`noEngineReferences`), but Unity-owned hit resolution breaks it behaviorally:
|
||||
the simulation compiles without Unity yet cannot resolve combat without it.
|
||||
cannot reference UnityEngine (`Aetheria.Shared.Unity.asmdef` sets
|
||||
`noEngineReferences`), and `Aetheria.Shared/Aetheria.Shared.csproj` builds it
|
||||
from source with the plain .NET SDK, so a clean headless build is the check.
|
||||
Tools (`tools/AetherDb`) and future test harnesses reference that project.
|
||||
Unity-owned hit resolution still breaks the invariant behaviorally: the
|
||||
simulation builds without Unity yet cannot resolve combat without it.
|
||||
That was a velocity compromise. Moving hit authority into fire control
|
||||
restores the invariant, and lets the planner and a balance harness simulate
|
||||
combat.
|
||||
|
|
@ -95,3 +98,9 @@ Economy simulation, hauling, mining yield, crafting/blueprints, reputation
|
|||
changes, story placement, multiplayer and `Economy.Server`, a headless
|
||||
server deployment, and the CultMesh/daemon rebuild (parked in
|
||||
`F:\Projects\AetheriaEve`).
|
||||
|
||||
Post-ship direction for items: generic item classes (docking bays, cargo
|
||||
bays) become faction-neutral blueprints that branded manufacturing runs
|
||||
reference, so no faction's absence from a galaxy can remove a required item
|
||||
class. Until then, database variety has to guarantee it; `LoadoutGenerator`
|
||||
logs whenever a required item falls back to an unavailable manufacturer.
|
||||
|
|
|
|||
37
tools/AetherDb/AetherDb.cs
Normal file
37
tools/AetherDb/AetherDb.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
// Opens GameData/AetherDB.msgpack through the game's own CultCache and data types, for inspection and editing scripts.
|
||||
// Close the editor's Database Tools before saving from a script, or its next Save will overwrite the script's changes.
|
||||
public sealed class AetherDb
|
||||
{
|
||||
public string Root { get; }
|
||||
public CultCache Cache { get; }
|
||||
private readonly SingleFileMessagePackBackingStore _store;
|
||||
|
||||
private AetherDb(string root)
|
||||
{
|
||||
Root = root;
|
||||
RegisterResolver.Register();
|
||||
var gameData = Path.Combine(root, "GameData");
|
||||
_store = new SingleFileMessagePackBackingStore(Path.Combine(gameData, "AetherDB.msgpack"));
|
||||
Cache = new CultCache();
|
||||
Cache.AddBackingStore(_store);
|
||||
Cache.AddBackingStore(new MultiFileMessagePackBackingStore(gameData), typeof(NameFile));
|
||||
Cache.PullAllBackingStores();
|
||||
}
|
||||
|
||||
// With no root given, walks up from the working directory to the repository
|
||||
public static AetherDb Open(string root = null) => new AetherDb(root ?? FindRoot());
|
||||
|
||||
// Writes every entry back to AetherDB.msgpack, as the editor's Save button does
|
||||
public void Save() => _store.PushAll();
|
||||
|
||||
private static string FindRoot()
|
||||
{
|
||||
for (var dir = new DirectoryInfo(Environment.CurrentDirectory); dir != null; dir = dir.Parent)
|
||||
if (File.Exists(Path.Combine(dir.FullName, "GameData", "AetherDB.msgpack")))
|
||||
return dir.FullName;
|
||||
throw new DirectoryNotFoundException("Run from inside the Aetheria repository.");
|
||||
}
|
||||
}
|
||||
14
tools/AetherDb/Directory.Build.props
Normal file
14
tools/AetherDb/Directory.Build.props
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project>
|
||||
<!-- Applies to every script under tools/AetherDb. Scripts are file-based programs: pass a script path to dotnet run
|
||||
with its file option. They load game data through the headless Aetheria.Shared build of ServerShared. -->
|
||||
<PropertyGroup>
|
||||
<Nullable>disable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<!-- File-based programs default to AOT, which disables the dynamic code MessagePack's resolvers generate -->
|
||||
<PublishAot>false</PublishAot>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)AetherDb.cs" />
|
||||
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\Aetheria.Shared\Aetheria.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
22
tools/AetherDb/scripts/station-fit.cs
Normal file
22
tools/AetherDb/scripts/station-fit.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Checks that some docking bay fits every station hull, which LoadoutGenerator.GenerateStationLoadout requires.
|
||||
// Exits with the number of station hulls that cannot take any docking bay.
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
var db = AetherDb.Open();
|
||||
var bays = db.Cache.GetAll<DockingBayData>().ToArray();
|
||||
var failures = 0;
|
||||
foreach (var hull in db.Cache.GetAll<HullData>().Where(h => h.HullType == HullType.Station))
|
||||
{
|
||||
// Hardpoint gear is equipped before the docking bay, so the worst case leaves only the non-hardpoint interior free
|
||||
var worstCase = new Shape(hull.Shape.Width, hull.Shape.Height);
|
||||
foreach (var v in hull.InteriorCells.Coordinates) worstCase[v] = true;
|
||||
foreach (var hardpoint in hull.Hardpoints)
|
||||
foreach (var v in hardpoint.Shape.Coordinates)
|
||||
worstCase[hardpoint.Position + v] = false;
|
||||
|
||||
var fitting = bays.Where(b => b.Shape.FitsWithin(worstCase, out _, out _)).Select(b => b.Name).ToArray();
|
||||
if (fitting.Length == 0) failures++;
|
||||
Console.WriteLine($"{hull.Name}: {(fitting.Length == 0 ? "NO docking bay fits" : string.Join(", ", fitting))}");
|
||||
}
|
||||
return failures;
|
||||
Loading…
Reference in a new issue