Continue refuses a run whose equipment no longer fits its hull's edited layout
A mod package edited in place keeps its hull key, so RequireDesigns passed while saved gear could sit outside the new hardpoints or interior cells and be dropped on load. RequireLayouts applies the equip rules (HardpointData.TakesAt, interior cells for tools) to each saved entity and names the changed hulls. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
db6bda1655
commit
c6a3bee879
2 changed files with 71 additions and 1 deletions
|
|
@ -158,7 +158,7 @@ public static class RunSave
|
|||
var named = designs.Where(key => key.IsSet()).Distinct()
|
||||
.Where(key => cache.Get<ItemData>(key) == null)
|
||||
.Select(key => key.Value).OrderBy(key => key, StringComparer.Ordinal).ToArray();
|
||||
if (named.Length == 0) return;
|
||||
if (named.Length == 0) { RequireLayouts(cache, game); return; }
|
||||
const string modHull = "mod-hull:";
|
||||
var mods = named.Where(key => key.StartsWith(modHull, StringComparison.Ordinal)).Select(key => key.Substring(modHull.Length)).ToArray();
|
||||
var others = named.Where(key => !key.StartsWith(modHull, StringComparison.Ordinal)).ToArray();
|
||||
|
|
@ -168,6 +168,35 @@ public static class RunSave
|
|||
". Reinstall them, or start a new game.");
|
||||
}
|
||||
|
||||
// Continue's second gate: a hull's cells or hardpoints edited under a saved run must still hold what the run
|
||||
// equipped on it (a package edited in place keeps its key, so the design check above passes). Each saved piece of
|
||||
// gear must sit where equipping would accept it on the hull as the catalog holds it now, by the same rules
|
||||
// (HardpointData.TakesAt for hardpoint gear, interior cells for tools); occupancy is not rechecked, the save
|
||||
// carries only what equipping admitted.
|
||||
private static void RequireLayouts(CultCache cache, SavedGame game)
|
||||
{
|
||||
var moved = new SortedSet<string>(StringComparer.Ordinal);
|
||||
void Check(EntityPack pack)
|
||||
{
|
||||
if (pack.Hull.Data.Key.IsSet() && cache.Get<ItemData>(pack.Hull.Data.Key) is HullData hull)
|
||||
foreach (var (position, item) in pack.Equipment.Concat(pack.CargoBays).Concat(pack.DockingBays))
|
||||
{
|
||||
if (!item.Data.Key.IsSet() || !(cache.Get<ItemData>(item.Data.Key) is EquippableItemData design)) continue;
|
||||
var fits = design.HardpointType == HardpointType.Tool
|
||||
? design.Shape.Coordinates.All(cell => hull.InteriorCells[position + design.Shape.Rotate(cell, item.Rotation)])
|
||||
: hull.Hardpoints.Any(hardpoint => hardpoint.TakesAt(design, position - hardpoint.Position));
|
||||
if (!fits) moved.Add(hull.Name);
|
||||
}
|
||||
foreach (var child in pack.Children) Check(child);
|
||||
}
|
||||
foreach (var zoneRef in game.Zones ?? Array.Empty<CultRecordRef<SavedZone>>())
|
||||
foreach (var pack in cache.Get(zoneRef).Contents?.Entities ?? new List<EntityPack>())
|
||||
Check(pack);
|
||||
if (moved.Count > 0)
|
||||
throw new InvalidOperationException("This run's equipment no longer fits its hulls' layouts; changed hulls: " +
|
||||
string.Join(", ", moved) + ". Restore the earlier version of the mod, or start a new game.");
|
||||
}
|
||||
|
||||
private static InvalidOperationException MalformedSave(string where) =>
|
||||
new InvalidOperationException($"This run's save is malformed: {where}. Start a new game.");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue