public partial class ItemManager : Node { public Dictionary TrackedItems { get; } = []; public override void _Ready() { var items = GetParent().FindChildren("*", "res://objects/Item.cs", owned: false).Cast(); foreach (var item in items) Add(item); } public void Add(Item item) { if (item.Manager != null) throw new ArgumentException( $"Item '{item.GetPath()}' is already part of another scene"); // Generate a random, unused id for this item. uint id; do { id = Randi(); } while (TrackedItems.ContainsKey(id)); TrackedItems.Add(id, item); item.Manager = this; item.TrackingId = id; } public void Remove(Item item) { if (item.Manager != this) throw new ArgumentException( $"Item '{item.GetPath()}' is not part of this scene"); TrackedItems.Remove(item.TrackingId); item.Manager = null; item.TrackingId = 0; } // FIXME: This should be fixed in 4.3 and thus not required anymore? // https://github.com/godotengine/godot/issues/85883 internal enum RequestFunc { RequestPickup, RequestPlace, RequestThrow } internal enum AcceptFunc { AcceptPickup, AcceptPlace, AcceptThrow } [Rpc(RpcMode.AnyPeer)] internal void RelayRequest(NodePath itemPath, RequestFunc func, Godot.Collections.Array args) { var item = this.GetNodeOrThrow(itemPath); var callable = new Callable(item, func.ToString()); callable.Call(args.ToArray()); } [Rpc(CallLocal = true)] internal void RelayAccept(NodePath itemPath, AcceptFunc func, Godot.Collections.Array args) { var item = this.GetNodeOrThrow(itemPath); if (GetMultiplayerAuthority() != item.GetMultiplayerAuthority()) throw new InvalidOperationException( $"Item {item.GetPath()} not owned by correct player"); var callable = new Callable(item, func.ToString()); callable.Call(args.ToArray()); } }