using System; using System.Collections.Generic; using Game.Features.Interactions.Contracts; using Godot; namespace Game.Features.Interactions.Godot; public partial class InteractionWorldController : Node, IInteractionWorld { public const string RegistryGroup = "interaction_world_registry"; private readonly Dictionary _targets = []; public override void _EnterTree() { AddToGroup(RegistryGroup); } public void RegisterSceneTargets() { foreach (Node node in GetTree().GetNodesInGroup(WorldInteractionController.InteractionGroup)) { if (node is WorldInteractionController target) { Register(target); } } } public void Register(WorldInteractionController target) { if (_targets.TryGetValue(target.Id, out WorldInteractionController existing)) { if (ReferenceEquals(existing, target)) { return; } throw new InvalidOperationException($"Duplicate interaction target id: {target.Id}."); } _targets.Add(target.Id, target); target.RegisterWith(this); } public void Unregister(InteractionTargetId targetId) { _targets.Remove(targetId); } public InteractionResult TryInteract(InteractionRequest request) { if (!_targets.TryGetValue(request.TargetId, out WorldInteractionController target)) { return InteractionResult.Fail(InteractionStatus.TargetNotFound, $"Target {request.TargetId} was not found."); } if (!target.CanInteract) { return InteractionResult.Fail(InteractionStatus.Unavailable, "The target is not currently available."); } return target.Execute(request.PlayerId); } }