From c1be1499ee8777954a643cd412ff5728b879ab18 Mon Sep 17 00:00:00 2001 From: Madpeter <57852827+Madpeterz@users.noreply.github.com> Date: Thu, 15 May 2025 14:23:47 +0100 Subject: [PATCH] fix ReturnAllObjectsOnParcel --- SecondBotEvents/Commands/ParcelCommands.cs | 194 +++++++++++++-------- SecondBotEvents/EventsSecondBot.cs | 2 +- 2 files changed, 124 insertions(+), 72 deletions(-) diff --git a/SecondBotEvents/Commands/ParcelCommands.cs b/SecondBotEvents/Commands/ParcelCommands.cs index 11a75df..3f244f8 100644 --- a/SecondBotEvents/Commands/ParcelCommands.cs +++ b/SecondBotEvents/Commands/ParcelCommands.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using System.Threading.Tasks; using static OpenMetaverse.DirectoryManager; using static OpenMetaverse.ParcelManager; using static OpenMetaverse.Stats.UtilizationStatistics; @@ -597,6 +598,128 @@ namespace SecondBotEvents.Commands } + [About("Returns all objects on a parcel owned by selected avatar")] + [ReturnHintsFailure("Error not in a sim")] + [ReturnHintsFailure("Parcel data not ready")] + [ReturnHintsFailure("Land is not group owned and im not the owner")] + [ReturnHintsFailure("I do not have access to the group")] + [ReturnHintsFailure("No objects found to return")] + [ReturnHintsFailure("Timeout waiting for object owners reply")] + [ReturnHintsFailure("Invaild avatar")] + [ReturnHints("ok")] + [ArgHints("avatar", "uuid of the avatar or Firstname Lastname")] + public object ReturnAllObjectsOnParcelByOwner(string avatar) + { + KeyValuePair tests = SetupCurrentParcel(); + if (tests.Key == false) + { + return Failure(tests.Value); + } + ProcessAvatar(avatar); + if (avataruuid == UUID.Zero) + { + return Failure("Invaild avatar", [avatar]); + } + return ReturnAllObjectsOnParcelReal(avataruuid); + } + + [About("Returns all objects on a parcel")] + [ReturnHintsFailure("Error not in a sim")] + [ReturnHintsFailure("Parcel data not ready")] + [ReturnHintsFailure("Land is not group owned and im not the owner")] + [ReturnHintsFailure("I do not have access to the group")] + [ReturnHintsFailure("No objects found to return")] + [ReturnHintsFailure("Timeout waiting for object owners reply")] + [ReturnHints("ok")] + public object ReturnAllObjectsOnParcel() + { + KeyValuePair tests = SetupCurrentParcel(); + if (tests.Key == false) + { + return Failure(tests.Value); + } + return ReturnAllObjectsOnParcelReal(UUID.Zero); + } + + protected object ReturnAllObjectsOnParcelReal(UUID filter,bool repeat = false) + { + if (targetparcel.OwnerID != GetClient().Self.AgentID) + { + // im not the owner of the parcel + if (targetparcel.GroupID == UUID.Zero) + { + // the parcel is not group owned + return Failure("Land is not group owned and im not the owner"); + } + if (targetparcel.GroupID != GetClient().Self.ActiveGroup) + { + if (repeat == true) + { + return Failure("I do not have access to the group"); + } + GetClient().Groups.ActivateGroup(targetparcel.GroupID); + return ReturnAllObjectsOnParcelReal(filter,true); + } + } + var ownersList = new List(); + using (var waitHandle = new AutoResetEvent(false)) + { + EventHandler handler = null; + handler = (sender, e) => + { + // Unsubscribe immediately to avoid leaks + GetClient().Parcels.ParcelObjectOwnersReply -= handler; + + foreach (ParcelPrimOwners A in e.PrimOwners) + { + if (A.OwnerID == UUID.Zero) + { + // Skip if the owner is zero + continue; + } + if (ownersList.Contains(A.OwnerID)) + { + // Skip if the owner is already in the list + continue; + } + if(filter != UUID.Zero) + { + if (filter == A.OwnerID) + { + // Skip if the owner is not the filter target + continue; + } + } + ownersList.Add(A.OwnerID); + } + waitHandle.Set(); + }; + + GetClient().Parcels.ParcelObjectOwnersReply += handler; + GetClient().Parcels.RequestObjectOwners(GetClient().Network.CurrentSim, targetparcel.LocalID); + + // Wait for the event to be signaled, with a timeout to avoid deadlock + if (!waitHandle.WaitOne(13000)) // 13 seconds timeout + { + GetClient().Parcels.ParcelObjectOwnersReply -= handler; + return Failure("Timeout waiting for object owners reply"); + } + } + if (ownersList.Count == 0) + { + return Failure("No objects found to return"); + } + GetClient().Parcels.ReturnObjects( + GetClient().Network.CurrentSim, + targetparcel.LocalID, + ObjectReturnType.List, + ownersList + ); + + return BasicReply("ok"); + } + + [About("Updates the current parcels name")] [ReturnHints("true|false")] [ReturnHintsFailure("Error not in a sim")] @@ -674,77 +797,6 @@ namespace SecondBotEvents.Commands return BasicReply("Applying perms", [escapedflagdata]); } - [About("Returns all objects from the current parcel for the selected avatar")] - [ReturnHints("ok")] - [ReturnHintsFailure("Error not in a sim")] - [ReturnHintsFailure("Parcel data not ready")] - [ReturnHintsFailure("Invaild avatar UUID")] - [ArgHints("avatar", "avatar uuid or Firstname Lastname")] - public object ParcelReturnTargeted(string avatar) - { - KeyValuePair tests = SetupCurrentParcel(); - if (tests.Key == false) - { - return Failure(tests.Value, [avatar]); - } - ProcessAvatar(avatar); - if (avataruuid == UUID.Zero) - { - return Failure("Invaild avatar UUID", [avatar]); - } - GetClient().Parcels.ReturnObjects(GetClient().Network.CurrentSim, targetparcel.LocalID, ObjectReturnType.None, [avataruuid]); - return BasicReply("ok", [avatar]); - } - - [About("Returns all objects from the current parcel for all avatars")] - [ReturnHints("ok")] - [ReturnHintsFailure("Error not in a sim")] - [ReturnHintsFailure("Parcel data not ready")] - public object ParcelReturnAll() - { - KeyValuePair tests = SetupCurrentParcel(); - if (tests.Key == false) - { - return Failure(tests.Value); - } - // Create a blocking event - AutoResetEvent eventWaitHandle = new(false); - - void OnParcelObjectOwnersReply(object sender, ParcelObjectOwnersReplyEventArgs e) - { - // Signal that the event has been handled - eventWaitHandle.Set(); - if(e.Simulator != GetClient().Network.CurrentSim) - { - return; - } - foreach (ParcelPrimOwners A in e.PrimOwners) - { - ParcelReturnTargeted(A.OwnerID.ToString()); - } - } - - try - { - GetClient().Parcels.ParcelObjectOwnersReply += OnParcelObjectOwnersReply; - GetClient().Parcels.RequestObjectOwners(GetClient().Network.CurrentSim, targetparcel.LocalID); - bool eventTriggered = eventWaitHandle.WaitOne(5000); // 5000ms timeout - - if (!eventTriggered) - { - return Failure("Timed out waiting for ParcelObjectOwnersReply"); - } - return BasicReply("processing request"); - } - finally - { - // Ensure the event handler is removed to avoid memory leaks - GetClient().Parcels.ParcelObjectOwnersReply -= OnParcelObjectOwnersReply; - - } - } - - [About("transfers the current parcel ownership to the assigned group")] [ReturnHints("ok")] [ArgHints("group", "The group uuid to assign")] diff --git a/SecondBotEvents/EventsSecondBot.cs b/SecondBotEvents/EventsSecondBot.cs index 91294b2..5e03f2f 100644 --- a/SecondBotEvents/EventsSecondBot.cs +++ b/SecondBotEvents/EventsSecondBot.cs @@ -175,7 +175,7 @@ namespace SecondBotEvents RegisterService("TriggerOnEventService"); RegisterService("RelayService"); RegisterService("ChatGptService"); - RegisterService("RecoveryService"); + //RegisterService("RecoveryService"); RegisterService("SmtpService"); if (BotClient.IsLoaded() == false) {