Editor/Layers/ArchLayerOrder.cs

Utility that decides layer ordering for architecture operations. It determines if one layer operation precedes another based on explicit recorded Order within a shared parent, falling back to monotonic ItemId. It also decides whether an operation applies to a given standing layer (including anonymous host 0).

Reflection
using System.Collections.Generic;
using System.Linq;

namespace Sunless.Architecture;

// WHICH OPERATION HAPPENS FIRST - asked here and nowhere else, because the stack is an ordered operation
// stack and every operation in it obeys the same order. A part standing when a later operation runs is
// subject to it; a part added afterwards is not. Carve a zone and then hang slats in it and the slats are
// whole; hang the slats and then carve over them and the carve takes them.
//
// The answer is the explicit stack position where the author has set one - that is what dragging a row in
// the stack writes - and otherwise the order the two were authored in, which the monotonic id already
// records. Nothing else may re-derive this: a second opinion about order is a part that is carved in the
// generator and whole in the preview.
public static class ArchLayerOrder
{
	public static bool Precedes( ArchPlan plan, int itemId, int otherId )
	{
		if ( itemId == 0 || otherId == 0 || itemId == otherId )
		{
			return false;
		}

		var mine = Record( plan, itemId );
		var theirs = Record( plan, otherId );

		if ( mine is not null && theirs is not null && mine.ParentId == theirs.ParentId && mine.Order != theirs.Order )
		{
			return mine.Order < theirs.Order;
		}

		return itemId < otherId;
	}

	// The operations a host is subject to: the ones authored after it. A host of 0 is anonymous - a derived
	// slab with no layer of its own - and everything reaches it, which is how the generator behaved before
	// any of this was ordered.
	public static bool Applies( ArchPlan plan, int operationId, int standingId )
	{
		return standingId == 0 || operationId == 0 || Precedes( plan, standingId, operationId );
	}

	static ArchLayerRecord Record( ArchPlan plan, int itemId )
	{
		if ( ArchBuildMemo.Current is { } memo )
		{
			return memo.Records.TryGetValue( itemId, out var held ) ? held : null;
		}

		return plan?.Layers?.FirstOrDefault( record => record.ItemId == itemId );
	}
}