48 lines
2.0 KiB
C#
48 lines
2.0 KiB
C#
namespace NeonSprawl.Server.Game.Gathering;
|
|
|
|
/// <summary>Registry-backed lazy init and atomic depletion commits for world node instances (NEO-61).</summary>
|
|
public static class ResourceNodeInstanceOperations
|
|
{
|
|
/// <summary>
|
|
/// Decrements remaining gathers by one after lazy-init from catalog <c>maxGathers</c>. Interact wiring (NEO-63)
|
|
/// maps <see cref="ResourceNodeInstanceReasonCodes.NodeDepleted"/> to denied interact responses.
|
|
/// </summary>
|
|
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));
|
|
}
|
|
|
|
store.TryGetRemainingGathers(key, out var current);
|
|
return new ResourceNodeInstanceMutationOutcome(
|
|
ResourceNodeInstanceMutationKind.Denied,
|
|
ResourceNodeInstanceReasonCodes.NodeDepleted,
|
|
current.InteractableId.Length > 0 ? current : new ResourceNodeInstanceSnapshot(key, 0));
|
|
}
|
|
}
|