namespace NeonSprawl.Server.Game.Gathering;
/// Registry-backed lazy init and atomic depletion commits for world node instances (NEO-61).
public static class ResourceNodeInstanceOperations
{
///
/// Decrements remaining gathers by one after lazy-init from catalog maxGathers. Interact wiring (NEO-63)
/// maps to denied interact responses.
///
public static ResourceNodeInstanceMutationOutcome TryCommitSuccessfulGatherDecrement(
string interactableId,
IResourceNodeDefinitionRegistry registry,
IResourceNodeInstanceStore store)
{
var key = ResourceNodeInstanceIds.Normalize(interactableId);
if (key.Length == 0 || !registry.TryGetDefinition(key, out var definition))
{
return new ResourceNodeInstanceMutationOutcome(
ResourceNodeInstanceMutationKind.Denied,
ResourceNodeInstanceReasonCodes.UnknownNode,
null);
}
if (!store.TryGetRemainingGathers(key, out _))
{
if (!store.TryEnsureInitialized(key, definition.MaxGathers))
{
throw new InvalidOperationException(
$"Failed to initialize resource node instance '{key}' with maxGathers {definition.MaxGathers}.");
}
}
if (store.TryDecrementRemainingGathers(key, out _, out var remaining))
{
return new ResourceNodeInstanceMutationOutcome(
ResourceNodeInstanceMutationKind.Applied,
null,
new ResourceNodeInstanceSnapshot(key, remaining));
}
if (!store.TryGetRemainingGathers(key, out var current))
{
current = new ResourceNodeInstanceSnapshot(key, 0);
}
return new ResourceNodeInstanceMutationOutcome(
ResourceNodeInstanceMutationKind.Denied,
ResourceNodeInstanceReasonCodes.NodeDepleted,
current);
}
}