|
|
|
public partial class ItemManager : Node
|
|
|
|
{
|
|
|
|
public Dictionary<uint, Item> TrackedItems { get; } = [];
|
|
|
|
|
|
|
|
public override void _Ready()
|
|
|
|
{
|
|
|
|
var items = GetParent().FindChildren("*", "res://objects/Item.cs", owned: false).Cast<Item>();
|
|
|
|
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?
|
|
|
|
// FIXME: Don't actually rely on item path, use its TrackingId.
|
|
|
|
// https://github.com/godotengine/godot/issues/85883
|
|
|
|
|
|
|
|
internal enum RequestFunc { RequestPickup, RequestPlace, RequestThrow }
|
|
|
|
internal enum AcceptFunc { AcceptPickup, AcceptPlace, AcceptThrow }
|
|
|
|
|
|
|
|
[Rpc(RpcMode.AnyPeer, CallLocal = true)]
|
|
|
|
internal void RelayRequest(NodePath itemPath, RequestFunc func, Godot.Collections.Array args)
|
|
|
|
{
|
|
|
|
var item = this.GetNodeOrThrow<Item>(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<Item>(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());
|
|
|
|
}
|
|
|
|
}
|