Editor/Output/ArchBuildGate.cs

Utility that decides whether a given architectural scope (building/road) should be skipped during a build. It computes a scope key using ArchLayerHash, records keys for each queried scope, and compares against a provided standing map and refused set to determine skips.

Reflection
using System.Collections.Generic;

namespace Sunless.Architecture;

// Which scopes this build may leave alone entirely - not generated, not finished, not touched. A scope is a
// building or a road, keyed through ArchLayerHash: the group it stands in, plus everything that reaches out of
// every group. Nothing here decides what a layer's identity IS; it only asks.
//
// Absent, every scope builds - which is what a cold build, a designer stage and a preview all want.
public sealed class ArchBuildGate
{
	readonly Dictionary<int, ulong> standing;
	readonly IReadOnlySet<int> refused;
	readonly ArchPlan plan;
	readonly ulong wide;

	public ArchBuildGate( ArchPlan plan, ArchKit kit, int terrain, Dictionary<int, ulong> standing, IReadOnlySet<int> refused )
	{
		this.plan = plan;
		this.standing = standing;
		this.refused = refused;

		wide = ArchLayerHash.Wide( plan, kit, terrain );
	}

	public Dictionary<int, ulong> Keys { get; } = new();

	// Asked once per scope, and it RECORDS as it answers - the key it just computed is what the next build
	// compares against, so a scope can never be skipped twice off one stale reading.
	public bool Skips( int itemId )
	{
		var key = ArchLayerHash.Scope( wide, plan, itemId );

		Keys[itemId] = key;

		if ( refused is not null && refused.Contains( itemId ) )
		{
			return false;
		}

		return standing is not null && standing.TryGetValue( itemId, out var held ) && held == key;
	}
}